// glsl / C++ compatible source as interface for FrustrumGrid#if defined(Q_OS_LINUX)#define float_exp2 exp2f#else#define float_exp2 exp2#endif #ifdef __cplusplus# define _MIN glm::min# define _ABS(x) (int)fabsf(x)#else# define _MIN min# define _ABS abs#endif float frustumGrid_depthRampGridToVolume(float ngrid) { // return ngrid; // return sqrt(ngrid); return float_exp2(ngrid) - 1.0f;}float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) { // return nvolume; // return nvolume * nvolume; return log2(nvolume + 1.0f);} vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) { vec3 gridScale = vec3(1.0f) / vec3(dims); vec3 volumePos = pos * gridScale; volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z); return volumePos;} float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) { return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);} vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) { vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims); return gridPos;} vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) { vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z); float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z); vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth); return clipPos;} vec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) { return vec3( (clipPos.x + projection[2][0] * clipPos.w) / projection[0][0], (clipPos.y + projection[2][1] * clipPos.w) / projection[1][1], -clipPos.w //, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2] );} vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) { return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);} float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) { return (-eposZ - rangeNear) / (rangeFar - rangeNear);} vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], epos.y * projection[1][1] + epos.z * projection[2][1], epos.z * projection[2][2] + projection[2][3], -epos.z); vec4 ndcPos = clipPos / clipPos.w; vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear)); return volumePos;} int frustumGrid_numClusters() { return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);} int frustumGrid_clusterToIndex(ivec3 pos) { return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;}ivec3 frustumGrid_indexToCluster(int index) { ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1); int layer = index / summedDims.x; int offsetInLayer = index % summedDims.x; ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer); return clusterPos;} vec3 frustumGrid_clusterPosToEye(vec3 clusterPos) { vec3 cvpos = clusterPos; vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims); vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); return eyePos;} vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) { vec3 cvpos = vec3(clusterPos) + offset; return frustumGrid_clusterPosToEye(cvpos);} int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) { return -2; } if (eyeZ > -frustumGrid.rangeNear) { return -1; } float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar); int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims)); return _MIN(gridZ, frustumGrid.dims.z);} ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { // make sure the frontEyePos is always in the front to eval the grid pos correctly vec3 frontEyePos = eyePos; frontEyePos.z = -_ABS(eyePos.z); vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); gridPos.z = _MIN(gridPos.z, float(frustumGrid.dims.z)); ivec3 igridPos = ivec3(floor(gridPos)); if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { return ivec3(igridPos.x, igridPos.y, - 2); } if (eyePos.z > -frustumGrid.rangeNear) { return ivec3(igridPos.x, igridPos.y, -1); } return igridPos;} int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { return int(eyeDir.x > 0.0f) * (frustumGrid.dims.x + 1) - 1; } float eyeDepth = -eyeDir.z; float nclipDir = eyeDir.x / eyeDepth; float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0]; float volumeDir = 0.5f * (ndcDir + 1.0f); float gridPos = volumeDir * float(frustumGrid.dims.x); return int(gridPos);} int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { return int(eyeDir.y > 0.0f) * (frustumGrid.dims.y + 1) - 1; } float eyeDepth = -eyeDir.z; float nclipDir = eyeDir.y / eyeDepth; float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1]; float volumeDir = 0.5f * (ndcDir + 1.0f); float gridPos = volumeDir * float(frustumGrid.dims.y); return int(gridPos);} ivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) { return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));} vec4 frustumGrid_eyeToWorld(vec4 eyePos) { return frustumGrid.eyeToWorldMat * eyePos;} vec4 frustumGrid_worldToEye(vec4 worldPos) { return frustumGrid.worldToEyeMat * worldPos;} // <@if 1@> // Trigger Scribe include // <@endif@> <!def that !> End C++ compatible
// glsl / C++ compatible source as interface for FrustrumGrid
#if defined(Q_OS_LINUX)
#define float_exp2 exp2f
#else
#define float_exp2 exp2
#endif
#ifdef __cplusplus
# define _MIN glm::min
# define _ABS(x) (int)fabsf(x)
#else
# define _MIN min
# define _ABS abs
#endif
float frustumGrid_depthRampGridToVolume(float ngrid) {
// return ngrid;
// return sqrt(ngrid);
return float_exp2(ngrid) - 1.0f;
}
float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {
// return nvolume;
// return nvolume * nvolume;
return log2(nvolume + 1.0f);
}
vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {
vec3 gridScale = vec3(1.0f) / vec3(dims);
vec3 volumePos = pos * gridScale;
volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);
return volumePos;
}
float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {
return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);
}
vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {
vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);
return gridPos;
}
vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {
vec3 ndcPos = vec3(-1.0f + 2.0f * vpos.x, -1.0f + 2.0f * vpos.y, vpos.z);
float depth = rangeNear * (1.0f - ndcPos.z) + rangeFar * (ndcPos.z);
vec4 clipPos = vec4(ndcPos.x * depth, ndcPos.y * depth, 1.0f, depth);
return clipPos;
}
vec3 frustumGrid_clipToEye(vec4 clipPos, mat4 projection) {
return vec3(
(clipPos.x + projection[2][0] * clipPos.w) / projection[0][0],
(clipPos.y + projection[2][1] * clipPos.w) / projection[1][1],
-clipPos.w
//, (clipPos.z - projection[3][3] * clipPos.w) / projection[3][2]
);
}
vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float rangeFar) {
return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);
}
float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {
return (-eposZ - rangeNear) / (rangeFar - rangeNear);
}
vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {
vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],
epos.y * projection[1][1] + epos.z * projection[2][1],
epos.z * projection[2][2] + projection[2][3],
-epos.z);
vec4 ndcPos = clipPos / clipPos.w;
vec3 volumePos = vec3(0.5f * (ndcPos.x + 1.0f), 0.5f * (ndcPos.y + 1.0f), (clipPos.w - rangeNear) / (rangeFar - rangeNear));
return volumePos;
}
int frustumGrid_numClusters() {
return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);
}
int frustumGrid_clusterToIndex(ivec3 pos) {
return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;
}
ivec3 frustumGrid_indexToCluster(int index) {
ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);
int layer = index / summedDims.x;
int offsetInLayer = index % summedDims.x;
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
return clusterPos;
}
vec3 frustumGrid_clusterPosToEye(vec3 clusterPos) {
vec3 cvpos = clusterPos;
vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims);
vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);
return eyePos;
}
vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {
vec3 cvpos = vec3(clusterPos) + offset;
return frustumGrid_clusterPosToEye(cvpos);
}
int frustumGrid_eyeDepthToClusterLayer(float eyeZ) {
if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {
return -2;
}
if (eyeZ > -frustumGrid.rangeNear) {
return -1;
}
float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);
int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims));
return _MIN(gridZ, frustumGrid.dims.z);
}
ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {
// make sure the frontEyePos is always in the front to eval the grid pos correctly
vec3 frontEyePos = eyePos;
frontEyePos.z = -_ABS(eyePos.z);
vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar);
vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims);
gridPos.z = _MIN(gridPos.z, float(frustumGrid.dims.z));
ivec3 igridPos = ivec3(floor(gridPos));
if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {
return ivec3(igridPos.x, igridPos.y, - 2);
}
if (eyePos.z > -frustumGrid.rangeNear) {
return ivec3(igridPos.x, igridPos.y, -1);
}
return igridPos;
}
int frustumGrid_eyeToClusterDirH(vec3 eyeDir) {
if (eyeDir.z >= 0.0f) {
return int(eyeDir.x > 0.0f) * (frustumGrid.dims.x + 1) - 1;
}
float eyeDepth = -eyeDir.z;
float nclipDir = eyeDir.x / eyeDepth;
float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];
float volumeDir = 0.5f * (ndcDir + 1.0f);
float gridPos = volumeDir * float(frustumGrid.dims.x);
return int(gridPos);
}
int frustumGrid_eyeToClusterDirV(vec3 eyeDir) {
if (eyeDir.z >= 0.0f) {
return int(eyeDir.y > 0.0f) * (frustumGrid.dims.y + 1) - 1;
}
float eyeDepth = -eyeDir.z;
float nclipDir = eyeDir.y / eyeDepth;
float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];
float volumeDir = 0.5f * (ndcDir + 1.0f);
float gridPos = volumeDir * float(frustumGrid.dims.y);
return int(gridPos);
}
ivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {
return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));
}
vec4 frustumGrid_eyeToWorld(vec4 eyePos) {
return frustumGrid.eyeToWorldMat * eyePos;
}
vec4 frustumGrid_worldToEye(vec4 worldPos) {
return frustumGrid.worldToEyeMat * worldPos;
}
// <@if 1@>
// Trigger Scribe include
// <@endif@> <!def that !> End C++ compatible