mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
MOre refinements?
This commit is contained in:
parent
9b94a025fc
commit
a0862820e6
9 changed files with 116 additions and 86 deletions
|
@ -55,17 +55,6 @@ uniform clusterContentBuffer {
|
|||
int _clusterGridContent[16384];
|
||||
};
|
||||
|
||||
int clusterGrid_clusterToIndex(ivec3 pos) {
|
||||
return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;
|
||||
}
|
||||
ivec3 clusterGrid_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;
|
||||
}
|
||||
|
||||
ivec2 clusterGrid_getCluster(int index) {
|
||||
int clusterDesc = _clusterGridTable[index];
|
||||
int numLights = 0xFFFF & (clusterDesc >> 16);
|
||||
|
|
|
@ -1,27 +1,33 @@
|
|||
// glsl / C++ compatible source as interface for FrustrumGrid
|
||||
float frustumGrid_depthRamp(float linear) {
|
||||
// return linear;
|
||||
return linear * linear;
|
||||
float frustumGrid_depthRampGridToVolume(float ngrid) {
|
||||
if (ngrid < 0.0)
|
||||
return ngrid;
|
||||
// return ngrid;
|
||||
// return sqrt(ngrid);
|
||||
return exp2(ngrid) - 1.0;
|
||||
}
|
||||
float frustumGrid_depthRampInverse(float volume) {
|
||||
// return volume;
|
||||
return sqrt(volume);
|
||||
float frustumGrid_depthRampInverseVolumeToGrid(float nvolume) {
|
||||
if (nvolume < 0.0)
|
||||
return nvolume;
|
||||
// return nvolume;
|
||||
// return nvolume * nvolume;
|
||||
return log2(nvolume + 1.0);
|
||||
}
|
||||
|
||||
vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {
|
||||
vec3 gridScale = vec3(1.0, 1.0, 1.0) / vec3(dims);
|
||||
vec3 volumePos = pos * gridScale;
|
||||
volumePos.z = frustumGrid_depthRamp(volumePos.z);
|
||||
volumePos.z = frustumGrid_depthRampGridToVolume(volumePos.z);
|
||||
return volumePos;
|
||||
}
|
||||
|
||||
|
||||
float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {
|
||||
return frustumGrid_depthRampInverse(vposZ) * float(dims.z);
|
||||
return frustumGrid_depthRampInverseVolumeToGrid(vposZ) * float(dims.z);
|
||||
}
|
||||
|
||||
vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {
|
||||
vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims);
|
||||
vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverseVolumeToGrid(vpos.z)) * vec3(dims);
|
||||
return gridPos;
|
||||
}
|
||||
|
||||
|
@ -68,6 +74,21 @@ 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) {
|
||||
if (index <= 0) {
|
||||
return ivec3(0, 0, -1);
|
||||
}
|
||||
index -= 1;
|
||||
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;
|
||||
|
@ -87,7 +108,7 @@ vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {
|
|||
|
||||
int frustumGrid_eyeDepthToClusterLayer(float eyeZ) {
|
||||
if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (eyeZ > -frustumGrid.rangeNear) {
|
||||
|
@ -108,7 +129,7 @@ int frustumGrid_eyeDepthToClusterLayer(float eyeZ) {
|
|||
|
||||
ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {
|
||||
if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {
|
||||
return ivec3(-1);
|
||||
return ivec3(-2);
|
||||
}
|
||||
|
||||
if (eyePos.z > -frustumGrid.rangeNear) {
|
||||
|
|
|
@ -49,18 +49,18 @@ void FrustumGrid::generateGridPlanes(Planes& xPlanes, Planes& yPlanes, Planes& z
|
|||
float centerY = float(dims.y) * 0.5;
|
||||
float centerX = float(dims.x) * 0.5;
|
||||
|
||||
for (int z = 0; z < zPlanes.size(); z++) {
|
||||
for (int z = 0; z < (int) zPlanes.size(); z++) {
|
||||
ivec3 pos(0, 0, z);
|
||||
zPlanes[z] = glm::vec4(0.0f, 0.0f, 1.0f, -frustumGrid_clusterPosToEye(pos, vec3(0.0)).z);
|
||||
}
|
||||
|
||||
for (int x = 0; x < xPlanes.size(); x++) {
|
||||
for (int x = 0; x < (int) xPlanes.size(); x++) {
|
||||
auto slicePos = frustumGrid_clusterPosToEye(glm::vec3((float)x, centerY, 0.0));
|
||||
auto sliceDir = glm::normalize(slicePos);
|
||||
xPlanes[x] = glm::vec4(sliceDir.z, 0.0, -sliceDir.x, 0.0);
|
||||
}
|
||||
|
||||
for (int y = 0; y < yPlanes.size(); y++) {
|
||||
for (int y = 0; y < (int) yPlanes.size(); y++) {
|
||||
auto slicePos = frustumGrid_clusterPosToEye(glm::vec3(centerX, (float)y, 0.0));
|
||||
auto sliceDir = glm::normalize(slicePos);
|
||||
yPlanes[y] = glm::vec4(0.0, sliceDir.z, -sliceDir.y, 0.0);
|
||||
|
@ -177,72 +177,95 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p
|
|||
}
|
||||
|
||||
float distanceToPlane(const glm::vec3& point, const glm::vec4& plane) {
|
||||
return glm::dot(plane, glm::vec4(point.x, point.y, point.z, -1.0));
|
||||
return plane.x * point.x + plane.y * point.y + plane.z * point.z + plane.w;
|
||||
}
|
||||
|
||||
glm::vec4 projectToPlane(glm::vec4& sphere, const glm::vec4& plane) {
|
||||
bool reduceSphereToPlane(const glm::vec4& sphere, const glm::vec4& plane, glm::vec4& reducedSphere) {
|
||||
float distance = distanceToPlane(glm::vec3(sphere), plane);
|
||||
|
||||
if (distance < sphere.w) {
|
||||
return glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance));
|
||||
} else {
|
||||
return sphere;
|
||||
if (abs(distance) <= sphere.w) {
|
||||
reducedSphere = glm::vec4(sphere.x - distance * plane.x, sphere.y - distance * plane.y, sphere.z - distance * plane.z, sqrt(sphere.w * sphere.w - distance * distance));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool scanLightVolume(const FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius,
|
||||
uint32_t& numClustersTouched, uint32_t maxNumIndices, std::vector< std::vector<LightClusters::LightIndex>>& clusterGrid) {
|
||||
uint32_t scanLightVolumeBox(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius,
|
||||
std::vector< std::vector<LightClusters::LightIndex>>& clusterGrid) {
|
||||
glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y);
|
||||
uint32_t numClustersTouched = 0;
|
||||
|
||||
for (auto z = zMin; (z <= zMax); z++) {
|
||||
for (auto y = yMin; (y <= yMax); y++) {
|
||||
for (auto x = xMin; (x <= xMax); x++) {
|
||||
auto index = 1 + x + gridPosToOffset.y * y + gridPosToOffset.z * z;
|
||||
clusterGrid[index].emplace_back(lightId);
|
||||
numClustersTouched++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numClustersTouched;
|
||||
}
|
||||
|
||||
uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes planes[3], int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius,
|
||||
std::vector< std::vector<LightClusters::LightIndex>>& clusterGrid) {
|
||||
glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y);
|
||||
uint32_t numClustersTouched = 0;
|
||||
const auto& xPlanes = planes[0];
|
||||
const auto& yPlanes = planes[1];
|
||||
const auto& zPlanes = planes[2];
|
||||
|
||||
int center_z = (zMax + zMin) >> 1;
|
||||
int center_z = grid.frustumGrid_eyeDepthToClusterLayer(eyePosRadius.z);
|
||||
int center_y = (yMax + yMin) >> 1;
|
||||
bool hasBudget = true;
|
||||
for (auto z = zMin; (z <= zMax) && hasBudget; z++) {
|
||||
for (auto z = zMin; (z <= zMax); z++) {
|
||||
auto zSphere = eyePosRadius;
|
||||
if (z != center_z) {
|
||||
auto& plane = (z < center_z) ? zPlanes[z + 1] : -zPlanes[z];
|
||||
zSphere = projectToPlane(zSphere, plane);
|
||||
if (!reduceSphereToPlane(zSphere, plane, zSphere)) {
|
||||
// pass this slice!
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (auto y = yMin; (y <= yMax) && hasBudget; y++) {
|
||||
for (auto y = yMin; (y <= yMax); y++) {
|
||||
auto ySphere = zSphere;
|
||||
if (y != center_y) {
|
||||
auto& plane = (y < center_y) ? yPlanes[y + 1] : -yPlanes[y];
|
||||
ySphere = projectToPlane(ySphere, plane);
|
||||
if (!reduceSphereToPlane(ySphere, plane, ySphere)) {
|
||||
// pass this slice!
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 spherePoint(ySphere);
|
||||
|
||||
auto x = xMin;
|
||||
for (; (x < xMax); ++x) {
|
||||
auto& plane = xPlanes[x + 1];
|
||||
auto testDistance = glm::dot(plane, glm::vec4(ySphere.x, ySphere.y, ySphere.z, -1.0)) + ySphere.w;
|
||||
if (testDistance >= 0.0f ) {
|
||||
auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w;
|
||||
if (testDistance >= 0.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto xs = xMax;
|
||||
for (; (xs >= x); --xs) {
|
||||
auto& plane = -xPlanes[xs];
|
||||
auto testDistance = glm::dot(plane, glm::vec4(ySphere.x, ySphere.y, ySphere.z, -1.0)) + ySphere.w;
|
||||
auto testDistance = distanceToPlane(spherePoint, plane) + ySphere.w;
|
||||
if (testDistance >= 0.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; (x <= xs) && hasBudget; x++) {
|
||||
auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z;
|
||||
for (; (x <= xs); x++) {
|
||||
auto index = grid.frustumGrid_clusterToIndex(ivec3(x, y, z));
|
||||
clusterGrid[index].emplace_back(lightId);
|
||||
numClustersTouched++;
|
||||
if (numClustersTouched >= maxNumIndices) {
|
||||
hasBudget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasBudget;
|
||||
return numClustersTouched;
|
||||
}
|
||||
|
||||
void LightClusters::updateClusters() {
|
||||
|
@ -284,7 +307,18 @@ void LightClusters::updateClusters() {
|
|||
int zMin = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMin);
|
||||
int zMax = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMax);
|
||||
// That should never happen
|
||||
if (zMin == -1 && zMax == -1) {
|
||||
if (zMin == -2 && zMax == -2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Firt slice volume ?
|
||||
/* if (zMin == -1) {
|
||||
clusterGrid[0].emplace_back(lightId);
|
||||
numClusterTouched++;
|
||||
} */
|
||||
|
||||
// Stop there with this light if zmax is in near range
|
||||
if (zMax == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -361,37 +395,31 @@ void LightClusters::updateClusters() {
|
|||
}
|
||||
|
||||
// now voxelize
|
||||
bool hasBudget = scanLightVolume(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid);
|
||||
|
||||
/* bool hasBudget = true;
|
||||
for (auto z = zMin; (z <= zMax) && hasBudget; z++) {
|
||||
for (auto y = yMin; (y <= yMax) && hasBudget; y++) {
|
||||
for (auto x = xMin; (x <= xMax) && hasBudget; x++) {
|
||||
auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z;
|
||||
clusterGrid[index].emplace_back(lightId);
|
||||
numClusterTouched++;
|
||||
if (numClusterTouched >= maxNumIndices) {
|
||||
hasBudget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!hasBudget) {
|
||||
break;
|
||||
}
|
||||
numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid);
|
||||
}
|
||||
|
||||
// Lights have been gathered now reexpress in terms of 2 sequential buffers
|
||||
|
||||
// Start filling from near to far and stops if it overflows
|
||||
bool checkBudget = false;
|
||||
if (numClusterTouched > maxNumIndices) {
|
||||
checkBudget = true;
|
||||
}
|
||||
uint16_t indexOffset = 0;
|
||||
for (int i = 0; i < clusterGrid.size(); i++) {
|
||||
auto& cluster = clusterGrid[i];
|
||||
uint16_t numLights = ((uint16_t)cluster.size());
|
||||
uint16_t offset = indexOffset;
|
||||
|
||||
// Check for overflow
|
||||
if (checkBudget) {
|
||||
if (indexOffset + numLights > maxNumIndices) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_clusterGrid[i] = (uint32_t)((numLights << 16) | offset);
|
||||
|
||||
|
||||
if (numLights) {
|
||||
memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightIndex));
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
LightStage::LightIndices _visibleLightIndices;
|
||||
gpu::BufferView _lightIndicesBuffer;
|
||||
|
||||
uint32_t _numClusters { 0 };
|
||||
int32_t _numClusters { 0 };
|
||||
|
||||
const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
|
||||
const LightID INVALID_LIGHT { LightStage::INVALID_INDEX };
|
||||
|
@ -124,9 +124,9 @@ public:
|
|||
float rangeNear{ 1.0f };
|
||||
float rangeFar{ 512.0f };
|
||||
|
||||
int dimX { 8 };
|
||||
int dimY { 8 };
|
||||
int dimZ { 12 };
|
||||
int dimX { 16 };
|
||||
int dimY { 16 };
|
||||
int dimZ { 16 };
|
||||
|
||||
bool freeze{ false };
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ void main(void) {
|
|||
|
||||
float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0);
|
||||
|
||||
ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID);
|
||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
||||
|
||||
float boxScale = 0.99;
|
||||
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz);
|
||||
|
|
|
@ -37,7 +37,7 @@ void main(void) {
|
|||
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
|
||||
|
||||
|
||||
ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos));
|
||||
ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
|
||||
int numLights = cluster.x;
|
||||
float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0);
|
||||
|
||||
|
|
|
@ -53,15 +53,7 @@ void main(void) {
|
|||
);
|
||||
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
|
||||
|
||||
ivec3 dims = frustumGrid.dims.xyz;
|
||||
|
||||
ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1);
|
||||
|
||||
int layer = gl_InstanceID / summedDims.x;
|
||||
int offsetInLayer = gl_InstanceID % summedDims.x;
|
||||
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
|
||||
|
||||
|
||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
||||
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
|
||||
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void main(void) {
|
|||
ivec2 cluster = clusterGrid_getCluster(gl_InstanceID);
|
||||
int numLights = cluster.x;
|
||||
|
||||
ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID);
|
||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
||||
|
||||
|
||||
float boxScale = 1.0;
|
||||
|
|
|
@ -61,7 +61,7 @@ void main(void) {
|
|||
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
|
||||
|
||||
|
||||
ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos));
|
||||
ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
|
||||
int numLights = cluster.x;
|
||||
if (numLights <= 0) {
|
||||
discard;
|
||||
|
|
Loading…
Reference in a new issue