diff --git a/Data/Shaders/VPT/CheckIsosurfaceHit.glsl b/Data/Shaders/VPT/CheckIsosurfaceHit.glsl index 981d65d..eeb9e21 100644 --- a/Data/Shaders/VPT/CheckIsosurfaceHit.glsl +++ b/Data/Shaders/VPT/CheckIsosurfaceHit.glsl @@ -9,7 +9,6 @@ #ifdef CLOSE_ISOSURFACES if (isFirstPointFromOutside) { - // TODO: Normals isFirstPoint = false; lastScalarSign = sign(-parameters.isoValue); } else @@ -42,6 +41,10 @@ firstEvent.hasValue = true; firstEvent.density = parameters.extinction.x; firstEvent.depth = tMax - d + distance(x1, x); +#ifdef CLOSE_ISOSURFACES + firstEvent.normal = surfaceNormalGlobal; + firstEvent.isIsosurface = true; +#endif } if (rayBoxIntersect(parameters.boxMin, parameters.boxMax, x, w, tMin, tMax)) { x += w * tMin; @@ -49,6 +52,9 @@ } } //foundHit = true; +#ifdef CLOSE_ISOSURFACES + isFirstPointFromOutside = false; +#endif break; } diff --git a/Data/Shaders/VPT/Clouds.glsl b/Data/Shaders/VPT/Clouds.glsl index de20d45..e1ad7e7 100644 --- a/Data/Shaders/VPT/Clouds.glsl +++ b/Data/Shaders/VPT/Clouds.glsl @@ -88,7 +88,12 @@ void pathTraceSample(int i, bool onlyFirstEvent, out ScatterEvent firstEvent){ // Get ray direction and volume entry point vec3 x, w; createCameraRay(screenCoord, x, w); - firstEvent = ScatterEvent(false, x, 0.0, w, 0.0, 0.0, 0.0); + firstEvent = ScatterEvent( + false, x, 0.0, w, 0.0, 0.0, 0.0 +#ifdef CLOSE_ISOSURFACES + , vec3(0.0), false +#endif + ); #if defined(USE_ISOSURFACES) || defined(USE_HEADLIGHT) cameraPosition = x; @@ -242,8 +247,15 @@ void pathTraceSample(int i, bool onlyFirstEvent, out ScatterEvent firstEvent){ //imageStore(firstX, imageCoord, vec4(firstEvent.x, firstEvent.pdf_x)); #ifdef WRITE_NORMAL_MAP -#ifdef USE_ISOSURFACES - vec3 diff = -computeGradient((firstEvent.x - parameters.boxMin)/(parameters.boxMax -parameters.boxMin)); +#if defined(CLOSE_ISOSURFACES) + vec3 diff; + if (firstEvent.isIsosurface) { + diff = firstEvent.normal; + } else { + diff = -computeGradient((firstEvent.x - parameters.boxMin) / (parameters.boxMax -parameters.boxMin)); + } +#elif defined(USE_ISOSURFACES) + vec3 diff = -computeGradient((firstEvent.x - parameters.boxMin) / (parameters.boxMax -parameters.boxMin)); #else // !defined(USE_ISOSURFACES) vec3 diff = getCloudFiniteDifference(firstEvent.x); #endif // USE_ISOSURFACES diff --git a/Data/Shaders/VPT/IsosurfaceRendering.glsl b/Data/Shaders/VPT/IsosurfaceRendering.glsl index e614e36..97fd706 100644 --- a/Data/Shaders/VPT/IsosurfaceRendering.glsl +++ b/Data/Shaders/VPT/IsosurfaceRendering.glsl @@ -3,6 +3,9 @@ vec3 isosurfaceRendering(vec3 x, vec3 w, inout ScatterEvent firstEvent) { vec3 weights = vec3(1, 1, 1); float lastScalarSign, currentScalarSign; bool isFirstPoint = true; +#ifdef CLOSE_ISOSURFACES + bool isFirstPointFromOutside = true; +#endif ivec3 voxelGridSize = textureSize(gridImage, 0); vec3 boxDelta = parameters.boxMax - parameters.boxMin; @@ -20,10 +23,17 @@ vec3 isosurfaceRendering(vec3 x, vec3 w, inout ScatterEvent firstEvent) { float scalarValue = sampleCloudIso(xNew); currentScalarSign = sign(scalarValue - parameters.isoValue); +#ifdef CLOSE_ISOSURFACES + if (isFirstPoint) { + isFirstPoint = false; + lastScalarSign = sign(-parameters.isoValue); + } +#else if (isFirstPoint) { isFirstPoint = false; lastScalarSign = currentScalarSign; } +#endif if (lastScalarSign != currentScalarSign) { if (!firstEvent.hasValue) { @@ -41,6 +51,7 @@ vec3 isosurfaceRendering(vec3 x, vec3 w, inout ScatterEvent firstEvent) { break; } + isFirstPointFromOutside = false; x = xNew; d -= t; } @@ -48,7 +59,12 @@ vec3 isosurfaceRendering(vec3 x, vec3 w, inout ScatterEvent firstEvent) { if (foundHit) { vec3 surfaceNormal; - vec3 color = getIsoSurfaceHitDirect(x, w, surfaceNormal); + vec3 color = getIsoSurfaceHitDirect( + x, w, surfaceNormal +#ifdef CLOSE_ISOSURFACES + , isFirstPointFromOutside +#endif + ); weights *= color; x += surfaceNormal * 1e-3; diff --git a/Data/Shaders/VPT/VptUtils.glsl b/Data/Shaders/VPT/VptUtils.glsl index 2eb7b0d..fed7553 100644 --- a/Data/Shaders/VPT/VptUtils.glsl +++ b/Data/Shaders/VPT/VptUtils.glsl @@ -36,6 +36,10 @@ struct ScatterEvent { vec3 w; float pdf_w; float depth; float density; +#ifdef CLOSE_ISOSURFACES + vec3 normal; + bool isIsosurface; +#endif }; @@ -791,6 +795,7 @@ bool rayBoxIntersect(vec3 bMin, vec3 bMax, vec3 P, vec3 D, out float tMin, out f #ifdef CLOSE_ISOSURFACES void rayBoxIntersectionNormal(vec3 bMin, vec3 bMax, vec3 P, vec3 D, inout vec3 surfaceNormal) { + float tMinTest, tMaxTest; D.x = abs(D).x <= 1e-6 ? 1e-6 : D.x; D.y = abs(D).y <= 1e-6 ? 1e-6 : D.y; D.z = abs(D).z <= 1e-6 ? 1e-6 : D.z; @@ -1132,6 +1137,9 @@ float isoSurfaceOpacity = isoSurfaceColorAll.a; #define UNIFORM_SAMPLING //#define USE_MIS // only for specular BRDF sampling +#ifdef CLOSE_ISOSURFACES +vec3 surfaceNormalGlobal; +#endif bool getIsoSurfaceHit( vec3 currentPoint, inout vec3 w, inout vec3 throughput @@ -1170,6 +1178,10 @@ bool getIsoSurfaceHit( surfaceNormal = -surfaceNormal; } +#ifdef CLOSE_ISOSURFACES + surfaceNormalGlobal = surfaceNormal; +#endif + vec3 surfaceTangent; vec3 surfaceBitangent; ComputeDefaultBasis(surfaceNormal, surfaceTangent, surfaceBitangent); @@ -1316,10 +1328,20 @@ bool getIsoSurfaceHit( #include "Lighting.glsl" // Direct illumination -vec3 getIsoSurfaceHitDirect(vec3 currentPoint, vec3 w, inout vec3 surfaceNormal) { +vec3 getIsoSurfaceHitDirect( + vec3 currentPoint, vec3 w, inout vec3 surfaceNormal +#ifdef CLOSE_ISOSURFACES + , bool isFirstPointFromOutside +#endif +) { vec3 texCoords = (currentPoint - parameters.boxMin) / (parameters.boxMax - parameters.boxMin); texCoords = texCoords * (parameters.gridMax - parameters.gridMin) + parameters.gridMin; surfaceNormal = computeGradient(texCoords); // computeGradientLegacy(texCoords); +#ifdef CLOSE_ISOSURFACES + if (isFirstPointFromOutside) { + rayBoxIntersectionNormal(parameters.boxMin, parameters.boxMax, cameraPosition, w, surfaceNormal); + } else +#endif if (dot(cameraPosition - currentPoint, surfaceNormal) < 0.0) { surfaceNormal = -surfaceNormal; } diff --git a/src/PathTracer/VolumetricPathTracingPass.cpp b/src/PathTracer/VolumetricPathTracingPass.cpp index 542c934..bbb3725 100644 --- a/src/PathTracer/VolumetricPathTracingPass.cpp +++ b/src/PathTracer/VolumetricPathTracingPass.cpp @@ -2008,6 +2008,10 @@ void VolumetricPathTracingPass::_render() { uniformData.maxAoDist = maxAoDist; uniformData.numAoSamples = numAoSamples; + uniformData.useClipPlane = int32_t(useClipPlane); + uniformData.clipPlaneNormal = glm::normalize(clipPlaneNormal); + uniformData.clipPlaneDistance = clipPlaneDistance; + // Update BRDF parameters uniformData.subsurface = subsurface; uniformData.metallic = metallic; @@ -2023,9 +2027,6 @@ void VolumetricPathTracingPass::_render() { uniformBuffer->updateData( sizeof(UniformData), &uniformData, renderer->getVkCommandBuffer()); - uniformData.clipPlaneNormal = clipPlaneNormal; - uniformData.clipPlaneDistance = clipPlaneDistance; - if (useGlobalFrameNumber) { frameInfo.globalFrameNumber = globalFrameNumber; } else { @@ -2817,10 +2818,10 @@ bool VolumetricPathTracingPass::renderGuiPropertyEditorNodes(sgl::PropertyEditor setShaderDirty(); optionChanged = true; } - if (useClipPlane && propertyEditor.addSliderFloat3("Clip Plane Normal", &clipPlaneNormal.x, 0.01f, 1.0f)) { + if (useClipPlane && propertyEditor.addSliderFloat3("Clip Plane Normal", &clipPlaneNormal.x, -1.0f, 1.0f)) { optionChanged = true; } - if (useClipPlane && propertyEditor.addSliderFloat("Clip Plane Distance", &clipPlaneDistance, -1.0f, 1.0f)) { + if (useClipPlane && propertyEditor.addSliderFloat("Clip Plane Distance", &clipPlaneDistance, -0.5f, 0.5f)) { optionChanged = true; } propertyEditor.endNode(); diff --git a/src/PathTracer/VolumetricPathTracingPass.hpp b/src/PathTracer/VolumetricPathTracingPass.hpp index 55b86dc..7a3a358 100644 --- a/src/PathTracer/VolumetricPathTracingPass.hpp +++ b/src/PathTracer/VolumetricPathTracingPass.hpp @@ -454,7 +454,7 @@ class VolumetricPathTracingPass : public sgl::vk::ComputePass { int numAoSamples = 4; // Clip Plane - int useClipPlane; + int32_t useClipPlane; glm::vec3 clipPlaneNormal; float clipPlaneDistance;