├── Caustics.cpp ├── Caustics.h ├── Caustics.vcxproj ├── Caustics.vcxproj.filters ├── Caustics.vcxproj.user ├── Data ├── AllocateTilePhoton.cs.hlsl ├── AnalyseTraceResult.cs.hlsl ├── Caustics.ps.hlsl ├── Caustics.rt.hlsl ├── Common.hlsl ├── Composite.ps.hlsl ├── CompositeRT.rt.hlsl ├── GPass.ps.hlsl ├── GenerateRayCountMipmap.cs.hlsl ├── PhotonGather.cs.hlsl ├── PhotonScatter.ps.hlsl ├── PhotonTrace.rt.hlsl ├── ResetDrawArgument.cs.hlsl ├── SmoothPhoton.cs.hlsl ├── SpacialFilter.cs.hlsl ├── TemporalFilter.cs.hlsl ├── UpdateRayDensity.cs.hlsl ├── compile_all.bat ├── dragonDetail.ini ├── far.ini ├── far2.ini ├── fxc.exe ├── gaussian.xcf ├── glass.ini ├── init.ini ├── len.ini └── uniform.xcf ├── Media └── Caustics │ ├── copo.mtl │ ├── copo.obj │ ├── dragon.fbx │ ├── gaussian.png │ ├── glass3.fbx │ ├── glassCup.fbx │ ├── monkey.fbx │ ├── prism.blend1 │ ├── prism.fbx │ ├── quad.blend1 │ ├── quad.mtl │ ├── quad.obj │ ├── ring.fbx │ ├── ring.fscene │ ├── sphere.mtl │ ├── sphere.obj │ └── uniform.png ├── README.md └── ReadmeImage ├── algorithm01.png ├── algorithm02.png ├── algorithm03.png ├── algorithm04.png ├── intro01.gif ├── intro02.png └── intro03.png /Caustics.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #pragma once 29 | #include "Falcor.h" 30 | #include "FalcorExperimental.h" 31 | 32 | #define MAX_CAUSTICS_MAP_SIZE 2048 33 | #define MAX_PHOTON_COUNT 2048*2048 34 | 35 | using namespace Falcor; 36 | 37 | class Caustics : public IRenderer 38 | { 39 | public: 40 | Caustics(); 41 | void onLoad(RenderContext* pRenderContext) override; 42 | void onFrameRender(RenderContext* pRenderContext, const Fbo::SharedPtr& pTargetFbo) override; 43 | void onResizeSwapChain(uint32_t width, uint32_t height) override; 44 | bool onKeyEvent(const KeyboardEvent& keyEvent) override; 45 | bool onMouseEvent(const MouseEvent& mouseEvent) override; 46 | void onGuiRender(Gui* pGui) override; 47 | 48 | private: 49 | // Photon trace 50 | enum TraceType 51 | { 52 | TRACE_FIXED = 0, 53 | TRACE_ADAPTIVE = 1, 54 | TRACE_NONE = 2, 55 | TRACE_ADAPTIVE_RAY_MIP_MAP = 3, 56 | }; 57 | TraceType mTraceType = TRACE_ADAPTIVE_RAY_MIP_MAP; 58 | int mDispatchSize = 64; 59 | int mMaxTraceDepth = 10; 60 | float mEmitSize = 30.0; 61 | float mIntensity = 2.0f; 62 | float mRoughThreshold = 0.1f; 63 | enum AreaType 64 | { 65 | AREA_AVG_SQUARE = 0, 66 | AREA_AVG_LENGTH = 1, 67 | AREA_MAX_SQUARE = 2, 68 | AREA_EXACT = 3 69 | } mAreaType = AREA_AVG_SQUARE; 70 | float mIOROveride = 1.5f; 71 | int mColorPhoton = 0; 72 | int mPhotonIDScale = 50; 73 | float mTraceColorThreshold = 0.0005f; 74 | float mCullColorThreshold = 1.0f; 75 | bool mUpdatePhoton = true; 76 | float mMaxPhotonPixelRadius = 90.0f; 77 | float mSmallPhotonCompressScale = 1.0f; 78 | float mFastPhotonPixelRadius = 19.0f; 79 | float mFastPhotonDrawCount = 0.f; 80 | bool mFastPhotonPath = false; 81 | bool mShrinkColorPayload = true; 82 | bool mShrinkRayDiffPayload = true; 83 | 84 | // Adaptive photon refine 85 | float mNormalThreshold = 0.2f; 86 | float mDistanceThreshold = 10.0f; 87 | float mPlanarThreshold = 2.0f; 88 | float mMinPhotonPixelSize = 15.0f; 89 | float mSmoothWeight = 0.15f; 90 | float mMaxTaskCountPerPixel = 8192; 91 | float mUpdateSpeed = 0.2f; 92 | float mVarianceGain = 0.0f; 93 | float mDerivativeGain = 0.0f; 94 | enum SamplePlacement 95 | { 96 | SAMPLE_PLACEMENT_RANDOM = 0, 97 | SAMPLE_PLACEMENT_GRID = 1 98 | } mSamplePlacement = SAMPLE_PLACEMENT_GRID; 99 | 100 | // smooth photon 101 | bool mMedianFilter = false; 102 | int mMinNeighbourCount = 2; 103 | bool mRemoveIsolatedPhoton = false; 104 | float mPixelLuminanceThreshold = 0.5f; 105 | float trimDirectionThreshold = 0.5f; 106 | 107 | // Photon Scatter 108 | enum ScatterGeometry 109 | { 110 | SCATTER_GEOMETRY_QUAD = 0, 111 | SCATTER_GEOMETRY_SPHERE = 1, 112 | }; 113 | ScatterGeometry mScatterGeometry= SCATTER_GEOMETRY_QUAD; 114 | int mCausticsMapResRatio = 1; 115 | enum DensityEstimation 116 | { 117 | DENSITY_ESTIMATION_SCATTER = 0, 118 | DENSITY_ESTIMATION_GATHER = 1, 119 | DENSITY_ESTIMATION_NONE = 2 120 | } mScatterOrGather = DENSITY_ESTIMATION_SCATTER; 121 | float mSplatSize = 1.1f; 122 | float mKernelPower = 1.0f; 123 | enum PhotonDisplayMode 124 | { 125 | PHOTON_DISPLAY_MODE_KERNEL = 0, 126 | PHOTON_DISPLAY_MODE_SOLID = 1, 127 | PHOTON_DISPLAY_MODE_SHADED = 2, 128 | } mPhotonDisplayMode = PHOTON_DISPLAY_MODE_KERNEL; 129 | enum PhotonMode 130 | { 131 | PHOTON_MODE_ANISOTROPIC = 0, 132 | PHOTON_MODE_ISOTROPIC = 1, 133 | PHOTON_MODE_PHOTON_MESH = 2, 134 | PHOTON_MODE_SCREEN_DOT = 3, 135 | PHOTON_MODE_SCREEN_DOT_WITH_COLOR = 4, 136 | } mPhotonMode = PHOTON_MODE_ANISOTROPIC; 137 | float mScatterNormalThreshold = 0.2f; 138 | float mScatterDistanceThreshold = 10.0f; 139 | float mScatterPlanarThreshold = 2.0f; 140 | float mMaxAnisotropy = 20.0f; 141 | float mZTolerance = 0.2f; 142 | 143 | // Photon Gather 144 | int mTileCountScale = 10; 145 | uint2 mTileSize = uint2(32,32); 146 | bool mShowTileCount = false; 147 | float mDepthRadius = 0.1f; 148 | float mMinGatherColor = 0.001f; 149 | 150 | // Temporal Filter 151 | bool mTemporalFilter = true; 152 | float mFilterWeight = 0.85f; 153 | float mJitter = 0.6f; 154 | float mJitterPower = 1.0f; 155 | float mTemporalNormalKernel = 0.7f; 156 | float mTemporalDepthKernel = 3.0f; 157 | float mTemporalColorKernel = 10.0f; 158 | 159 | // Spacial Filter 160 | bool mSpacialFilter = false; 161 | int mSpacialPasses = 1; 162 | float mSpacialNormalKernel = 0.7f; 163 | float mSpacialDepthKernel = 3.0f; 164 | float mSpacialColorKernel = 0.5f; 165 | float mSpacialScreenKernel = 1.0f; 166 | 167 | // Composite 168 | bool mRayTrace = true; 169 | enum Display 170 | { 171 | ShowRasterization = 0, 172 | ShowDepth = 1, 173 | ShowNormal = 2, 174 | ShowDiffuse = 3, 175 | ShowSpecular = 4, 176 | ShowPhoton = 5, 177 | ShowWorld = 6, 178 | ShowRoughness = 7, 179 | ShowRayTex = 8, 180 | ShowRayTracing = 9, 181 | ShowAvgScreenArea = 10, 182 | ShowAvgScreenAreaVariance = 11, 183 | ShowCount = 12, 184 | ShowTotalPhoton = 13, 185 | ShowRayCountMipmap = 14, 186 | ShowPhotonDensity = 15, 187 | ShowSmallPhoton = 16, 188 | ShowSmallPhotonCount = 17, 189 | }; 190 | Display mDebugMode = ShowRayTracing; 191 | float mMaxPixelArea = 100; 192 | float mMaxPhotonCount = 1000000; 193 | int mRayCountMipIdx = 5; 194 | int mRayTexScaleFactor = 4; 195 | float mUVKernel = 0.7f; 196 | float mZKernel = 4.5f; 197 | float mNormalKernel = 4.0f; 198 | bool mFilterCausticsMap = false; 199 | 200 | // Others 201 | int mFrameCounter = 0; 202 | bool mUseDOF = false; 203 | uint32_t mSampleIndex = 0xdeadbeef; 204 | float2 mLightAngle{3.01f,2.f}; 205 | float3 mLightDirection; 206 | float2 mLightAngleSpeed{0,0}; 207 | 208 | Model::SharedPtr mpQuad; 209 | Model::SharedPtr mpSphere; 210 | RtScene::SharedPtr mpScene; 211 | Camera::SharedPtr mpCamera; 212 | FirstPersonCameraController mCamController; 213 | 214 | // forward shading pass 215 | RasterScenePass::SharedPtr mpRasterPass; 216 | 217 | // Clear draw argument 218 | ComputeProgram::SharedPtr mpDrawArgumentProgram; 219 | ComputeVars::SharedPtr mpDrawArgumentVars; 220 | ComputeState::SharedPtr mpDrawArgumentState; 221 | StructuredBuffer::SharedPtr mpDrawArgumentBuffer; 222 | 223 | // g-pass 224 | RasterScenePass::SharedPtr mpGPass; 225 | struct GBuffer 226 | { 227 | Texture::SharedPtr mpNormalTex; 228 | Texture::SharedPtr mpDiffuseTex; 229 | Texture::SharedPtr mpSpecularTex; 230 | Texture::SharedPtr mpDepthTex; 231 | Fbo::SharedPtr mpGPassFbo; 232 | }; 233 | GBuffer mGBuffer[2]; 234 | Texture::SharedPtr mpSmallPhotonTex; 235 | 236 | // photon trace 237 | struct PhotonTraceShader 238 | { 239 | RtProgram::SharedPtr mpPhotonTraceProgram; 240 | RtProgramVars::SharedPtr mpPhotonTraceVars; 241 | RtState::SharedPtr mpPhotonTraceState; 242 | }; 243 | enum PhotonTraceMacro 244 | { 245 | RAY_DIFFERENTIAL = 0, 246 | RAY_CONE = 1, 247 | RAY_NONE = 2 248 | }; 249 | PhotonTraceMacro mPhotonTraceMacro = RAY_DIFFERENTIAL; 250 | std::unordered_map mPhotonTraceShaderList; 251 | Texture::SharedPtr mpUniformNoise; 252 | 253 | // update ray density result 254 | ComputeProgram::SharedPtr mpUpdateRayDensityProgram; 255 | ComputeVars::SharedPtr mpUpdateRayDensityVars; 256 | ComputeState::SharedPtr mpUpdateRayDensityState; 257 | 258 | // analyse trace result 259 | ComputeProgram::SharedPtr mpAnalyseProgram; 260 | ComputeVars::SharedPtr mpAnalyseVars; 261 | ComputeState::SharedPtr mpAnalyseState; 262 | StructuredBuffer::SharedPtr mpRayArgumentBuffer; 263 | 264 | // generate ray count 265 | ComputeProgram::SharedPtr mpGenerateRayCountProgram; 266 | ComputeVars::SharedPtr mpGenerateRayCountVars; 267 | ComputeState::SharedPtr mpGenerateRayCountState; 268 | StructuredBuffer::SharedPtr mpRayCountQuadTree; 269 | 270 | // generate ray count mipmap 271 | ComputeProgram::SharedPtr mpGenerateRayCountMipProgram; 272 | ComputeVars::SharedPtr mpGenerateRayCountMipVars; 273 | ComputeState::SharedPtr mpGenerateRayCountMipState; 274 | 275 | // smooth photon 276 | ComputeProgram::SharedPtr mpSmoothProgram; 277 | ComputeVars::SharedPtr mpSmoothVars; 278 | ComputeState::SharedPtr mpSmoothState; 279 | 280 | // photon scatter 281 | GraphicsProgram::SharedPtr mpPhotonScatterProgram; 282 | GraphicsVars::SharedPtr mpPhotonScatterVars; 283 | GraphicsState::SharedPtr mpPhotonScatterBlendState; 284 | GraphicsState::SharedPtr mpPhotonScatterNoBlendState; 285 | Fbo::SharedPtr mpCausticsFbo[2]; 286 | Texture::SharedPtr mpGaussianKernel; 287 | Sampler::SharedPtr mpLinearSampler; 288 | 289 | // photon gather 290 | #define GATHER_PROCESSING_SHADER_COUNT 4 291 | ComputeProgram::SharedPtr mpAllocateTileProgram[GATHER_PROCESSING_SHADER_COUNT]; 292 | ComputeVars::SharedPtr mpAllocateTileVars[GATHER_PROCESSING_SHADER_COUNT]; 293 | ComputeState::SharedPtr mpAllocateTileState[GATHER_PROCESSING_SHADER_COUNT]; 294 | ComputeProgram::SharedPtr mpPhotonGatherProgram; 295 | ComputeVars::SharedPtr mpPhotonGatherVars; 296 | ComputeState::SharedPtr mpPhotonGatherState; 297 | StructuredBuffer::SharedPtr mpTileIDInfoBuffer; 298 | Buffer::SharedPtr mpIDBuffer; 299 | Buffer::SharedPtr mpIDCounterBuffer; 300 | 301 | // temporal filter 302 | ComputeProgram::SharedPtr mpFilterProgram; 303 | ComputeVars::SharedPtr mpFilterVars; 304 | ComputeState::SharedPtr mpFilterState; 305 | 306 | // spacial filter 307 | ComputeProgram::SharedPtr mpSpacialFilterProgram; 308 | ComputeVars::SharedPtr mpSpacialFilterVars; 309 | ComputeState::SharedPtr mpSpacialFilterState; 310 | 311 | // raytrace 312 | RtProgram::SharedPtr mpRaytraceProgram; 313 | RtProgramVars::SharedPtr mpRtVars; 314 | RtState::SharedPtr mpRtState; 315 | RtSceneRenderer::SharedPtr mpRtRenderer; 316 | Texture::SharedPtr mpRtOut; 317 | 318 | // composite pass 319 | Sampler::SharedPtr mpPointSampler; 320 | FullScreenPass::SharedPtr mpCompositePass; 321 | Texture::SharedPtr mpPhotonCountTex; 322 | 323 | // RT composite pass 324 | RtProgram::SharedPtr mpCompositeRTProgram; 325 | RtProgramVars::SharedPtr mpCompositeRTVars; 326 | RtState::SharedPtr mpCompositeRTState; 327 | 328 | // Caustics map 329 | StructuredBuffer::SharedPtr mpPhotonBuffer; 330 | StructuredBuffer::SharedPtr mpPhotonBuffer2; 331 | StructuredBuffer::SharedPtr mpRayTaskBuffer; 332 | StructuredBuffer::SharedPtr mpPixelInfoBuffer; 333 | Texture::SharedPtr mpRayDensityTex; 334 | 335 | void setPerFrameVars(const Fbo* pTargetFbo); 336 | void renderRT(RenderContext* pContext, Fbo::SharedPtr pTargetFbo); 337 | void loadScene(const std::string& filename, const Fbo* pTargetFbo); 338 | void loadShader(); 339 | void setCommonVars(GraphicsVars* pVars, const Fbo* pTargetFbo); 340 | void setPhotonTracingCommonVariable(PhotonTraceShader& shader); 341 | PhotonTraceShader getPhotonTraceShader(); 342 | void loadSceneSetting(std::string path); 343 | void saveSceneSetting(std::string path); 344 | void createCausticsMap(); 345 | void createGBuffer(int width, int height, GBuffer& gbuffer); 346 | int2 getTileDim() const; 347 | float resolutionFactor(); 348 | uint photonMacroToFlags(); 349 | }; 350 | -------------------------------------------------------------------------------- /Caustics.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | true 23 | 24 | 25 | true 26 | true 27 | 28 | 29 | true 30 | true 31 | 32 | 33 | true 34 | true 35 | 36 | 37 | true 38 | true 39 | 40 | 41 | true 42 | true 43 | 44 | 45 | true 46 | true 47 | 48 | 49 | true 50 | true 51 | 52 | 53 | true 54 | true 55 | 56 | 57 | true 58 | true 59 | 60 | 61 | true 62 | true 63 | 64 | 65 | true 66 | true 67 | 68 | 69 | true 70 | true 71 | 72 | 73 | true 74 | true 75 | 76 | 77 | true 78 | true 79 | 80 | 81 | true 82 | true 83 | 84 | 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | {2c535635-e4c5-4098-a928-574f0e7cd5f9} 92 | 93 | 94 | 95 | {9AF136FC-9741-4987-909F-279801DFBEAF} 96 | Win32Proj 97 | DXRT 98 | 10.0.17763.0 99 | Caustics 100 | 101 | 102 | 103 | Application 104 | true 105 | v141 106 | Unicode 107 | 108 | 109 | Application 110 | false 111 | v141 112 | true 113 | Unicode 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | true 127 | 128 | 129 | false 130 | 131 | 132 | 133 | 134 | 135 | Level3 136 | Disabled 137 | WIN32;SOLUTION_DIR=R"($(SolutionDir))";_DEBUG;%(PreprocessorDefinitions) 138 | stdcpp17 139 | true 140 | 141 | 142 | Windows 143 | true 144 | $(SolutionDir)\Framework\Externals\DXRT\Lib\;%(AdditionalLibraryDirectories) 145 | Shlwapi.lib;assimp.lib;freeimage.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;avcodec.lib;avutil.lib;avformat.lib;swscale.lib;%(AdditionalDependencies) 146 | 147 | 148 | 149 | 150 | Level3 151 | 152 | 153 | MaxSpeed 154 | true 155 | true 156 | WIN32;SOLUTION_DIR=R"($(SolutionDir))";NDEBUG;%(PreprocessorDefinitions) 157 | stdcpp17 158 | true 159 | 160 | 161 | Windows 162 | true 163 | true 164 | true 165 | $(SolutionDir)\Framework\Externals\DXRT\Lib\;%(AdditionalLibraryDirectories) 166 | Shlwapi.lib;assimp.lib;freeimage.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;avcodec.lib;avutil.lib;avformat.lib;swscale.lib;%(AdditionalDependencies) 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /Caustics.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {5ad81c70-0880-4571-9f05-ad80b98de9e7} 6 | 7 | 8 | 9 | 10 | Data 11 | 12 | 13 | Data 14 | 15 | 16 | Data 17 | 18 | 19 | Data 20 | 21 | 22 | Data 23 | 24 | 25 | Data 26 | 27 | 28 | Data 29 | 30 | 31 | Data 32 | 33 | 34 | Data 35 | 36 | 37 | Data 38 | 39 | 40 | Data 41 | 42 | 43 | Data 44 | 45 | 46 | Data 47 | 48 | 49 | Data 50 | 51 | 52 | Data 53 | 54 | 55 | Data 56 | 57 | 58 | Data 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Caustics.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Data/AllocateTilePhoton.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | 29 | __import ShaderCommon; 30 | 31 | #include "Common.hlsl" 32 | 33 | shared cbuffer PerFrameCB 34 | { 35 | float4x4 gViewProjMat; 36 | int2 screenDim; 37 | int2 tileDim; 38 | int2 blockCount; 39 | float gSplatSize; 40 | float minColor; 41 | }; 42 | 43 | #define PHOTON_COUNT_BLOCK_SIZE 32 44 | 45 | RWStructuredBuffer gDrawArgument; 46 | RWStructuredBuffer gPhotonBuffer; 47 | 48 | RWStructuredBuffer gTileInfo; 49 | RWByteAddressBuffer gIDBuffer; 50 | RWByteAddressBuffer gIDCounter; 51 | 52 | int getTileOffset(int x, int y) 53 | { 54 | return tileDim.x * y + x; 55 | } 56 | 57 | void GetPhotonScreenRange(Photon photon, out int2 minTileID, out int2 maxTileID) 58 | { 59 | // get screen position 60 | float3 corner0 = photon.dPdx + photon.dPdy; 61 | float3 corner1 = photon.dPdx - photon.dPdy; 62 | float4 px0 = mul(float4(photon.posW + corner0, 1), gViewProjMat); 63 | float4 px1 = mul(float4(photon.posW - corner0, 1), gViewProjMat); 64 | float4 py0 = mul(float4(photon.posW + corner1, 1), gViewProjMat); 65 | float4 py1 = mul(float4(photon.posW - corner1, 1), gViewProjMat); 66 | if ((px0.z < 0 || px0.z > px0.w) || 67 | (px1.z < 0 || px1.z > px1.w) || 68 | (py0.z < 0 || py0.z > py0.w) || 69 | (py1.z < 0 || py1.z > py1.w)) 70 | { 71 | minTileID = 1; 72 | maxTileID = -1; 73 | return; 74 | } 75 | px0.xyz /= px0.w; 76 | px1.xyz /= px1.w; 77 | py0.xyz /= py0.w; 78 | py1.xyz /= py1.w; 79 | px0.y *= -1; 80 | px1.y *= -1; 81 | py0.y *= -1; 82 | py1.y *= -1; 83 | 84 | // get range 85 | float3 minCoord = 10000; 86 | float3 maxCoord = -10000; 87 | minCoord = min(minCoord, px0.xyz); 88 | minCoord = min(minCoord, px1.xyz); 89 | minCoord = min(minCoord, py0.xyz); 90 | minCoord = min(minCoord, py1.xyz); 91 | maxCoord = max(maxCoord, px0.xyz); 92 | maxCoord = max(maxCoord, px1.xyz); 93 | maxCoord = max(maxCoord, py0.xyz); 94 | maxCoord = max(maxCoord, py1.xyz); 95 | minCoord.xy = (minCoord.xy + 1) * 0.5; 96 | maxCoord.xy = (maxCoord.xy + 1) * 0.5; 97 | if (any(minCoord > 1) || any(maxCoord < 0)) 98 | { 99 | minTileID = 1; 100 | maxTileID = -1; 101 | return; 102 | } 103 | minTileID = minCoord.xy * screenDim / uint2(GATHER_TILE_SIZE_X, GATHER_TILE_SIZE_Y); 104 | maxTileID = maxCoord.xy * screenDim / uint2(GATHER_TILE_SIZE_X, GATHER_TILE_SIZE_Y); 105 | 106 | minTileID = clamp(minTileID, 0, tileDim - 1); 107 | maxTileID = clamp(maxTileID, 0, tileDim - 1); 108 | } 109 | 110 | bool checkPhoton(Photon p) 111 | { 112 | return dot(p.color, float3(1, 1, 1)) > minColor; 113 | } 114 | 115 | int threadIDToPhotonID(uint3 threadIdx) 116 | { 117 | return threadIdx.y * blockCount.x * PHOTON_COUNT_BLOCK_SIZE + threadIdx.x; 118 | } 119 | 120 | 121 | bool orthogonalizeFrame(float3 a, float3 b, out float3 orthoA, out float3 orthoB) 122 | { 123 | float a11 = dot(a, a); 124 | float a12 = dot(a, b); 125 | float a22 = dot(b, b); 126 | 127 | if (abs(a12) > 1e-5) 128 | { 129 | float sum = a11 + a22; 130 | float diff = a11 - a22; 131 | float delta = sqrt(diff * diff + 4 * a12 * a12); 132 | 133 | float lambda1 = (sum + delta) * 0.5; 134 | float lambda2 = (sum - delta) * 0.5; 135 | 136 | float2 p1 = normalize(float2(a12, lambda1 - a11)); 137 | float2 p2 = normalize(float2(a12, lambda2 - a11)); 138 | 139 | orthoA = a * p1.x + b * p1.y; 140 | orthoB = a * p2.x + b * p2.y; 141 | } 142 | else 143 | { 144 | orthoA = a; 145 | orthoB = b; 146 | } 147 | 148 | float3 normal = cross(a, b); 149 | float lengthA = length(orthoA); 150 | float lengthB = length(orthoB); 151 | float lengthRatio = lengthA / lengthB; 152 | const float ratioThreshold = 1e3; 153 | if (min(lengthA, lengthB) < 0.005 || lengthRatio < 1/ratioThreshold || lengthRatio > ratioThreshold) 154 | { 155 | return false; 156 | } 157 | if (lengthB > lengthA) 158 | { 159 | float3 v = orthoB; 160 | orthoB = orthoA; 161 | orthoA = v; 162 | } 163 | float3 newNormal = cross(orthoA, orthoB); 164 | if (dot(normal, newNormal) < 0) 165 | { 166 | orthoB *= -1; 167 | } 168 | 169 | orthoA *= gSplatSize; 170 | orthoB *= gSplatSize; 171 | return true; 172 | } 173 | 174 | [numthreads(PHOTON_COUNT_BLOCK_SIZE, PHOTON_COUNT_BLOCK_SIZE, 1)] 175 | void OrthogonalizePhoton(uint3 threadIdx : SV_DispatchThreadID) 176 | { 177 | int photonID = threadIDToPhotonID(threadIdx); 178 | if (photonID >= gDrawArgument[0].instanceCount) 179 | { 180 | return; 181 | } 182 | 183 | Photon p = gPhotonBuffer[photonID]; 184 | float3 dPdx, dPdy; 185 | if (!orthogonalizeFrame(p.dPdx, p.dPdy, dPdx, dPdy)) 186 | { 187 | p.color = 0; 188 | } 189 | p.dPdx = dPdx; 190 | p.dPdy = dPdy; 191 | gPhotonBuffer[photonID] = p; 192 | } 193 | 194 | [numthreads(PHOTON_COUNT_BLOCK_SIZE, PHOTON_COUNT_BLOCK_SIZE, 1)] 195 | void CountTilePhoton(uint3 threadIdx : SV_DispatchThreadID) 196 | { 197 | int photonID = threadIDToPhotonID(threadIdx); 198 | if (photonID >= gDrawArgument[0].instanceCount) 199 | { 200 | return; 201 | } 202 | if (photonID == 0) 203 | { 204 | gIDCounter.Store(0, 0); 205 | } 206 | 207 | Photon photon = gPhotonBuffer[photonID]; 208 | if (!checkPhoton(photon)) 209 | { 210 | return; 211 | } 212 | 213 | int2 minTileID, maxTileID; 214 | GetPhotonScreenRange(photon, minTileID, maxTileID); 215 | for (int x = minTileID.x; x <= maxTileID.x; x++) 216 | { 217 | for (int y = minTileID.y; y <= maxTileID.y; y++) 218 | { 219 | int offset = getTileOffset(x, y); 220 | int count; 221 | InterlockedAdd(gTileInfo[offset].count, 1, count); 222 | } 223 | } 224 | } 225 | 226 | [numthreads(GATHER_TILE_SIZE_X, GATHER_TILE_SIZE_Y, 1)] 227 | void AllocateMemory(uint3 threadIdx : SV_DispatchThreadID) 228 | { 229 | int2 tileID = threadIdx.xy; 230 | if (any(tileID >= tileDim)) 231 | { 232 | return; 233 | } 234 | 235 | int offset = getTileOffset(tileID.x, tileID.y); 236 | uint count = gTileInfo[offset].count; 237 | uint address = 0; 238 | gIDCounter.InterlockedAdd(0, count, address); 239 | gTileInfo[offset].address = address; 240 | gTileInfo[offset].count = 0; 241 | } 242 | 243 | [numthreads(PHOTON_COUNT_BLOCK_SIZE, PHOTON_COUNT_BLOCK_SIZE, 1)] 244 | void StoreTilePhoton(uint3 threadIdx : SV_DispatchThreadID) 245 | { 246 | int photonID = threadIDToPhotonID(threadIdx); 247 | if (photonID >= gDrawArgument[0].instanceCount) 248 | { 249 | return; 250 | } 251 | 252 | Photon photon = gPhotonBuffer[photonID]; 253 | if (!checkPhoton(photon)) 254 | { 255 | return; 256 | } 257 | 258 | int2 minTileID, maxTileID; 259 | GetPhotonScreenRange(photon, minTileID, maxTileID); 260 | for (int x = minTileID.x; x <= maxTileID.x; x++) 261 | { 262 | for (int y = minTileID.y; y <= maxTileID.y; y++) 263 | { 264 | int offset = getTileOffset(x, y); 265 | int address = gTileInfo[offset].address; 266 | int idx = 0; 267 | InterlockedAdd(gTileInfo[offset].count, 1, idx); 268 | gIDBuffer.Store((address + idx)*4, photonID); 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /Data/AnalyseTraceResult.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | float4x4 viewProjMat; 33 | int2 taskDim; 34 | int2 screenDim; 35 | float2 randomOffset; 36 | float normalThreshold; 37 | float distanceThreshold; 38 | float planarThreshold; 39 | float pixelLuminanceThreshold; 40 | float minPhotonPixelSize; 41 | uint samplePlacement; 42 | }; 43 | 44 | struct DrawArguments 45 | { 46 | uint indexCountPerInstance; 47 | uint instanceCount; 48 | uint startIndexLocation; 49 | int baseVertexLocation; 50 | uint startInstanceLocation; 51 | }; 52 | 53 | RWStructuredBuffer gPhotonBuffer; 54 | //RWStructuredBuffer gDrawArgument; 55 | RWStructuredBuffer gRayArgument; 56 | RWStructuredBuffer gRayTask; 57 | StructuredBuffer gPixelInfo; 58 | Texture2D gDepthTex; 59 | Texture2D gRayDensityTex; 60 | 61 | int getRayTaskID(uint2 pos) 62 | { 63 | return pos.y * taskDim.x + pos.x; 64 | } 65 | 66 | [numthreads(32, 16, 1)] 67 | void addPhotonTaskFromTexture(uint3 groupID : SV_GroupID, uint groupIndex : SV_GroupIndex, uint3 threadIdx : SV_DispatchThreadID) 68 | { 69 | uint rayIdx = getRayTaskID(threadIdx.xy); 70 | //gPixelInfo[rayIdx].screenArea = 0; 71 | //gPixelInfo[rayIdx].screenAreaSq = 0; 72 | //gPixelInfo[rayIdx].count = 0; 73 | 74 | int idx0 = gPixelInfo[rayIdx].photonIdx; 75 | 76 | int2 pixel00 = threadIdx.xy; 77 | float v00 = gRayDensityTex.Load(int3(pixel00 + int2(0, 0), 0)).r; 78 | float v10 = gRayDensityTex.Load(int3(pixel00 + int2(1, 0), 0)).r; 79 | float v01 = gRayDensityTex.Load(int3(pixel00 + int2(0, 1), 0)).r; 80 | float v11 = gRayDensityTex.Load(int3(pixel00 + int2(1, 1), 0)).r; 81 | 82 | float sampleCountF = 0.25 * (v00 + v10 + v01 + v11); //max(v00, max(v10, max(v01, v11)));// 83 | if (samplePlacement == 0) 84 | { 85 | int sampleCount = int(sampleCountF); 86 | sampleCount = max(1, sampleCount);// clamp(sampleCount, 1, 1024 * 8); 87 | 88 | float pixelSize = 1.0; 89 | 90 | int taskIdx = 0; 91 | InterlockedAdd(gRayArgument[0].rayTaskCount, sampleCount, taskIdx); 92 | float g = 1.32471795724474602596; 93 | float a1 = 1.0 / g; 94 | float a2 = 1.0 / (g * g); 95 | for (uint i = 0; i < sampleCount; i++) 96 | { 97 | float x = frac(randomOffset.x + a1 * (i + 1)); 98 | float y = frac(randomOffset.y + a2 * (i + 1)); 99 | 100 | float2 uv = bilinearSample(v00, v10, v01, v11, float2(x, y)); 101 | RayTask newTask; 102 | newTask.screenCoord = pixel00 + uv +0.5; 103 | newTask.pixelSize = pixelSize *sqrt(1 / (bilinearIntepolation(v00, v10, v01, v11, uv))); 104 | gRayTask[taskIdx + i] = newTask; 105 | } 106 | } 107 | else 108 | { 109 | //sampleCountF = ceil(sampleCountF / round) * round; 110 | int sampleDim = (int)ceil(sqrt(sampleCountF)); 111 | int sampleCount = sampleDim * sampleDim; 112 | float pixelSize = sqrt(sampleCountF / sampleCount); 113 | int taskIdx = 0; 114 | InterlockedAdd(gRayArgument[0].rayTaskCount, sampleCount, taskIdx); 115 | if (sampleCount == 1) 116 | { 117 | v00 = v10 = v01 = v11 = 1; 118 | pixelSize = 1; 119 | } 120 | for (uint i = 0; i < sampleCount; i++) 121 | { 122 | uint yi = i / sampleDim; 123 | uint xi = i - yi * sampleDim; 124 | float x = (xi + 0.5) / sampleDim; 125 | float y = (yi + 0.5) / sampleDim; 126 | float2 rnd = float2(x, y); 127 | 128 | float2 uv = bilinearSample(v00, v10, v01, v11, rnd); 129 | //float2 duv = bilinearSample(v00, v10, v01, v11, rnd + 1e-2) - uv; 130 | float aniso = 1;// sqrt(duv.y / duv.x);// clamp(duv.y / duv.x, 0.1, 10); 131 | 132 | RayTask newTask; 133 | newTask.screenCoord = pixel00 + uv + 0.5; 134 | newTask.pixelSize = pixelSize * sqrt(1 / (bilinearIntepolation(v00, v10, v01, v11, uv))) *float2(1 / aniso, aniso); 135 | gRayTask[taskIdx + i] = newTask; 136 | } 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /Data/Caustics.ps.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | __import ShaderCommon; 29 | __import Shading; 30 | __import DefaultVS; 31 | 32 | float4 main(VertexOut vOut) : SV_TARGET 33 | { 34 | ShadingData sd = prepareShadingData(vOut, gMaterial, gCamera.posW); 35 | float4 color = 0; 36 | color.a = 1; 37 | 38 | [unroll] 39 | for (uint i = 0; i < 3; i++) 40 | { 41 | color += evalMaterial(sd, gLights[i], 1).color; 42 | } 43 | color.rgb += sd.emissive; 44 | return color; 45 | } -------------------------------------------------------------------------------- /Data/Caustics.rt.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | RWTexture2D gOutput; 29 | __import Raytracing; 30 | import Helpers; 31 | 32 | shared cbuffer PerFrameCB 33 | { 34 | float4x4 invView; 35 | float2 viewportDims; 36 | float tanHalfFovY; 37 | uint sampleIndex; 38 | bool useDOF; 39 | }; 40 | 41 | struct PrimaryRayData 42 | { 43 | float4 color; 44 | uint depth; 45 | float hitT; 46 | }; 47 | 48 | struct ShadowRayData 49 | { 50 | bool hit; 51 | }; 52 | 53 | [shader("miss")] 54 | void shadowMiss(inout ShadowRayData hitData) 55 | { 56 | hitData.hit = false; 57 | } 58 | 59 | [shader("anyhit")] 60 | void shadowAnyHit(inout ShadowRayData hitData, in BuiltInTriangleIntersectionAttributes attribs) 61 | { 62 | hitData.hit = true; 63 | } 64 | 65 | [shader("miss")] 66 | void primaryMiss(inout PrimaryRayData hitData) 67 | { 68 | hitData.color = float4(0.38f, 0.52f, 0.10f, 1); 69 | hitData.hitT = -1; 70 | } 71 | 72 | bool checkLightHit(uint lightIndex, float3 origin) 73 | { 74 | float3 direction = gLights[lightIndex].posW - origin; 75 | RayDesc ray; 76 | float epsilon = 0.01; 77 | ray.Origin = origin; 78 | ray.Direction = normalize(direction); 79 | ray.TMin = epsilon; 80 | ray.TMax = max(0.01, length(direction)- epsilon); 81 | 82 | ShadowRayData rayData; 83 | rayData.hit = true; 84 | TraceRay(gRtScene, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xFF, 1 /* ray index */, hitProgramCount, 1, ray, rayData); 85 | return rayData.hit; 86 | } 87 | 88 | float3 getReflectionColor(float3 worldOrigin, VertexOut v, float3 worldRayDir, uint hitDepth) 89 | { 90 | float3 reflectColor = float3(0, 0, 0); 91 | if (hitDepth == 0) 92 | { 93 | PrimaryRayData secondaryRay; 94 | secondaryRay.depth.r = 1; 95 | RayDesc ray; 96 | ray.Origin = worldOrigin; 97 | ray.Direction = reflect(worldRayDir, v.normalW); 98 | ray.TMin = 0.001; 99 | ray.TMax = 100000; 100 | TraceRay(gRtScene, 0 /*rayFlags*/, 0xFF, 0 /* ray index*/, hitProgramCount, 0, ray, secondaryRay); 101 | reflectColor = secondaryRay.hitT == -1 ? 0 : secondaryRay.color.rgb; 102 | float falloff = max(1, (secondaryRay.hitT * secondaryRay.hitT)); 103 | reflectColor *= 20 / falloff; 104 | } 105 | return reflectColor; 106 | } 107 | 108 | [shader("closesthit")] 109 | void primaryClosestHit(inout PrimaryRayData hitData, in BuiltInTriangleIntersectionAttributes attribs) 110 | { 111 | // Get the hit-point data 112 | float3 rayOrigW = WorldRayOrigin(); 113 | float3 rayDirW = WorldRayDirection(); 114 | float hitT = RayTCurrent(); 115 | uint triangleIndex = PrimitiveIndex(); 116 | 117 | float3 posW = rayOrigW + hitT * rayDirW; 118 | // prepare the shading data 119 | VertexOut v = getVertexAttributes(triangleIndex, attribs); 120 | ShadingData sd = prepareShadingData(v, gMaterial, rayOrigW, 0); 121 | 122 | // Shoot a reflection ray 123 | float3 reflectColor = 0;// getReflectionColor(posW, v, rayDirW, hitData.depth.r); 124 | float3 color = 0; 125 | 126 | [unroll] 127 | for (int i = 0; i < gLightsCount; i++) 128 | { 129 | if (checkLightHit(i, posW) == false) 130 | { 131 | color += evalMaterial(sd, gLights[i], 1).color.xyz; 132 | } 133 | } 134 | 135 | hitData.color.rgb = color; 136 | hitData.hitT = hitT; 137 | // A very non-PBR inaccurate way to do reflections 138 | float roughness = min(0.5, max(1e-8, sd.roughness)); 139 | hitData.color.rgb += sd.specular * reflectColor * (roughness * roughness); 140 | hitData.color.rgb += sd.emissive; 141 | //hitData.color.rgb = sd.N; 142 | hitData.color.a = 1; 143 | } 144 | 145 | [shader("raygeneration")] 146 | void rayGen() 147 | { 148 | uint3 launchIndex = DispatchRaysIndex(); 149 | uint randSeed = rand_init(launchIndex.x + launchIndex.y * viewportDims.x, sampleIndex, 16); 150 | 151 | RayDesc ray; 152 | if (!useDOF) 153 | { 154 | ray = generateRay(gCamera, launchIndex.xy, viewportDims); 155 | } 156 | else 157 | { 158 | ray = generateDOFRay(gCamera, launchIndex.xy, viewportDims, randSeed); 159 | } 160 | PrimaryRayData hitData; 161 | hitData.depth = 0; 162 | TraceRay( gRtScene, 0 /*rayFlags*/, 0xFF, 0 /* ray index*/, hitProgramCount, 0, ray, hitData ); 163 | gOutput[launchIndex.xy] = hitData.color; 164 | } 165 | -------------------------------------------------------------------------------- /Data/Common.hlsl: -------------------------------------------------------------------------------- 1 | 2 | #define GATHER_TILE_SIZE_X 32 3 | #define GATHER_TILE_SIZE_Y 32 4 | 5 | struct Photon 6 | { 7 | float3 posW; 8 | //float3 normalW; 9 | float3 color; 10 | float3 dPdx; 11 | float3 dPdy; 12 | }; 13 | 14 | struct RayTask 15 | { 16 | float2 screenCoord; 17 | float2 pixelSize; 18 | }; 19 | 20 | struct PixelInfo 21 | { 22 | uint screenArea; 23 | uint screenAreaSq; 24 | uint count; 25 | int photonIdx; 26 | }; 27 | 28 | struct RayArgument 29 | { 30 | int rayTaskCount; 31 | }; 32 | 33 | struct IDBlock 34 | { 35 | int address; 36 | int count; 37 | }; 38 | 39 | void getRefractVector(float3 I, float3 N, out float3 R, float eta) 40 | { 41 | float IN = dot(I, N); 42 | float RN = -sqrt(1 - eta * eta * (1 - IN * IN)); 43 | float mu = eta * IN - RN; 44 | R = eta * I - mu * N; 45 | } 46 | 47 | // eta = eta i / eta o 48 | bool isTotalInternalReflection(float3 I, float3 N, float eta) 49 | { 50 | // detect total internal reflection 51 | float cosI = dot(I, N); 52 | return cosI * cosI < (1 - 1 / (eta * eta)); 53 | } 54 | 55 | bool isPhotonAdjecent(Photon photon0, Photon photon1, float normalThreshold, float distanceThreshold, float planarThreshold) 56 | { 57 | return 58 | //dot(photon0.normalW, photon1.normalW) < normalThreshold && 59 | length(photon0.posW - photon1.posW) < distanceThreshold// && 60 | //dot(photon0.normalW, photon0.posW - photon1.posW) < planarThreshold 61 | ; 62 | } 63 | 64 | float smoothKernel(float x) 65 | { 66 | x = saturate(x); 67 | return x * x * (2 * x - 3) + 1; 68 | } 69 | 70 | bool isInFrustum(float4 p) 71 | { 72 | return (p.x >= -p.w) && (p.x <= p.w) && (p.y >= -p.w) && (p.y <= p.w) && (p.z >= 0) && (p.z <= p.w); 73 | } 74 | 75 | float linearSample(float a, float b, float u) 76 | { 77 | if (a == b) 78 | return u; 79 | float s = 0.5 * (a + b); 80 | a /= s; 81 | b /= s; 82 | return (a - sqrt(lerp(a * a, b * b, u))) / (a - b); 83 | } 84 | 85 | float2 bilinearSample(float a00, float a10, float a01, float a11, float2 uv) 86 | { 87 | float a0 = a00 + a01; 88 | float a1 = a10 + a11; 89 | float u = linearSample(a0, a1, uv.x); 90 | float b0 = lerp(a00, a10, u); 91 | float b1 = lerp(a01, a11, u); 92 | float v = linearSample(b0, b1, uv.y); 93 | return float2(u, v); 94 | } 95 | 96 | float bilinearIntepolation(float a00, float a10, float a01, float a11, float2 uv) 97 | { 98 | float b0 = lerp(a00, a10, uv.x); 99 | float b1 = lerp(a01, a11, uv.x); 100 | return lerp(b0, b1, uv.y); 101 | } 102 | 103 | float toViewSpace(float4x4 invProj, float depth) 104 | { 105 | return (invProj[2][2] * depth + invProj[3][2]) / (invProj[2][3] * depth + invProj[3][3]); 106 | } 107 | 108 | int getMipOffset(int mip) 109 | { 110 | return ((1 << (mip << 1)) - 1) / 3; 111 | } 112 | 113 | int getMipSize(int mip) 114 | { 115 | return (1 << mip); 116 | } 117 | 118 | int getTextureOffset(int2 pos, int mip) 119 | { 120 | int mipSize = (1 << mip); 121 | int mipOffset = ((1 << (mip << 1)) - 1) / 3; 122 | return mipOffset + pos.y * mipSize + pos.x; 123 | } 124 | 125 | int getMipOffset4(int mip) 126 | { 127 | return (((1 << (mip << 2)) - 1) << 2) / 15; 128 | } 129 | 130 | int getMipSize4(int mip) 131 | { 132 | return ((1 << (mip << 1)) << 1); 133 | } 134 | 135 | int getTextureOffset4(int2 pos, int mip) 136 | { 137 | int mipSize = getMipSize4(mip); 138 | int mipOffset = getMipOffset4(mip); 139 | return mipOffset + pos.y * mipSize + pos.x; 140 | } 141 | 142 | float getLuminance(float3 color) 143 | { 144 | return dot(color, float3(0.299, 0.587, 0.114)); 145 | } 146 | 147 | uint compressColor(float3 color, float scale) 148 | { 149 | uint3 c = color * 255 * scale; 150 | return (1 << 28) | (c.r << 19) | (c.g << 9) | (c.b); 151 | } 152 | 153 | float4 decompressColor(uint c, float scale) 154 | { 155 | float4 color; 156 | color.b = (c & 0x1ff); 157 | color.g = ((c >> 9) & 0x3ff); 158 | color.r = ((c >> 19) & 0x1ff); 159 | color.a = ((c >> 28) & 0xf); 160 | color.rgb /= (255 * scale); 161 | return color; 162 | } 163 | -------------------------------------------------------------------------------- /Data/Composite.ps.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | __import ShaderCommon; 29 | __import Shading; 30 | __import DefaultVS; 31 | 32 | #include "Common.hlsl" 33 | 34 | SamplerState gPointSampler : register(s1); 35 | 36 | Texture2D gDepthTex; 37 | Texture2D gNormalTex; 38 | Texture2D gDiffuseTex; 39 | Texture2D gSpecularTex; 40 | Texture2D gPhotonTex; 41 | Texture2D gRaytracingTex; 42 | Texture2D gRayTex; 43 | Texture1D gStatisticsTex; 44 | Texture2D gSmallPhotonTex; 45 | StructuredBuffergRayCountQuadTree; 46 | StructuredBuffer gPixelInfo; 47 | 48 | // Debug modes 49 | #define ShowDepth 1 50 | #define ShowNormal 2 51 | #define ShowDiffuse 3 52 | #define ShowSpecular 4 53 | #define ShowPhoton 5 54 | #define ShowWorld 6 55 | #define ShowRoughness 7 56 | #define ShowRayTex 8 57 | #define ShowRayTracing 9 58 | #define ShowAvgScreenArea 10 59 | #define ShowAvgScreenAreaVariance 11 60 | #define ShowCount 12 61 | #define ShowTotalPhoton 13 62 | #define ShowRayCountMipTex 14 63 | #define ShowPhotonDensity 15 64 | #define ShowSmallPhotonTex 16 65 | #define ShowSmallPhotonCount 17 66 | 67 | cbuffer PerImageCB 68 | { 69 | // Lighting params 70 | LightData gLightData[16]; 71 | float4x4 gInvWvpMat; 72 | float4x4 gInvPMat; 73 | 74 | float3 gCameraPos; 75 | uint gNumLights; 76 | 77 | int2 screenDim; 78 | int2 dispatchSize; 79 | 80 | uint gDebugMode; 81 | float gMaxPixelArea; 82 | int gRayTexScale; 83 | uint gStatisticsOffset; 84 | 85 | float gMaxPhotonCount; 86 | int gRayCountMip; 87 | float gSmallPhotonColorScale; 88 | }; 89 | 90 | float4 main(float2 texC : TEXCOORD) : SV_TARGET 91 | { 92 | float depth = gDepthTex.Sample(gPointSampler, texC).r; 93 | float4 screenPnt = float4(texC * float2(2,-2) + float2(-1,1), depth, 1); 94 | float4 worldPnt = mul(screenPnt, gInvWvpMat); 95 | worldPnt /= worldPnt.w; 96 | float4 normalVal = gNormalTex.Sample(gPointSampler, texC); 97 | float4 diffuseVal = gDiffuseTex.Sample(gPointSampler, texC); 98 | float4 specularVal = gSpecularTex.Sample(gPointSampler, texC); 99 | float4 rtColor = gRaytracingTex.Sample(gPointSampler, texC); 100 | 101 | float4 color = rtColor; 102 | if (gDebugMode == ShowDepth) 103 | { 104 | float4 viewPnt = mul(screenPnt, gInvPMat); 105 | viewPnt /= viewPnt.w; 106 | float viewDepth = (gInvPMat[2][2] * depth + gInvPMat[3][2]) / (gInvPMat[2][3] * depth + gInvPMat[3][3]); 107 | color = float4(abs(viewDepth.xxx)*0.01, 1); 108 | } 109 | else if (gDebugMode == ShowNormal) 110 | color = normalVal; 111 | else if (gDebugMode == ShowDiffuse) 112 | color = gDiffuseTex.Sample(gPointSampler, texC); 113 | else if (gDebugMode == ShowSpecular) 114 | color = gSpecularTex.Sample(gPointSampler, texC); 115 | else if (gDebugMode == ShowWorld) 116 | color = frac(worldPnt * 0.01 + 0.01); 117 | else if (gDebugMode == ShowRoughness) 118 | color = diffuseVal.a; 119 | else if (gDebugMode == ShowRayTex) 120 | { 121 | int2 screenPixel = texC * screenDim; 122 | //float2 uv = clamp(screenPixel / 2048, 0, 1); 123 | //color = gRayTex.Sample(gPointSampler, uv); 124 | float4 v = gRayTex.Load(int3(screenPixel.xy / gRayTexScale, 0)); 125 | //color = float4(v >> 16, 0, 0, v & 0xff); 126 | //color /= color.w; 127 | //color.r /= gMaxPixelArea; 128 | if(v.r <= gMaxPixelArea) 129 | color = float4(v.rgb / gMaxPixelArea, 1); 130 | else 131 | color = float4(1, 0, 1, 1); 132 | } 133 | else if (gDebugMode == ShowRayCountMipTex) 134 | { 135 | int2 screenPixel = texC * screenDim; 136 | int2 texelPos = screenPixel.xy / gRayTexScale; 137 | if (all(texelPos < getMipSize(gRayCountMip))) 138 | { 139 | int offset = getTextureOffset(texelPos.xy, gRayCountMip); 140 | uint4 v = gRayCountQuadTree[offset];// .Load(int3(texelPos, gRayCountMip)); 141 | uint sum = v.a; 142 | if (sum <= gMaxPixelArea) 143 | color = float4(sum / gMaxPixelArea, 1); 144 | else 145 | color = float4(1, 0, 1, 1); 146 | } 147 | } 148 | else if (gDebugMode == ShowRayTracing) 149 | { 150 | color = rtColor; 151 | } 152 | else if (gDebugMode == ShowAvgScreenArea || gDebugMode == ShowAvgScreenAreaVariance || gDebugMode == ShowCount) 153 | { 154 | int2 screenPixel = texC * screenDim; 155 | int2 texelPos = screenPixel.xy / gRayTexScale; 156 | if (all(texelPos < dispatchSize)) 157 | { 158 | PixelInfo info = gPixelInfo[texelPos.y * dispatchSize.x + texelPos.x]; 159 | float value = 0; 160 | float avgArea = float(info.screenArea) / float(info.count + 0.001); 161 | float avgAreaSq = float(info.screenAreaSq) / float(info.count + 0.001); 162 | if (gDebugMode == ShowAvgScreenArea) 163 | { 164 | value = avgArea; 165 | } 166 | else if (gDebugMode == ShowAvgScreenAreaVariance) 167 | { 168 | value = sqrt(avgAreaSq - avgArea * avgArea); 169 | } 170 | else if (gDebugMode == ShowCount) 171 | { 172 | value = info.count; 173 | } 174 | float maxVal = gMaxPixelArea; 175 | if (value <= maxVal) 176 | color = float4(value.xxx / maxVal, 1); 177 | else 178 | color = float4(1, 0, 1, 1); 179 | } 180 | } 181 | else if (gDebugMode == ShowTotalPhoton) 182 | { 183 | texC.y = 1 - texC.y; 184 | int2 screenPixel = texC * screenDim; 185 | int texelPos = (gStatisticsOffset - screenPixel.x + screenDim.x) % screenDim.x; 186 | uint valueI = gStatisticsTex[texelPos].r; 187 | valueI = valueI * screenDim.y / gMaxPhotonCount; 188 | uint segmentWidth = screenDim.y / 4; 189 | float4 graphColor; 190 | float alpha = 0.3; 191 | if (screenPixel.y % segmentWidth == 0) 192 | graphColor = float4(0.2, 0.2, 0.2, alpha); 193 | else if (screenPixel.y <= valueI) 194 | graphColor = float4(1, 0, 0, alpha); 195 | else 196 | graphColor = float4(0, 0, 0, 0); 197 | color.rgb = lerp(rtColor.rgb, graphColor.rgb, graphColor.a); 198 | color.a = 1; 199 | } 200 | else if (gDebugMode == ShowSmallPhotonTex) 201 | { 202 | texC.y = 1 - texC.y; 203 | int2 screenPixel = texC * screenDim; 204 | uint v = gSmallPhotonTex.Load(int3(screenPixel.xy, 0)); 205 | float4 photonClr = decompressColor(v, gSmallPhotonColorScale); 206 | color = float4(photonClr.rgb, 1); 207 | } 208 | else if (gDebugMode == ShowSmallPhotonCount) 209 | { 210 | texC.y = 1 - texC.y; 211 | int2 screenPixel = texC * screenDim; 212 | uint v = gSmallPhotonTex.Load(int3(screenPixel.xy, 0)); 213 | float4 photonClr = decompressColor(v, gSmallPhotonColorScale); 214 | if (photonClr.a <= gMaxPixelArea) 215 | color = float4(photonClr.aaa / gMaxPixelArea, 1); 216 | else 217 | color = float4(1, 0, 1, 1); 218 | color.rgb += rtColor.rgb;// *0.5; 219 | } 220 | else 221 | { 222 | ShadingData sd = initShadingData(); 223 | sd.posW = worldPnt.xyz; 224 | sd.V = normalize(gCameraPos - sd.posW); 225 | sd.N = normalVal.xyz; 226 | sd.NdotV = saturate(dot(sd.V, sd.N)); 227 | sd.linearRoughness = diffuseVal.a; 228 | sd.roughness = sd.linearRoughness * sd.linearRoughness; 229 | sd.specular = specularVal.xyz; 230 | sd.diffuse = diffuseVal.rgb; 231 | sd.opacity = specularVal.a; 232 | color = float4(0,0,0,1); 233 | for (uint l = 0; l < gNumLights; l++) 234 | { 235 | ShadingResult sr = evalMaterial(sd, gLightData[l], 1); 236 | color.rgb += sr.color.rgb; 237 | } 238 | 239 | float4 photonClr = gPhotonTex.Sample(gPointSampler, texC); 240 | if (gDebugMode == ShowPhoton) 241 | { 242 | color.rgb = photonClr.rgb;// lerp(color.rgb, photonClr.rgb, photonClr.a); 243 | } 244 | else if (gDebugMode == ShowPhotonDensity) 245 | { 246 | if(photonClr.a <= gMaxPixelArea) 247 | color.rgb = photonClr.aaa / gMaxPixelArea; 248 | else 249 | color = float4(1, 0, 1, 1); 250 | } 251 | else 252 | { 253 | color.rgb += photonClr.rgb * sd.diffuse; 254 | } 255 | } 256 | 257 | return color; 258 | } 259 | -------------------------------------------------------------------------------- /Data/CompositeRT.rt.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | RWTexture2D gOutput; 30 | Texture2D gCausticsTex; 31 | Texture2D gDepthTex; 32 | Texture2D gNormalTex; 33 | SamplerState gLinearSampler; 34 | SamplerState gPointSampler; 35 | __import Raytracing; 36 | import Helpers; 37 | 38 | shared cbuffer PerFrameCB 39 | { 40 | float4x4 invView; 41 | float4x4 invProj; 42 | float2 viewportDims; 43 | float tanHalfFovY; 44 | uint sampleIndex; 45 | bool useDOF; 46 | float roughThreshold; 47 | int maxDepth; 48 | float iorOverride; 49 | int causticsResRatio; 50 | float gPosKernel; 51 | float gZKernel; 52 | float gNormalKernel; 53 | }; 54 | 55 | struct HitData 56 | { 57 | float3 color; 58 | float hitT; 59 | float3 nextDir; 60 | float3 throughput; 61 | }; 62 | 63 | struct ShadowRayData 64 | { 65 | bool hit; 66 | }; 67 | 68 | [shader("miss")] 69 | void shadowMiss(inout ShadowRayData hitData) 70 | { 71 | hitData.hit = false; 72 | } 73 | 74 | [shader("anyhit")] 75 | void shadowAnyHit(inout ShadowRayData hitData, in BuiltInTriangleIntersectionAttributes attribs) 76 | { 77 | hitData.hit = true; 78 | } 79 | 80 | [shader("miss")] 81 | void primaryMiss(inout HitData hitData) 82 | { 83 | hitData.color = 0;// float4(0.38f, 0.52f, 0.10f, 1); 84 | hitData.hitT = -1; 85 | hitData.throughput = 0; 86 | } 87 | 88 | bool checkLightHit(uint lightIndex, float3 origin) 89 | { 90 | float3 direction = gLights[lightIndex].posW - origin; 91 | RayDesc ray; 92 | ray.Origin = origin; 93 | ray.Direction = normalize(direction); 94 | ray.TMin = 0.001; 95 | ray.TMax = max(0.01, length(direction)); 96 | 97 | ShadowRayData rayData; 98 | rayData.hit = true; 99 | TraceRay(gRtScene, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xFF, 1 /* ray index */, hitProgramCount, 1, ray, rayData); 100 | return rayData.hit; 101 | } 102 | 103 | void getSample(SamplerState samplerState, float2 uv, out float3 causticsClr, out float3 normal, out float depth) 104 | { 105 | causticsClr = gCausticsTex.SampleLevel(samplerState, uv, 0).rgb; 106 | normal = gNormalTex.SampleLevel(samplerState, uv, 0).rgb; 107 | depth = gDepthTex.SampleLevel(samplerState, uv, 0).r; 108 | 109 | depth = toViewSpace(invProj, depth); 110 | //float4 screenPnt = float4(uv * float2(2, -2) + float2(-1, 1), depth, 1); 111 | //float4 worldPnt = mul(screenPnt, invProj); 112 | //pos = worldPnt.xyz / worldPnt.w; 113 | } 114 | 115 | float getWeight(float2 offset, float3 normal0, float3 normal1, float z0, float z1) 116 | { 117 | float normalDiff = gNormalKernel * (1 - saturate(dot(normal0, normal1))); 118 | //float3 dPos = pos0 - pos1; 119 | float zDiff = gZKernel * abs(z0 - z1);// (length(dPos)); 120 | float uvDiff = gPosKernel * length(offset); 121 | //float x = zDiff * normalDiff * uvDiff * gPosKernel;// *zDiff * 1; 122 | return exp(-1 * (zDiff * zDiff + normalDiff * normalDiff + uvDiff * uvDiff)); 123 | } 124 | 125 | [shader("closesthit")] 126 | void primaryClosestHit(inout HitData hitData, in BuiltInTriangleIntersectionAttributes attribs) 127 | { 128 | float3 rayOrigW = WorldRayOrigin(); 129 | float3 rayDirW = WorldRayDirection(); 130 | float hitT = RayTCurrent(); 131 | uint triangleIndex = PrimitiveIndex(); 132 | 133 | // prepare the shading data 134 | float3 posW = rayOrigW + hitT * rayDirW; 135 | VertexOut v = getVertexAttributes(triangleIndex, attribs); 136 | ShadingData sd = prepareShadingData(v, gMaterial, rayOrigW, 0); 137 | 138 | float3 color = 0; 139 | if(sd.linearRoughness > roughThreshold || sd.opacity < 1) 140 | { 141 | bool isReflect = (sd.opacity == 1); 142 | float3 R; 143 | float eta = iorOverride > 0 ? 1.0 / iorOverride : 1.0 / sd.IoR; 144 | float3 N = v.normalW; 145 | if (!isReflect) 146 | { 147 | if (dot(N, rayDirW) > 0) 148 | { 149 | eta = 1.0 / eta; 150 | N *= -1; 151 | } 152 | isReflect = isTotalInternalReflection(rayDirW, N, eta); 153 | } 154 | 155 | if (isReflect) 156 | { 157 | R = reflect(rayDirW, N); 158 | } 159 | else 160 | { 161 | getRefractVector(rayDirW, N, R, eta); 162 | } 163 | 164 | float3 baseColor = lerp(1, sd.diffuse, sd.opacity); 165 | color = 0; 166 | hitData.nextDir = R; 167 | hitData.throughput = baseColor; 168 | } 169 | else 170 | { 171 | float4 posS = mul(float4(posW,1), gCamera.viewProjMat); 172 | posS /= posS.w; 173 | if (all(posS.xy < 1)) 174 | { 175 | posS.y *= -1; 176 | float2 texCoord = (posS.xy + 1) * 0.5; 177 | float3 clr0, nor0; 178 | float z0; 179 | getSample(gLinearSampler, texCoord, clr0, nor0, z0); 180 | 181 | float totalWeight = 1; 182 | float3 causticsClr = clr0; 183 | if (gPosKernel > 0 || gZKernel > 0 || gNormalKernel > 0) 184 | { 185 | float2 dir[] = { 186 | float2(-1,-1), float2(-1,0), float2(-1,1), 187 | float2(0,-1), float2(0,1), 188 | float2(1,-1), float2(1,0), float2(1,1), 189 | }; 190 | [unroll] 191 | for (int i = 0; i < 8; i++) 192 | { 193 | float2 sampleUV = texCoord + dir[i] / (viewportDims / causticsResRatio); 194 | float3 clr, nor; 195 | float z; 196 | getSample(gLinearSampler, sampleUV, clr, nor, z); 197 | float w = getWeight(dir[i],nor0, nor, z0, z); 198 | causticsClr += clr * w; 199 | totalWeight += w; 200 | //color += w; 201 | } 202 | } 203 | causticsClr /= totalWeight; 204 | 205 | color += sd.diffuse* causticsClr;// gCausticsTex.SampleLevel(gLinearSampler, texCoord, 0).rgb; 206 | } 207 | [unroll] 208 | for (int i = 0; i < gLightsCount; i++) 209 | { 210 | if (checkLightHit(i, posW) == false) 211 | { 212 | color += evalMaterial(sd, gLights[i], 1).color.xyz; 213 | } 214 | } 215 | 216 | hitData.throughput = 0; 217 | } 218 | 219 | hitData.color.rgb = color; 220 | hitData.hitT = hitT; 221 | hitData.color.rgb += sd.emissive; 222 | } 223 | 224 | [shader("raygeneration")] 225 | void rayGen() 226 | { 227 | uint3 launchIndex = DispatchRaysIndex(); 228 | uint randSeed = rand_init(launchIndex.x + launchIndex.y * viewportDims.x, sampleIndex, 16); 229 | 230 | RayDesc ray; 231 | if (!useDOF) 232 | { 233 | ray = generateRay(gCamera, launchIndex.xy, viewportDims); 234 | } 235 | else 236 | { 237 | ray = generateDOFRay(gCamera, launchIndex.xy, viewportDims, randSeed); 238 | } 239 | 240 | float3 totalColor = 0; 241 | float3 totalThroughput = 1; 242 | for (int i = 0; i < maxDepth && any(totalThroughput > 0); i++) 243 | { 244 | HitData hitData; 245 | TraceRay(gRtScene, 0, 0xFF, 0, hitProgramCount, 0, ray, hitData); 246 | 247 | totalColor += totalThroughput * hitData.color.rgb; 248 | totalThroughput *= hitData.throughput; 249 | 250 | ray.Origin = ray.Origin + ray.Direction * hitData.hitT; 251 | ray.Direction = hitData.nextDir; 252 | ray.TMin = 0.001; 253 | ray.TMax = 100000; 254 | } 255 | 256 | gOutput[launchIndex.xy] = float4(totalColor,1); 257 | } 258 | -------------------------------------------------------------------------------- /Data/GPass.ps.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | __import ShaderCommon; 29 | __import Shading; 30 | __import DefaultVS; 31 | 32 | struct GPassPsOut 33 | { 34 | float4 normal: SV_TARGET0; 35 | float4 diffuse: SV_TARGET1; 36 | float4 specular: SV_TARGET2; 37 | }; 38 | 39 | GPassPsOut gpassPS(VertexOut vOut) : SV_TARGET 40 | { 41 | ShadingData sd = prepareShadingData(vOut, gMaterial, gCamera.posW); 42 | 43 | if (sd.opacity < 1) 44 | { 45 | discard; 46 | } 47 | GPassPsOut output; 48 | output.normal = float4(normalize(vOut.normalW.xyz), 1); 49 | output.diffuse = float4(sd.diffuse, sd.linearRoughness); 50 | output.specular = float4(sd.specular, sd.opacity); 51 | return output; 52 | } 53 | -------------------------------------------------------------------------------- /Data/GenerateRayCountMipmap.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | int2 taskDim; 33 | int2 screenDim; 34 | int mipLevel; 35 | }; 36 | 37 | //RWStructuredBuffer gPhotonBuffer; 38 | //RWStructuredBuffer gDrawArgument; 39 | RWStructuredBuffer gRayArgument; 40 | //RWStructuredBuffer gRayTask; 41 | //StructuredBuffer gPixelInfo; 42 | //Texture2D gDepthTex; 43 | Texture2D gRayDensityTex; 44 | RWStructuredBuffer gRayCountQuadTree; 45 | 46 | int getRayTaskID(uint2 pos) 47 | { 48 | return pos.y * taskDim.x + pos.x; 49 | } 50 | 51 | uint getSampleCount(float v00, float v10, float v01, float v11) 52 | { 53 | float sampleCountF = 0.25 * (v00 + v10 + v01 + v11); 54 | int sampleDim = (int)ceil(sqrt(sampleCountF)); 55 | uint sampleCount = sampleDim * sampleDim; 56 | return sampleCount; 57 | } 58 | 59 | [numthreads(8, 8, 1)] 60 | void generateMip0(uint3 groupID : SV_GroupID, uint groupIndex : SV_GroupIndex, uint3 threadIdx : SV_DispatchThreadID) 61 | { 62 | uint rayIdx = getRayTaskID(threadIdx.xy); 63 | //gPixelInfo[rayIdx].screenArea = 0; 64 | //gPixelInfo[rayIdx].screenAreaSq = 0; 65 | //gPixelInfo[rayIdx].count = 0; 66 | 67 | //int idx0 = gPixelInfo[rayIdx].photonIdx; 68 | 69 | int2 pixel00 = threadIdx.xy*2; 70 | float v00 = gRayDensityTex.Load(int3(pixel00 + int2(0, 0), 0)).r; 71 | float v10 = gRayDensityTex.Load(int3(pixel00 + int2(1, 0), 0)).r; 72 | float v20 = gRayDensityTex.Load(int3(pixel00 + int2(2, 0), 0)).r; 73 | 74 | float v01 = gRayDensityTex.Load(int3(pixel00 + int2(0, 1), 0)).r; 75 | float v11 = gRayDensityTex.Load(int3(pixel00 + int2(1, 1), 0)).r; 76 | float v21 = gRayDensityTex.Load(int3(pixel00 + int2(2, 1), 0)).r; 77 | 78 | float v02 = gRayDensityTex.Load(int3(pixel00 + int2(0, 2), 0)).r; 79 | float v12 = gRayDensityTex.Load(int3(pixel00 + int2(1, 2), 0)).r; 80 | float v22 = gRayDensityTex.Load(int3(pixel00 + int2(2, 2), 0)).r; 81 | 82 | uint count00 = getSampleCount(v00, v10, v01, v11); 83 | uint count10 = count00 + getSampleCount(v10, v20, v11, v21); 84 | uint count01 = count10 + getSampleCount(v01, v11, v02, v12); 85 | uint count11 = count01 + getSampleCount(v11, v21, v12, v22); 86 | //int sampleCount = count00 + count10 + count01 + count11; 87 | //int taskIdx = 0; 88 | //InterlockedAdd(gRayArgument[0].rayTaskCount, sampleCount, taskIdx); 89 | 90 | int offset = getTextureOffset(threadIdx.xy, mipLevel); 91 | gRayCountQuadTree[offset] = uint4(count00, count10, count01, count11); 92 | } 93 | 94 | [numthreads(8, 8, 1)] 95 | void generateMipLevel(uint3 threadIdx : SV_DispatchThreadID) 96 | { 97 | int mipDim = getMipSize(mipLevel); 98 | if (any(threadIdx.xy >= mipDim)) 99 | { 100 | return; 101 | } 102 | 103 | int2 pixel00 = threadIdx.xy * 2; 104 | int nextMipLevel = mipLevel + 1; 105 | uint4 count00 = gRayCountQuadTree[getTextureOffset(pixel00 + int2(0, 0), nextMipLevel)]; 106 | uint4 count10 = gRayCountQuadTree[getTextureOffset(pixel00 + int2(1, 0), nextMipLevel)]; 107 | uint4 count01 = gRayCountQuadTree[getTextureOffset(pixel00 + int2(0, 1), nextMipLevel)]; 108 | uint4 count11 = gRayCountQuadTree[getTextureOffset(pixel00 + int2(1, 1), nextMipLevel)]; 109 | 110 | uint4 value; 111 | value.x = count00.w; 112 | value.y = value.x + count10.w; 113 | value.z = value.y + count01.w; 114 | value.w = value.z + count11.w; 115 | gRayCountQuadTree[getTextureOffset(threadIdx.xy, mipLevel)] = value;// value; 116 | } 117 | -------------------------------------------------------------------------------- /Data/PhotonGather.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | float4x4 gInvViewProjMat; 33 | int2 screenDim; 34 | int2 tileDim; 35 | float gSplatSize; 36 | float gDepthRadius; 37 | int gShowTileCount; 38 | int gTileCountScale; 39 | float gKernelPower; 40 | int causticsMapResRatio; 41 | }; 42 | 43 | struct DrawArguments 44 | { 45 | uint indexCountPerInstance; 46 | uint instanceCount; 47 | uint startIndexLocation; 48 | int baseVertexLocation; 49 | uint startInstanceLocation; 50 | }; 51 | 52 | 53 | StructuredBuffer gPhotonBuffer; 54 | StructuredBuffer gTileInfo; 55 | ByteAddressBuffer gIDBuffer; 56 | 57 | Texture2D gDepthTex; 58 | Texture2D gNormalTex; 59 | RWTexture2D gPhotonTex; 60 | 61 | #define PHOTON_CACHE_SIZE 64 62 | 63 | groupshared Photon photonList[PHOTON_CACHE_SIZE]; 64 | groupshared float3 normalList[PHOTON_CACHE_SIZE]; 65 | groupshared int photonCount; 66 | groupshared int beginAddress; 67 | 68 | #define NUM_GROUP_PER_TILE 2 69 | #define BLOCK_SIZE_X GATHER_TILE_SIZE_X 70 | #define BLOCK_SIZE_Y (GATHER_TILE_SIZE_Y/NUM_GROUP_PER_TILE) 71 | 72 | int getTileOffset(int x, int y) 73 | { 74 | return tileDim.x * y + x; 75 | } 76 | 77 | float getLightFactor(float3 pos, float3 photonPos, float3 dPdx, float3 dPdy, float3 normal) 78 | { 79 | float3 dPos = pos - photonPos; 80 | float3 localCoord = float3(dot(dPdx, dPos), dot(dPdy, dPos), dot(normal, dPos)); 81 | float r = length(localCoord); 82 | return pow(saturate(smoothKernel(r)), gKernelPower); 83 | } 84 | 85 | [numthreads(BLOCK_SIZE_X, BLOCK_SIZE_Y, 1)] 86 | void main(uint3 groupID : SV_GroupID, uint3 groupThreadID : SV_GroupThreadID, uint3 threadIdx : SV_DispatchThreadID) 87 | { 88 | uint2 tileID = groupID.xy; 89 | uint2 pixelTileIndex = groupThreadID.xy;// threadIdx.xy - tileID * GATHER_TILE_SIZE; 90 | uint2 pixelLocation0 = tileID * uint2(GATHER_TILE_SIZE_X, GATHER_TILE_SIZE_Y) + pixelTileIndex; 91 | 92 | float3 worldPnt[NUM_GROUP_PER_TILE]; 93 | [unroll] 94 | for (int i = 0; i < NUM_GROUP_PER_TILE; i++) 95 | { 96 | uint2 pixelLocation = pixelLocation0 + uint2(0, i * BLOCK_SIZE_Y); 97 | float depth = gDepthTex.Load(int3(pixelLocation * causticsMapResRatio, 0)).r; 98 | //float3 normal = gNormalTex.Load(int3(pixelLocation* causticsMapResRatio,0)).rgb; 99 | float2 uv = pixelLocation / float2(screenDim); 100 | float4 ndc = float4(uv * float2(2, -2) + float2(-1, 1), depth, 1); 101 | float4 worldPnt0 = mul(ndc, gInvViewProjMat); 102 | worldPnt[i] = worldPnt0.xyz / worldPnt0.w; 103 | } 104 | 105 | if (all(groupThreadID == uint3(0,0,0))) 106 | { 107 | int tileOffset = getTileOffset(tileID.x, tileID.y); 108 | beginAddress = gTileInfo[tileOffset].address; 109 | photonCount = gTileInfo[tileOffset].count; 110 | } 111 | GroupMemoryBarrierWithGroupSync(); 112 | 113 | if (gShowTileCount) 114 | { 115 | float intensity = float(photonCount) / gTileCountScale; 116 | float4 color; 117 | if (intensity <= 1) 118 | { 119 | color = float4(intensity.xxx, 1); 120 | } 121 | else 122 | { 123 | color = float4(1, 0, 0, 1); 124 | } 125 | [unroll] 126 | for (int i = 0; i < NUM_GROUP_PER_TILE; i++) 127 | { 128 | uint2 pixelLocation = pixelLocation0 + uint2(0, i * BLOCK_SIZE_Y); 129 | if (all(pixelLocation < screenDim)) 130 | gPhotonTex[pixelLocation] = color; 131 | } 132 | return; 133 | } 134 | 135 | float3 totalLight[NUM_GROUP_PER_TILE]; 136 | [unroll] 137 | for (int i = 0; i < NUM_GROUP_PER_TILE; i++) 138 | totalLight[i] = 0; 139 | 140 | int threadGroupOffset = pixelTileIndex.y * BLOCK_SIZE_X + pixelTileIndex.x; 141 | for (int photonIdx = 0; photonIdx < photonCount; photonIdx+= PHOTON_CACHE_SIZE) 142 | { 143 | int idOffset = photonIdx + threadGroupOffset; 144 | if (threadGroupOffset < PHOTON_CACHE_SIZE && idOffset < photonCount) 145 | { 146 | int id = gIDBuffer.Load((beginAddress + idOffset) * 4); 147 | Photon p = gPhotonBuffer[id]; 148 | p.dPdx /= dot(p.dPdx, p.dPdx); 149 | p.dPdy /= dot(p.dPdy, p.dPdy); 150 | photonList[threadGroupOffset] = p; 151 | normalList[threadGroupOffset] = normalize(cross(p.dPdx, p.dPdy)) / (gDepthRadius * gSplatSize); 152 | } 153 | GroupMemoryBarrierWithGroupSync(); 154 | 155 | for (int i = 0; i < min(PHOTON_CACHE_SIZE, photonCount - photonIdx); i++) 156 | { 157 | Photon p = photonList[i]; 158 | float3 normal = normalList[i]; 159 | for (int ithPixel = 0; ithPixel < NUM_GROUP_PER_TILE; ithPixel++) 160 | { 161 | float lightFactor = getLightFactor(worldPnt[ithPixel], p.posW, p.dPdx, p.dPdy, normal); 162 | totalLight[ithPixel] += lightFactor * p.color; 163 | } 164 | } 165 | GroupMemoryBarrierWithGroupSync(); 166 | } 167 | 168 | [unroll] 169 | for (int i = 0; i < NUM_GROUP_PER_TILE; i++) 170 | { 171 | uint2 pixelLocation = pixelLocation0 + uint2(0, i * BLOCK_SIZE_Y); 172 | if (all(pixelLocation < screenDim)) 173 | gPhotonTex[pixelLocation] = float4(totalLight[i], photonCount); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /Data/PhotonScatter.ps.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | __import ShaderCommon; 29 | __import Shading; 30 | __import DefaultVS; 31 | 32 | #include "Common.hlsl" 33 | 34 | StructuredBuffer gPhotonBuffer; 35 | StructuredBuffer gRayTask; 36 | 37 | Texture2D gDepthTex; 38 | Texture2D gNormalTex; 39 | Texture2D gDiffuseTex; 40 | Texture2D gSpecularTex; 41 | 42 | Texture2D gGaussianTex; 43 | 44 | SamplerState gLinearSampler; 45 | 46 | cbuffer PerFrameCB : register(b0) 47 | { 48 | float4x4 gWvpMat; 49 | float4x4 gWorldMat; 50 | float4x4 gInvProjMat; 51 | 52 | float3 gEyePosW; 53 | float gLightIntensity; 54 | 55 | float3 gLightDir; 56 | float gKernelPower; 57 | 58 | int2 taskDim; 59 | uint gShowPhoton; 60 | float normalThreshold; 61 | 62 | float distanceThreshold; 63 | float planarThreshold; 64 | float gSurfaceRoughness; 65 | float gSplatSize; 66 | 67 | int2 screenDim; 68 | uint gPhotonMode; 69 | float gMaxAnisotropy; 70 | 71 | float3 gCameraPos; 72 | float gMaxScreenRadius; 73 | 74 | float gZTolerance; 75 | int gResRatio; 76 | }; 77 | #define AnisotropicPhoton 0 78 | #define IsotropicPhoton 1 79 | #define PhotonMesh 2 80 | #define ScreenDot 3 81 | #define ScreenDotWithColor 4 82 | 83 | #define SHOW_PHOTON_KERNEL 0 84 | #define SHOW_PHOTON_SOLID 1 85 | #define SHOW_PHOTON_SHADED 2 86 | 87 | struct PhotonVSIn 88 | { 89 | float4 pos : POSITION; 90 | float3 normal : NORMAL; 91 | float2 texC : TEXCOORD; 92 | uint instanceID : SV_INSTANCEID; 93 | uint vertexID: SV_VERTEXID; 94 | }; 95 | 96 | struct PhotonVSOut 97 | { 98 | float4 posH : SV_POSITION; 99 | float2 texcoord: TEXCOORD0; 100 | float4 color : COLOR; 101 | }; 102 | 103 | int GetPhoton(int2 screenPos, inout Photon p) 104 | { 105 | int offset = screenPos.y * taskDim.x + screenPos.x; 106 | int photonIdx = gRayTask[offset].photonIdx; 107 | if (photonIdx == -1) 108 | { 109 | return 0; 110 | } 111 | p = gPhotonBuffer[photonIdx]; 112 | return 1; 113 | } 114 | 115 | void ProcessPhoton(inout Photon p, float2 dir) 116 | { 117 | p.dPdx *= dir.x; 118 | p.dPdy *= -dir.y; 119 | } 120 | 121 | bool isAdjacent(Photon photon0, Photon photon1, float3 axis, float normalThreshold, float distanceThreshold, float planarThreshold) 122 | { 123 | float proj = abs(dot(photon1.posW - photon0.posW, axis)); 124 | //float dist = proj / length(axis); 125 | float dist = length(photon1.posW - photon0.posW); 126 | return 127 | //dot(photon0.normalW, photon1.normalW) < normalThreshold && 128 | dist < distanceThreshold// && 129 | //dot(photon0.normalW, photon0.posW - photon1.posW) < planarThreshold 130 | ; 131 | } 132 | 133 | bool GetPhotons(int instanceID, float2 vertex, inout Photon p00, inout Photon p01, inout Photon p10, inout Photon p11, out int mask) 134 | { 135 | mask = 0; 136 | int2 screenPos; 137 | screenPos.y = instanceID / taskDim.x; 138 | screenPos.x = instanceID - taskDim.x * screenPos.y; 139 | if (!GetPhoton(screenPos, p00)) 140 | { 141 | return false; 142 | } 143 | 144 | //int xOffset = vertex.x;// (vertexID & 0x1) * 2 - 1; 145 | //int yOffset = vertex.y;// (vertexID >> 1) * 2 - 1; 146 | //int2 offsetArray[] = { int2(-1,1), int2(1,-1), int2(-1,-1), int2(1,1) }; 147 | float2 offset = vertex;// offsetArray[vertexID]; 148 | 149 | ProcessPhoton(p00, offset); 150 | if (GetPhoton(screenPos + int2(offset.x, 0), p01)) 151 | { 152 | ProcessPhoton(p01, offset); 153 | if (isAdjacent(p00, p01, p00.dPdx, normalThreshold, distanceThreshold, planarThreshold)) 154 | mask |= 0x1; 155 | } 156 | if (GetPhoton(screenPos + int2(0, offset.y), p10)) 157 | { 158 | ProcessPhoton(p10, offset); 159 | if (isAdjacent(p00, p10, p00.dPdy, normalThreshold, distanceThreshold, planarThreshold)) 160 | mask |= 0x2; 161 | } 162 | if (GetPhoton(screenPos + offset, p11)) 163 | { 164 | ProcessPhoton(p11, offset); 165 | if (isAdjacent(p00, p11, p00.dPdx+ p00.dPdy, normalThreshold, distanceThreshold * 1.42, planarThreshold)) 166 | mask |= 0x4; 167 | } 168 | 169 | return true; 170 | } 171 | 172 | void GetVertexPosInfo(Photon p00, Photon p01, Photon p10, Photon p11, int mask, out float3 posW, out float3 color) 173 | { 174 | if (mask ==0) 175 | { 176 | posW = p00.posW + gSplatSize * (p00.dPdx + p00.dPdy); 177 | color = 0;// p00.color; 178 | } 179 | else if (mask == 1) 180 | { 181 | posW = 0.5 * (p00.posW + p01.posW) + gSplatSize * 0.5 * (p00.dPdy + p01.dPdy); 182 | color = 0;// float3(0, 0, 100); 183 | } 184 | else if (mask == 2) 185 | { 186 | posW = 0.5 * (p00.posW + p10.posW) + gSplatSize * 0.5 * (p00.dPdx + p10.dPdx); 187 | color = 0;// float3(100, 0, 100); 188 | } 189 | else if (mask == 3) 190 | { 191 | posW = 0.5 * (p10.posW + p01.posW); 192 | color = 0;// float3(0, 100, 0); 193 | } 194 | else if (mask == 4 || mask == 5 || mask == 6) 195 | { 196 | posW = 0.5 * (p00.posW + p11.posW); 197 | color = 0;// float3(100, 0, 0);// 0; 198 | } 199 | else if (mask == 7) 200 | { 201 | posW = 0.25 * (p00.posW + p01.posW + p10.posW + p11.posW); 202 | color.rgb = 0.25 * (p00.color + p01.color + p10.color + p11.color); 203 | } 204 | //float newDist = length(posW - p00.posW); 205 | //float oldDist = length(p00.dPdx + p00.dPdy) * 0.5; 206 | //float distRatio = newDist / oldDist; 207 | //float areaRatio = distRatio * distRatio; 208 | //color *= areaRatio; 209 | } 210 | 211 | bool meshScatter(int instanceID, float2 vertex, out float4 posH, out float3 color) 212 | { 213 | color = 0; 214 | posH = float4(100, 100, 100, 1); 215 | Photon p00, p01, p10, p11; 216 | int mask = 0; 217 | if (!GetPhotons(instanceID, vertex, p00, p01, p10, p11, mask)) 218 | return false; 219 | 220 | float3 posW; 221 | GetVertexPosInfo(p00, p01, p10, p11, mask, posW, color); 222 | posH = mul(float4(posW, 1), gWvpMat); 223 | return true; 224 | } 225 | 226 | float3 scaleVector(float3 vec, float3 axis, float2 factor) 227 | { 228 | axis = normalize(axis); 229 | float proj = dot(vec, axis); 230 | vec *= factor.y; 231 | vec += axis * proj * (factor.x - factor.y); 232 | return vec; 233 | } 234 | 235 | PhotonVSOut photonScatterVS(PhotonVSIn vIn) 236 | { 237 | PhotonVSOut vOut; 238 | vOut.texcoord = vIn.pos.xz;// (vIn.pos.xz + 1) * 0.5; 239 | 240 | float3 tangent, bitangent, color; 241 | if (gPhotonMode == PhotonMesh) 242 | { 243 | float4 posH = 0; 244 | float3 clr = 0; 245 | meshScatter(vIn.instanceID, vIn.pos.xz, posH, clr); 246 | vOut.posH = posH; 247 | vOut.color = float4(clr,1); 248 | return vOut; 249 | } 250 | 251 | Photon p = gPhotonBuffer[vIn.instanceID]; 252 | float3 normal = normalize(cross(p.dPdx, p.dPdy)); 253 | 254 | if (gPhotonMode == AnisotropicPhoton) 255 | { 256 | tangent = p.dPdx; 257 | bitangent = p.dPdy; 258 | if (dot(tangent, bitangent) < 0) 259 | { 260 | bitangent *= -1; 261 | } 262 | 263 | float3 areaVector = cross(tangent, bitangent); 264 | float3 sideVector = tangent + bitangent; 265 | float area = length(areaVector); 266 | float side = length(sideVector); 267 | float height = area / side; 268 | float aniso = side / height; 269 | if (aniso > gMaxAnisotropy) 270 | { 271 | tangent = scaleVector(tangent, sideVector, float2(gMaxAnisotropy/ aniso, 1)); 272 | bitangent = scaleVector(bitangent, sideVector, float2(gMaxAnisotropy/aniso, 1)); 273 | } 274 | } 275 | else if (gPhotonMode == IsotropicPhoton) 276 | { 277 | tangent = normalize(float3(normal.y, -normal.x, 0)); 278 | bitangent = cross(tangent, normal); 279 | float radius = max(length(p.dPdx), length(p.dPdy)); 280 | tangent *= radius; 281 | bitangent *= radius; 282 | } 283 | else 284 | { 285 | tangent = normalize(float3(normal.y, -normal.x, 0)); 286 | bitangent = cross(tangent, normal); 287 | } 288 | 289 | tangent *= gSplatSize; 290 | bitangent *= gSplatSize; 291 | //normal *= gSplatSize; 292 | 293 | float3 areaVector = cross(tangent, bitangent); 294 | 295 | if (gPhotonMode == ScreenDot) 296 | { 297 | vOut.posH = mul(float4(p.posW, 1), gWvpMat); 298 | vOut.posH.xy += vIn.pos.xz * vOut.posH.w / screenDim.xy * gSplatSize; 299 | color = 1; 300 | } 301 | else if (gPhotonMode == ScreenDotWithColor) 302 | { 303 | vOut.posH = mul(float4(p.posW, 1), gWvpMat); 304 | vOut.posH.xy += vIn.pos.xz * vOut.posH.w / screenDim.xy * gSplatSize; 305 | float3 viewDir = p.posW - gCameraPos; 306 | float viewLength = length(viewDir); 307 | viewDir /= viewLength; 308 | float projArea = abs(dot(areaVector, viewDir)) / (viewLength * viewLength) * length(screenDim.xy);// *0.2; 309 | color = p.color*8;// *projArea;// / (gSplatSize * gSplatSize); 310 | //color = p.color * projArea; 311 | } 312 | else 313 | { 314 | float3 localPoint = tangent * vIn.pos.x + bitangent * vIn.pos.z + normal * vIn.pos.y * gSplatSize*0.05; 315 | vOut.posH = mul(float4(localPoint + p.posW, 1), gWvpMat); 316 | color = p.color; 317 | } 318 | 319 | if (gShowPhoton == SHOW_PHOTON_SHADED) 320 | { 321 | float3 surfNormal = normalize(tangent * vIn.normal.x + bitangent * vIn.normal.z + normal * vIn.normal.y* gSplatSize); 322 | vOut.color = float4(abs(dot(float3(1,1,1), surfNormal)), 1); 323 | } 324 | else 325 | vOut.color = float4(color, 1); 326 | 327 | return vOut; 328 | } 329 | 330 | float sinc(float x, float c) 331 | { 332 | return sin(x * c) / (x * c); 333 | } 334 | 335 | float4 photonScatterPS(PhotonVSOut vOut) : SV_TARGET 336 | { 337 | float depth = gDepthTex.Load(int3(vOut.posH.xy* gResRatio, 0)).x; 338 | depth = toViewSpace(gInvProjMat, depth); 339 | 340 | float pixelZ = -vOut.posH.w;// toViewSpace(vOut.posH.z, vOut.posH.w); 341 | if (gShowPhoton == SHOW_PHOTON_SHADED) 342 | { 343 | return float4(1, 1, 0, 1)* vOut.color; 344 | } 345 | 346 | float zDiff = pixelZ - depth; 347 | if (abs(zDiff) > gZTolerance) 348 | { 349 | discard; 350 | } 351 | 352 | float alpha; 353 | if (gShowPhoton == SHOW_PHOTON_SOLID || gPhotonMode == PhotonMesh || gPhotonMode == ScreenDot || gPhotonMode == ScreenDotWithColor) 354 | { 355 | alpha = 1; 356 | } 357 | else 358 | { 359 | alpha = smoothKernel(length(float3(vOut.texcoord.xy, zDiff)));//gGaussianTex.Sample(gLinearSampler, vOut.texcoord).r; 360 | const float c = gKernelPower*10; 361 | //alpha = sinc(length(vOut.texcoord.xy), c); 362 | //alpha = sinc(vOut.texcoord.x, c)* sinc(vOut.texcoord.y, c); 363 | alpha = pow(alpha, gKernelPower); 364 | } 365 | return float4(vOut.color.rgb * alpha, 1); 366 | } 367 | -------------------------------------------------------------------------------- /Data/PhotonTrace.rt.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | __import Raytracing; 30 | __import ShaderCommon; 31 | __import Shading; 32 | import Helpers; 33 | 34 | RWStructuredBuffer gPhotonBuffer; 35 | RWStructuredBuffer gDrawArgument; 36 | RWStructuredBuffer gRayArgument; 37 | RWStructuredBuffer gRayTask; 38 | RWStructuredBuffer gPixelInfo; 39 | 40 | StructuredBuffer gRayCountQuadTree; 41 | Texture2D gRayDensityTex; 42 | Texture2D gUniformNoise; 43 | 44 | Texture2D gPhotonTexture; 45 | RWTexture2D gSmallPhotonBuffer; 46 | 47 | shared cbuffer PerFrameCB 48 | { 49 | float4x4 invView; 50 | 51 | float2 viewportDims; 52 | uint2 coarseDim; 53 | 54 | float2 randomOffset; 55 | float emitSize; 56 | float roughThreshold; 57 | 58 | int gMipmap; 59 | int rayTaskOffset; 60 | int maxDepth; 61 | float iorOverride; 62 | 63 | uint colorPhotonID; 64 | int photonIDScale; 65 | float traceColorThreshold; 66 | float cullColorThreshold; 67 | 68 | uint gAreaType; 69 | float gIntensity; 70 | float gSplatSize; 71 | uint updatePhoton; 72 | 73 | float gMaxScreenRadius; 74 | float gMinScreenRadius; 75 | float gMinDrawCount; 76 | float gSmallPhotonColorScale; 77 | 78 | float3 cameraPos; 79 | }; 80 | 81 | struct CausticsPackedPayload 82 | { 83 | #ifdef SMALL_COLOR 84 | uint colorAndFlag; 85 | #else 86 | float3 color; 87 | uint isContinue; 88 | #endif 89 | float hitT; 90 | float3 nextDir; 91 | 92 | #ifdef RAY_DIFFERENTIAL 93 | #ifdef SMALL_RAY_DIFFERENTIAL 94 | uint3 dP, dD; 95 | #else 96 | float3 dPdx, dPdy, dDdx, dDdy; // ray differentials 97 | #endif 98 | #elif defined(RAY_CONE) 99 | float radius; 100 | float dRadius; 101 | #elif defined(RAY_NONE) 102 | #endif 103 | }; 104 | 105 | struct CausticsUnpackedPayload 106 | { 107 | float3 color; 108 | float hitT; 109 | float3 nextDir; 110 | uint isContinue; 111 | #ifdef RAY_DIFFERENTIAL 112 | float3 dPdx, dPdy, dDdx, dDdy; // ray differentials 113 | #elif defined(RAY_CONE) 114 | float radius; 115 | float dRadius; 116 | #elif defined(RAY_NONE) 117 | #endif 118 | }; 119 | 120 | #ifdef SMALL_COLOR 121 | 122 | uint colorRayToUint(float3 color, uint isContinue) 123 | { 124 | uint3 colorI = color * 255; 125 | return (colorI.r << 24) | (colorI.g << 16) | (colorI.b << 8) | (isContinue & 0x1); 126 | } 127 | 128 | void uintToColorRay(uint i, 129 | out float3 color, out uint isContinue) 130 | { 131 | isContinue = i & 0x1; 132 | uint3 colorI = uint3(i >> 24, i >> 16, i >> 8); 133 | colorI = (colorI & 0xff); 134 | color = colorI / 255.0; 135 | } 136 | #endif 137 | 138 | #ifdef SMALL_RAY_DIFFERENTIAL 139 | uint3 float3ToUint3(float3 a, float3 b) 140 | { 141 | uint3 res; 142 | res.x = ((f32tof16(a.x) << 16) | f32tof16(a.y)); 143 | res.y = ((f32tof16(a.z) << 16) | f32tof16(b.x)); 144 | res.z = ((f32tof16(b.y) << 16) | f32tof16(b.z)); 145 | return res; 146 | } 147 | 148 | void uint3ToFloat3(uint3 i, out float3 a, out float3 b) 149 | { 150 | a.x = f16tof32(i.x >> 16); 151 | a.y = f16tof32(i.x & 0xffff); 152 | a.z = f16tof32(i.y >> 16); 153 | b.x = f16tof32(i.y & 0xffff); 154 | b.y = f16tof32(i.z >> 16); 155 | b.z = f16tof32(i.z & 0xffff); 156 | } 157 | #endif 158 | 159 | void unpackCausticsPayload(CausticsPackedPayload p, out CausticsUnpackedPayload d) 160 | { 161 | #ifdef SMALL_COLOR 162 | uintToColorRay(p.colorAndFlag, d.color, d.isContinue); 163 | #else 164 | d.color = p.color; 165 | d.isContinue = p.isContinue; 166 | #endif 167 | d.nextDir = p.nextDir; 168 | d.hitT = p.hitT; 169 | 170 | #ifdef RAY_DIFFERENTIAL 171 | #ifdef SMALL_RAY_DIFFERENTIAL 172 | uint3ToFloat3(p.dP, d.dPdx, d.dPdy); 173 | uint3ToFloat3(p.dD, d.dDdx, d.dDdy); 174 | #else 175 | d.dPdx = p.dPdx; 176 | d.dPdy = p.dPdy; 177 | d.dDdx = p.dDdx; 178 | d.dDdy = p.dDdy; 179 | #endif 180 | #elif defined(RAY_CONE) 181 | d.radius = p.radius; 182 | d.dRadius = p.dRadius; 183 | #elif defined(RAY_NONE) 184 | #endif 185 | } 186 | 187 | void packCausticsPayload(CausticsUnpackedPayload d, out CausticsPackedPayload p) 188 | { 189 | #ifdef SMALL_COLOR 190 | p.colorAndFlag = colorRayToUint(d.color, d.isContinue); 191 | #else 192 | p.color = d.color; 193 | p.isContinue = d.isContinue; 194 | #endif 195 | p.hitT = d.hitT; 196 | p.nextDir = d.nextDir; 197 | 198 | #ifdef RAY_DIFFERENTIAL 199 | #ifdef SMALL_RAY_DIFFERENTIAL 200 | p.dP = float3ToUint3(d.dPdx, d.dPdy); 201 | p.dD = float3ToUint3(d.dDdx, d.dDdy); 202 | #else 203 | p.dPdx = d.dPdx; 204 | p.dPdy = d.dPdy; 205 | p.dDdx = d.dDdx; 206 | p.dDdy = d.dDdy; 207 | #endif 208 | #elif defined(RAY_CONE) 209 | p.radius = d.radius; 210 | p.dRadius = d.dRadius; 211 | #elif defined(RAY_NONE) 212 | #endif 213 | } 214 | 215 | struct ShadowRayData 216 | { 217 | bool hit; 218 | }; 219 | 220 | [shader("miss")] 221 | void primaryMiss(inout CausticsPackedPayload hitData) 222 | { 223 | #ifdef SMALL_COLOR 224 | hitData.colorAndFlag = colorRayToUint(float3(0, 0, 0), 0); 225 | #else 226 | hitData.color = float3(0, 0, 0); 227 | hitData.isContinue = 0; 228 | #endif 229 | hitData.hitT = 0; 230 | } 231 | 232 | VertexOut getVertexAttributes( 233 | uint triangleIndex, BuiltInTriangleIntersectionAttributes attribs, 234 | out float3 dP1, out float3 dP2, out float3 dN1, out float3 dN2) 235 | { 236 | float3 barycentrics = float3(1.0 - attribs.barycentrics.x - attribs.barycentrics.y, attribs.barycentrics.x, attribs.barycentrics.y); 237 | uint3 indices = getIndices(triangleIndex); 238 | VertexOut v; 239 | v.texC = 0; 240 | v.normalW = 0; 241 | v.bitangentW = 0; 242 | #ifdef USE_INTERPOLATED_POSITION 243 | v.posW = 0; 244 | #else 245 | v.posW = WorldRayOrigin() + WorldRayDirection() * RayTCurrent(); 246 | #endif 247 | v.colorV = 0; 248 | v.prevPosH = 0; 249 | v.lightmapC = 0; 250 | 251 | float3 P[3], N[3]; 252 | [unroll] 253 | for (int i = 0; i < 3; i++) 254 | { 255 | int address = (indices[i] * 3) * 4; 256 | P[i] = asfloat(gPositions.Load3(address)); 257 | N[i] = asfloat(gNormals.Load3(address)); 258 | 259 | v.texC += asfloat(gTexCrds.Load2(address)) * barycentrics[i]; 260 | v.normalW += N[i] * barycentrics[i]; 261 | v.bitangentW += asfloat(gBitangents.Load3(address)) * barycentrics[i]; 262 | v.lightmapC += asfloat(gLightMapUVs.Load2(address)) * barycentrics[i]; 263 | 264 | #ifdef USE_INTERPOLATED_POSITION 265 | v.posW += P[i] * barycentrics[i]; 266 | #endif 267 | } 268 | 269 | #ifdef USE_INTERPOLATED_POSITION 270 | v.posW = mul(float4(v.posW, 1.f), gWorldMat[0]).xyz; 271 | #endif 272 | 273 | #ifndef _MS_DISABLE_INSTANCE_TRANSFORM 274 | // Transform normal/bitangent to world space 275 | v.normalW = mul(v.normalW, (float3x3)gWorldInvTransposeMat[0]).xyz; 276 | v.bitangentW = mul(v.bitangentW, (float3x3)gWorldMat[0]).xyz; 277 | #endif 278 | 279 | dP1 = mul(P[1] - P[0], (float3x3)gWorldMat[0]).xyz; 280 | dP2 = mul(P[2] - P[0], (float3x3)gWorldMat[0]).xyz; 281 | dN1 = mul(N[1] - N[0], (float3x3)gWorldInvTransposeMat[0]).xyz; 282 | dN2 = mul(N[2] - N[0], (float3x3)gWorldInvTransposeMat[0]).xyz; 283 | 284 | // Handle invalid bitangents gracefully (avoid NaN from normalization). 285 | v.bitangentW = dot(v.bitangentW, v.bitangentW) > 0.f ? normalize(v.bitangentW) : float3(0, 0, 0); 286 | return v; 287 | } 288 | 289 | void getVerticesAndNormals( 290 | uint triangleIndex, BuiltInTriangleIntersectionAttributes attribs, 291 | out float3 P0, out float3 P1, out float3 P2, 292 | out float3 N0, out float3 N1, out float3 N2, 293 | out float3 N) 294 | { 295 | uint3 indices = getIndices(triangleIndex); 296 | int address = (indices[0] * 3) * 4; 297 | P0 = asfloat(gPositions.Load3(address)).xyz; 298 | P0 = mul(float4(P0, 1.f), gWorldMat[0]).xyz; 299 | N0 = asfloat(gNormals.Load3(address)).xyz; 300 | N0 = normalize(mul(float4(N0, 0.f), gWorldMat[0]).xyz); 301 | 302 | address = (indices[1] * 3) * 4; 303 | P1 = asfloat(gPositions.Load3(address)).xyz; 304 | P1 = mul(float4(P1, 1.f), gWorldMat[0]).xyz; 305 | N1 = asfloat(gNormals.Load3(address)).xyz; 306 | N1 = normalize(mul(float4(N1, 0.f), gWorldMat[0]).xyz); 307 | 308 | address = (indices[2] * 3) * 4; 309 | P2 = asfloat(gPositions.Load3(address)).xyz; 310 | P2 = mul(float4(P2, 1.f), gWorldMat[0]).xyz; 311 | N2 = asfloat(gNormals.Load3(address)).xyz; 312 | N2 = normalize(mul(float4(N2, 0.f), gWorldMat[0]).xyz); 313 | 314 | float3 barycentrics = float3(1.0 - attribs.barycentrics.x - attribs.barycentrics.y, attribs.barycentrics.x, attribs.barycentrics.y); 315 | N = (N0 * barycentrics.x + N1 * barycentrics.y + N2 * barycentrics.z); 316 | } 317 | 318 | void updateTransferRayDifferential( 319 | float3 N, 320 | inout float3 dPdx, 321 | float3 dDdx) 322 | { 323 | float3 D = WorldRayDirection(); 324 | float t = RayTCurrent(); 325 | float dtdx = -1 * dot(dPdx + t * dDdx, N) / dot(D, N); 326 | dPdx = dPdx + t * dDdx + dtdx * D; 327 | } 328 | 329 | void calculateDNdx( 330 | float3 dP1, float3 dP2, 331 | float3 dN1, float3 dN2, 332 | float3 N, 333 | float3 dPdx, out float3 dNdx) 334 | { 335 | float P11 = dot(dP1, dP1); 336 | float P12 = dot(dP1, dP2); 337 | float P22 = dot(dP2, dP2); 338 | 339 | float Q1 = dot(dP1, dPdx); 340 | float Q2 = dot(dP2, dPdx); 341 | 342 | float delta = P11 * P22 - P12 * P12; 343 | float dudx = (Q1 * P22 - Q2 * P12) / delta; 344 | float dvdx = (Q2 * P11 - Q1 * P12) / delta; 345 | 346 | float n2 = dot(N, N); 347 | float n1 = sqrt(n2); 348 | dNdx = dudx * dN1 + dvdx * dN2; 349 | dNdx = (n2 * dNdx - dot(N, dNdx) * N) / (n2 * n1); 350 | } 351 | 352 | void updateReflectRayDifferential( 353 | float3 N, 354 | float3 dPdx, 355 | float3 dNdx, 356 | inout float3 dDdx) 357 | { 358 | N = normalize(N); 359 | float3 D = WorldRayDirection(); 360 | float dDNdx = dot(dDdx, N) + dot(D, dNdx); 361 | dDdx = dDdx - 2 * (dot(D, N) * dNdx + dDNdx * N); 362 | } 363 | 364 | void getPhotonDifferential(CausticsUnpackedPayload hitData, RayDesc ray, out float3 dPdx, out float3 dPdy) 365 | { 366 | #ifdef RAY_DIFFERENTIAL 367 | dPdx = hitData.dPdx; 368 | dPdy = hitData.dPdy; 369 | #elif defined(RAY_CONE) 370 | float radius = hitData.radius; 371 | float3 normal = hitData.nextDir; 372 | float cosVal = dot(normal, ray.Direction); 373 | dPdx = normalize(ray.Direction - normal * cosVal) * radius; 374 | dPdy = cross(normal, dPdx); 375 | dPdx /= cosVal; 376 | #elif defined(RAY_NONE) 377 | float radius = 0.2; 378 | float3 normal = hitData.nextDir; 379 | float cosVal = dot(normal, ray.Direction); 380 | dPdx = normalize(ray.Direction - normal * cosVal) * radius; 381 | dPdy = cross(normal, dPdx); 382 | dPdx /= cosVal; 383 | #endif 384 | } 385 | 386 | float getPhotonScreenArea(float3 posW, float3 dPdx, float3 dPdy, out float3 screenCoord, out bool inFrustum) 387 | { 388 | dPdx = dPdx * gSplatSize; 389 | dPdy = dPdy * gSplatSize; 390 | float4 s0 = mul(float4(posW, 1), gCamera.viewProjMat); 391 | float4 s00 = mul(float4(posW + dPdx + dPdy, 1), gCamera.viewProjMat); 392 | float4 s01 = mul(float4(posW + dPdx - dPdy, 1), gCamera.viewProjMat); 393 | float4 s10 = mul(float4(posW - dPdx + dPdy, 1), gCamera.viewProjMat); 394 | float4 s11 = mul(float4(posW - dPdx - dPdy, 1), gCamera.viewProjMat); 395 | inFrustum = isInFrustum(s00) || isInFrustum(s01) || isInFrustum(s10) || isInFrustum(s11); 396 | s0 /= s0.w; 397 | s00 /= s00.w; 398 | s01 /= s01.w; 399 | float2 dx = (s00.xy - s0.xy) * viewportDims; 400 | float2 dy = (s01.xy - s0.xy) * viewportDims; 401 | float area = abs(dx.x * dy.y - dy.x * dx.y) / (gSplatSize * gSplatSize); 402 | screenCoord = s0.xyz; 403 | //float zRadius = max(1,length(dPdx) + length(dPdy)) * 0.5 / length(posW - gCamera.posW) * gCamera.nearZ * 0.5 * (viewportDims.x + viewportDims.y); 404 | //float area = zRadius * zRadius; 405 | //float area = 0.5 * (dot(dx, dx) + dot(dy, dy)) / (gSplatSize * gSplatSize); 406 | return area; 407 | } 408 | 409 | 410 | void updateRefractRayDifferential( 411 | float3 D, float3 R, float3 N, float eta, 412 | float3 dPdx, 413 | float3 dNdx, 414 | inout float3 dDdx) 415 | { 416 | N = normalize(N); 417 | float DN = dot(D, N); 418 | float RN = dot(R, N); 419 | float mu = eta * DN - RN; 420 | float dDNdx = dot(dDdx, N) + dot(D, dNdx); 421 | float dmudx = (eta - eta * eta * DN / RN) * dDNdx; 422 | dDdx = eta * dDdx - (mu * dNdx + dmudx * N); 423 | } 424 | 425 | [shader("closesthit")] 426 | void primaryClosestHit(inout CausticsPackedPayload payload, in BuiltInTriangleIntersectionAttributes attribs) 427 | { 428 | CausticsUnpackedPayload hitData; 429 | unpackCausticsPayload(payload, hitData); 430 | // Get the hit-point data 431 | float3 rayOrigW = WorldRayOrigin(); 432 | float3 rayDirW = WorldRayDirection(); 433 | float hitT = RayTCurrent(); 434 | uint triangleIndex = PrimitiveIndex(); 435 | 436 | // prepare the shading data 437 | float3 dP1, dP2, dN1, dN2; 438 | VertexOut v = getVertexAttributes(triangleIndex, attribs, dP1, dP2, dN1, dN2); 439 | float3 N = v.normalW; 440 | v.normalW = normalize(v.normalW); 441 | #ifdef RAY_DIFFERENTIAL 442 | updateTransferRayDifferential(v.normalW, hitData.dPdx, hitData.dDdx); 443 | updateTransferRayDifferential(v.normalW, hitData.dPdy, hitData.dDdy); 444 | #elif defined(RAY_CONE) 445 | hitData.radius = abs(hitData.radius + hitT * hitData.dRadius); 446 | #endif 447 | ShadingData sd = prepareShadingData(v, gMaterial, rayOrigW, 0); 448 | 449 | hitData.hitT = hitT; 450 | bool isSpecular = (sd.linearRoughness > roughThreshold || sd.opacity < 1); 451 | hitData.isContinue = isSpecular; 452 | if (isSpecular) 453 | { 454 | float3 N_ = v.normalW; 455 | bool isReflect = (sd.opacity == 1); 456 | float3 R; 457 | float eta = iorOverride > 0 ? 1.0 / iorOverride : 1.0 / sd.IoR; 458 | if (!isReflect) 459 | { 460 | if (dot(N_, rayDirW) > 0) 461 | { 462 | eta = 1.0 / eta; 463 | N *= -1; 464 | N_ *= -1; 465 | #ifdef RAY_DIFFERENTIAL 466 | dN1 *= -1; 467 | dN2 *= -1; 468 | #endif 469 | } 470 | isReflect = isTotalInternalReflection(rayDirW, N_, eta); 471 | } 472 | 473 | #ifdef RAY_DIFFERENTIAL 474 | float3 dNdx = 0; 475 | float3 dNdy = 0; 476 | calculateDNdx(dP1, dP2, dN1, dN2, N, hitData.dPdx, dNdx); 477 | calculateDNdx(dP1, dP2, dN1, dN2, N, hitData.dPdy, dNdy); 478 | if (isReflect) 479 | { 480 | updateReflectRayDifferential(N_, hitData.dPdx, dNdx, hitData.dDdx); 481 | updateReflectRayDifferential(N_, hitData.dPdy, dNdy, hitData.dDdy); 482 | R = reflect(rayDirW, N_); 483 | } 484 | else 485 | { 486 | getRefractVector(rayDirW, N_, R, eta); 487 | updateRefractRayDifferential(rayDirW, R, N_, eta, hitData.dPdx, dNdx, hitData.dDdx); 488 | updateRefractRayDifferential(rayDirW, R, N_, eta, hitData.dPdy, dNdy, hitData.dDdy); 489 | } 490 | float area = (dot(hitData.dPdx, hitData.dPdx) + dot(hitData.dPdy, hitData.dPdy)) * 0.5; 491 | #elif defined(RAY_CONE) 492 | float cosVal = abs(dot(N_, rayDirW)); 493 | float area = hitData.radius * hitData.radius / cosVal; 494 | float triArea = length(cross(dP1, dP2)) * 0.5; 495 | float triNormalArea = max(dot(dN1, dN1),dot(dN2, dN2)); 496 | float isConcave = (dot(dP1, dN1) + dot(dP2, dN2) >= 0) ? 1.0 : -1.0; 497 | float dH = area / triArea * triNormalArea * isConcave * 2; 498 | float dO; 499 | if (isReflect) 500 | { 501 | R = reflect(rayDirW, N_); 502 | dO = dH * 4 * cosVal; 503 | } 504 | else 505 | { 506 | getRefractVector(rayDirW, N_, R, eta); 507 | float etaI = eta; 508 | float etaO = 1; 509 | float3 ht = -1 * (-etaI * rayDirW + etaO * R); 510 | float dHdO = dot(ht, ht) / (etaO * etaO * abs(dot(ht, R))); 511 | dO = dH * dHdO; 512 | } 513 | hitData.dRadius += sqrt(dO); 514 | #elif defined(RAY_NONE) 515 | if (isReflect) 516 | { 517 | R = reflect(rayDirW, N_); 518 | } 519 | else 520 | { 521 | getRefractVector(rayDirW, N_, R, eta); 522 | } 523 | float area = 0.0001; 524 | #endif 525 | hitData.nextDir = R; 526 | float3 baseColor = lerp(1, sd.diffuse, sd.opacity); 527 | hitData.color = baseColor * hitData.color;// *float4(sd.specular, 1); 528 | } 529 | else 530 | { 531 | hitData.color.rgb = dot(-rayDirW, sd.N)* sd.diffuse* hitData.color.rgb; 532 | hitData.nextDir = sd.N; 533 | } 534 | 535 | packCausticsPayload(hitData, payload); 536 | } 537 | 538 | float getArea(float3 dPdx, float3 dPdy) 539 | { 540 | float area; 541 | if (gAreaType == 0) 542 | { 543 | area = (dot(dPdx, dPdx) + dot(dPdy, dPdy)) * 0.5; 544 | } 545 | else if (gAreaType == 1) 546 | { 547 | area = (length(dPdx) + length(dPdy)); 548 | area *= area; 549 | } 550 | else if (gAreaType == 2) 551 | { 552 | area = max(dot(dPdx, dPdx), dot(dPdy, dPdy)); 553 | } 554 | else 555 | { 556 | float3 areaVector = cross(dPdx, dPdy); 557 | area = length(areaVector); 558 | } 559 | return area; 560 | } 561 | 562 | 563 | void initFromLight(float2 lightUV, float2 pixelSize0, out RayDesc ray, out CausticsUnpackedPayload hitData) 564 | { 565 | lightUV = lightUV * 2 - 1; 566 | float2 pixelSize = pixelSize0 * emitSize / float2(coarseDim.xy); 567 | 568 | float3 lightOrigin = cameraPos + gLights[0].dirW * -100;// gLights[0].posW; 569 | float3 lightDirZ = gLights[0].dirW; 570 | float3 lightDirX = normalize(float3(-lightDirZ.z, 0, lightDirZ.x)); 571 | float3 lightDirY = normalize(cross(lightDirZ, lightDirX)); 572 | 573 | ray.Origin = lightOrigin + (lightDirX * lightUV.x + lightDirY * lightUV.y) * emitSize; 574 | ray.Direction = lightDirZ; 575 | ray.TMin = 0.001; 576 | ray.TMax = 1e10; 577 | 578 | float3 color0 = 1; 579 | if (colorPhotonID) 580 | { 581 | uint3 launchIndex = DispatchRaysIndex(); 582 | color0.xyz = frac(launchIndex.xyz / float(photonIDScale)) * 0.8 + 0.2; 583 | } 584 | hitData.color = color0 * pixelSize.x * pixelSize.y * 512 * 512 * 0.5 * gIntensity;// / (gSplatSize * gSplatSize); 585 | hitData.nextDir = ray.Direction; 586 | hitData.isContinue = 1; 587 | #ifdef RAY_DIFFERENTIAL 588 | hitData.dDdx = 0;// lightDirX* pixelSize.x * 2.0; 589 | hitData.dDdy = 0;// lightDirY* pixelSize.y * 2.0; 590 | hitData.dPdx = lightDirX * pixelSize.x * 2.0; 591 | hitData.dPdy = -lightDirY * pixelSize.y * 2.0; 592 | #elif defined(RAY_CONE) 593 | hitData.radius = 0.5 * (pixelSize.x + pixelSize.y); 594 | hitData.dRadius = 0.0; 595 | #endif 596 | } 597 | 598 | void StorePhoton(RayDesc ray, CausticsUnpackedPayload hitData, uint2 pixelCoord) 599 | { 600 | bool isInFrustum; 601 | float3 dPdx, dPdy; 602 | float3 posW = ray.Origin; 603 | getPhotonDifferential(hitData, ray, dPdx, dPdy); 604 | float area = getArea(dPdx, dPdy); 605 | float3 color = hitData.color.rgb / area; 606 | float3 screenCoord; 607 | float pixelArea = getPhotonScreenArea(posW, dPdx, dPdy, screenCoord, isInFrustum); 608 | if (dot(color, float3(0.299, 0.587, 0.114)) > cullColorThreshold && isInFrustum) 609 | { 610 | uint pixelLoc = pixelCoord.y * coarseDim.x + pixelCoord.x; 611 | 612 | bool storePhoton = (pixelArea < gMaxScreenRadius * gMaxScreenRadius); 613 | uint oldV; 614 | #ifdef FAST_PHOTON_PATH 615 | if (pixelArea < gMinScreenRadius * gMinScreenRadius) 616 | { 617 | float2 uv = (screenCoord.xy + 1) * 0.5; 618 | int2 dstPixel = uv * viewportDims; 619 | float4 lastClr = gPhotonTexture.Load(int3(dstPixel,0)); 620 | if (lastClr.a >= gMinDrawCount) 621 | { 622 | uint clr = compressColor(color, gSmallPhotonColorScale); 623 | InterlockedAdd(gSmallPhotonBuffer[dstPixel], clr, oldV); 624 | storePhoton = false; 625 | } 626 | } 627 | #endif 628 | if (storePhoton) 629 | { 630 | uint instanceIdx = 0; 631 | InterlockedAdd(gDrawArgument[0].instanceCount, 1, instanceIdx); 632 | 633 | Photon photon; 634 | photon.posW = posW; 635 | //photon.normalW = hitData.nextDir; 636 | if (dot(cross(dPdx,dPdy), hitData.nextDir) < 0) 637 | { 638 | dPdy *= -1; 639 | } 640 | photon.color = color; 641 | photon.dPdx = dPdx; 642 | photon.dPdy = dPdy; 643 | gPhotonBuffer[instanceIdx] = photon; 644 | #ifdef TRACE_FIXED 645 | gPixelInfo[pixelLoc].photonIdx = instanceIdx; 646 | #endif 647 | } 648 | 649 | pixelArea = clamp(pixelArea, 1, 100 * 100); 650 | InterlockedAdd(gPixelInfo[pixelLoc].screenArea, uint(pixelArea.x), oldV); 651 | InterlockedAdd(gPixelInfo[pixelLoc].screenAreaSq, uint(pixelArea.x * pixelArea.x), oldV); 652 | InterlockedAdd(gPixelInfo[pixelLoc].count, 1, oldV); 653 | } 654 | } 655 | 656 | #ifdef TRACE_ADAPTIVE_RAY_MIP_MAP 657 | bool getSamplePos(uint threadId, out uint2 pixelPos, out uint sampleIdx) 658 | { 659 | pixelPos = 0; 660 | sampleIdx = threadId; 661 | uint4 value = gRayCountQuadTree[0]; 662 | if (threadId >= value.w) 663 | return false; 664 | for (int mip = 1; mip <= gMipmap; mip++) 665 | { 666 | pixelPos <<= 1; 667 | if(sampleIdx >= value.b) 668 | { 669 | pixelPos += int2(1, 1); 670 | sampleIdx -= value.b; 671 | } 672 | else if (sampleIdx >= value.g) 673 | { 674 | pixelPos += int2(0, 1); 675 | sampleIdx -= value.g; 676 | } 677 | else if (sampleIdx >= value.r) 678 | { 679 | pixelPos += int2(1, 0); 680 | sampleIdx -= value.r; 681 | } 682 | 683 | int nodeOffset = getTextureOffset(pixelPos, mip); 684 | value = gRayCountQuadTree[nodeOffset]; 685 | } 686 | return true; 687 | } 688 | 689 | void getRaySample(uint2 pixel00, uint sampleIdx, inout float2 screenCoord, inout float2 pixelSize) 690 | { 691 | float v00 = gRayDensityTex.Load(int3(pixel00 + int2(0, 0), 0)).r; 692 | float v10 = gRayDensityTex.Load(int3(pixel00 + int2(1, 0), 0)).r; 693 | float v01 = gRayDensityTex.Load(int3(pixel00 + int2(0, 1), 0)).r; 694 | float v11 = gRayDensityTex.Load(int3(pixel00 + int2(1, 1), 0)).r; 695 | float sampleCountF = 0.25 * (v00 + v10 + v01 + v11); 696 | 697 | int sampleDim = (int)ceil(sqrt(sampleCountF)); 698 | int sampleCount = sampleDim * sampleDim; 699 | float sampleWeight = 1.0 / sqrt(float(sampleCount)) * sqrt(sampleCountF / sampleCount); 700 | pixelSize = sqrt(sampleCountF / sampleCount); 701 | if (sampleCount == 1) 702 | { 703 | v00 = v10 = v01 = v11 = 1; 704 | pixelSize = 1; 705 | } 706 | uint yi = sampleIdx / sampleDim; 707 | uint xi = sampleIdx - yi * sampleDim; 708 | float x = (xi + 0.5) / sampleDim; 709 | float y = (yi + 0.5) / sampleDim; 710 | float2 rnd = float2(x, y); 711 | float2 uv = bilinearSample(v00, v10, v01, v11, rnd); 712 | float2 duv = bilinearSample(v00, v10, v01, v11, rnd + 1e-3) - uv; 713 | float aniso = sqrt(duv.y / duv.x); 714 | 715 | screenCoord = pixel00 + uv + 0.5; 716 | pixelSize = pixelSize * sqrt(1 / (bilinearIntepolation(v00, v10, v01, v11, uv)));// *float2(1 / aniso, aniso); 717 | } 718 | 719 | uint part1By1(uint x) 720 | { 721 | x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 722 | x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 723 | x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 724 | x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 725 | x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 726 | return x; 727 | } 728 | 729 | uint encodeMorton2(uint2 idx) 730 | { 731 | return (part1By1(idx.y) << 1) + part1By1(idx.x); 732 | } 733 | 734 | #endif 735 | 736 | bool getTask(out float2 lightUV, out uint2 pixelCoord, out float2 pixelSize) 737 | { 738 | uint3 launchIndex = DispatchRaysIndex(); 739 | uint3 launchDimension = DispatchRaysDimensions(); 740 | uint taskIdx = launchIndex.y * launchDimension.x + launchIndex.x; 741 | #ifdef TRACE_ADAPTIVE 742 | { 743 | if (taskIdx >= gRayArgument[0].rayTaskCount) 744 | { 745 | return false; 746 | } 747 | RayTask task = gRayTask[taskIdx]; 748 | pixelCoord = task.screenCoord; 749 | lightUV = (task.screenCoord + randomOffset * task.pixelSize) / float2(coarseDim); 750 | pixelSize = task.pixelSize; 751 | } 752 | #elif defined(TRACE_FIXED) 753 | { 754 | pixelSize = 1; 755 | pixelCoord = launchIndex.xy; 756 | lightUV = float2(launchIndex.xy) / float2(coarseDim.xy); 757 | lightUV += randomOffset / float2(coarseDim.xy); 758 | if (any(launchIndex.xy >= coarseDim)) 759 | { 760 | return false; 761 | } 762 | } 763 | #elif defined(TRACE_NONE) 764 | { 765 | return false; 766 | } 767 | #elif defined(TRACE_ADAPTIVE_RAY_MIP_MAP) 768 | { 769 | uint2 pixelPosI; 770 | uint sampleIdx; 771 | float2 screenCoord = 0; 772 | pixelSize = 1; 773 | pixelCoord = 0; 774 | //taskIdx = encodeMorton2(launchIndex.xy); 775 | if (!getSamplePos(taskIdx, pixelPosI, sampleIdx)) 776 | return false; 777 | getRaySample(pixelPosI, sampleIdx, screenCoord, pixelSize); 778 | pixelCoord = screenCoord; 779 | lightUV = (screenCoord + randomOffset * pixelSize) / float2(coarseDim); 780 | //lightUV = pixelPosI / float2(coarseDim); // 781 | } 782 | #endif 783 | 784 | if (updatePhoton) 785 | { 786 | gPixelInfo[taskIdx].photonIdx = -1; 787 | } 788 | #ifdef TRACE_FIXED 789 | { 790 | gRayTask[taskIdx].screenCoord = launchIndex.xy; 791 | gRayTask[taskIdx].pixelSize = 1; 792 | } 793 | #endif 794 | return true; 795 | } 796 | 797 | [shader("raygeneration")] 798 | void rayGen() 799 | { 800 | // fetch task 801 | float2 lightUV; 802 | uint2 pixelCoord; 803 | float2 pixelSize; 804 | if (!getTask(lightUV, pixelCoord, pixelSize)) 805 | return; 806 | 807 | // Init ray and hit data 808 | RayDesc ray; 809 | CausticsUnpackedPayload hitData; 810 | initFromLight(lightUV, pixelSize, ray, hitData); 811 | float colorIntensity = max(hitData.color.r, max(hitData.color.g, hitData.color.b)); 812 | hitData.color /= colorIntensity; 813 | 814 | // Photon trace 815 | int depth; 816 | for (depth = 0; depth < maxDepth && hitData.isContinue; depth++) 817 | { 818 | ray.Direction = hitData.nextDir; 819 | 820 | CausticsPackedPayload payload; 821 | packCausticsPayload(hitData, payload); 822 | TraceRay(gRtScene, 0, 0xFF, 0, hitProgramCount, 0, ray, payload); 823 | unpackCausticsPayload(payload, hitData); 824 | 825 | float area = (dot(hitData.dPdx, hitData.dPdx) + dot(hitData.dPdy, hitData.dPdy)) * 0.5; 826 | if (hitData.isContinue && dot(hitData.color, float3(0.299, 0.587, 0.114)) * colorIntensity < traceColorThreshold * area) 827 | { 828 | hitData.isContinue = 0; 829 | hitData.color = 0; 830 | } 831 | 832 | ray.Origin = ray.Origin + ray.Direction * hitData.hitT; 833 | } 834 | 835 | // write result 836 | #ifdef UPDATE_PHOTON 837 | if (any(hitData.color > 0) && depth > 1) 838 | { 839 | hitData.color *= colorIntensity; 840 | StorePhoton(ray, hitData, pixelCoord); 841 | } 842 | #endif 843 | } 844 | -------------------------------------------------------------------------------- /Data/ResetDrawArgument.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "common.hlsl" 29 | struct DrawArguments 30 | { 31 | uint indexCountPerInstance; 32 | uint instanceCount; 33 | uint startIndexLocation; 34 | int baseVertexLocation; 35 | uint startInstanceLocation; 36 | }; 37 | 38 | shared cbuffer PerFrameCB 39 | { 40 | uint2 coarseDim; 41 | uint initRayCount; 42 | uint textureOffset; 43 | uint scatterGeoIdxCount; 44 | }; 45 | 46 | //StructuredBuffer gPhotonBuffer; 47 | RWStructuredBuffer gDrawArgument; 48 | RWStructuredBuffer gRayArgument; 49 | RWStructuredBuffer gPixelInfo; 50 | 51 | RWTexture1D gPhotonCountTexture; 52 | 53 | [numthreads(16, 16, 1)] 54 | void main(uint3 threadIdx : SV_DispatchThreadID) 55 | { 56 | //uint length, stride; 57 | //gPhotonBuffer.GetDimensions(length, stride); 58 | if (all(threadIdx == uint3(0,0,0))) 59 | { 60 | gPhotonCountTexture[textureOffset] = gDrawArgument[0].instanceCount; 61 | 62 | gDrawArgument[0].indexCountPerInstance = scatterGeoIdxCount;// 12;//6 63 | gDrawArgument[0].instanceCount = 0; 64 | gDrawArgument[0].startIndexLocation = 0; 65 | gDrawArgument[0].baseVertexLocation = 0; 66 | gDrawArgument[0].startInstanceLocation = 0; 67 | 68 | //gRayArgument[0].rayTaskCount = initRayCount; 69 | } 70 | 71 | //uint value = gRayDensityTex[threadIdx.xy]; 72 | //float avgArea = float(value >> 16) / float(value & 0xff); 73 | //uint lastCount = 1; 74 | int idx = coarseDim.x * threadIdx.y + threadIdx.x; 75 | gPixelInfo[idx].screenArea = 0;// (uint(avgArea * lastCount) << 16) | lastCount; 76 | gPixelInfo[idx].screenAreaSq = 0; 77 | gPixelInfo[idx].count = 0; 78 | } 79 | -------------------------------------------------------------------------------- /Data/SmoothPhoton.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | float4x4 viewProjMat; 33 | 34 | int2 taskDim; 35 | int2 screenDim; 36 | 37 | float normalThreshold; 38 | float distanceThreshold; 39 | float planarThreshold; 40 | float pixelLuminanceThreshold; 41 | 42 | float minPhotonPixelSize; 43 | float trimDirectionThreshold; 44 | uint enableMedianFilter; 45 | uint removeIsolatedPhoton; 46 | 47 | int minNeighbourCount; 48 | }; 49 | 50 | struct DrawArguments 51 | { 52 | uint indexCountPerInstance; 53 | uint instanceCount; 54 | uint startIndexLocation; 55 | int baseVertexLocation; 56 | uint startInstanceLocation; 57 | }; 58 | 59 | StructuredBuffer gSrcPhotonBuffer; 60 | RWStructuredBuffer gDstPhotonBuffer; 61 | //RWStructuredBuffer gDrawArgument; 62 | RWStructuredBuffer gRayArgument; 63 | StructuredBuffer gRayTask; 64 | Texture2D gDepthTex; 65 | 66 | bool checkPixelNeighbour(uint2 pixelCoord0, Photon photon0, uint2 offset) 67 | { 68 | uint2 pixelCoord1 = min(taskDim - 1, max(uint2(0, 0), pixelCoord0 + offset)); 69 | uint pixelIdx1 = pixelCoord1.y * taskDim.x + pixelCoord1.x; 70 | 71 | PixelInfo task1 = gRayTask[pixelIdx1]; 72 | bool isContinue = task1.photonIdx != -1; 73 | float3 dColor = photon0.color; 74 | Photon photon1; 75 | if (isContinue) 76 | { 77 | photon1 = gSrcPhotonBuffer[task1.photonIdx]; 78 | isContinue &= isPhotonAdjecent(photon0, photon1, normalThreshold, distanceThreshold, planarThreshold); 79 | } 80 | return isContinue; 81 | } 82 | 83 | bool getPhoton(uint2 pixelCoord, inout Photon photon) 84 | { 85 | uint2 pixelCoord1 = min(taskDim - 1, max(uint2(0, 0), pixelCoord)); 86 | uint pixelIdx1 = pixelCoord1.y * taskDim.x + pixelCoord1.x; 87 | PixelInfo task1 = gRayTask[pixelIdx1]; 88 | if (task1.photonIdx == -1) 89 | { 90 | return false; 91 | } 92 | photon = gSrcPhotonBuffer[task1.photonIdx]; 93 | return true; 94 | } 95 | 96 | void getTrimLength(float3 P1, float3 D1, float3 P2, float3 D2, inout float l) 97 | { 98 | D1 = normalize(D1); 99 | D2 = normalize(D2); 100 | float D1D2 = dot(D1, D2); 101 | if (abs(D1D2) > trimDirectionThreshold) 102 | { 103 | return; 104 | } 105 | //float3 P12 = P1 - P2; 106 | //float P12D1 = dot(P12, D1); 107 | //float P12D2 = dot(P12, D2); 108 | //float det = -1 + D1D2 * D1D2; 109 | //float t1 = P12D1 - P12D2 * D1D2; 110 | //l = min(l, abs(t1 / det)); 111 | 112 | float3 P21 = P2 - P1; 113 | float proj = length(P21);// dot(P21, D1); 114 | l = min(l, abs(proj)); 115 | } 116 | 117 | PixelInfo getRayTask(uint2 pixelCoord) 118 | { 119 | uint2 pixelCoord1 = min(taskDim - 1, max(uint2(0, 0), pixelCoord)); 120 | uint pixelIdx1 = pixelCoord1.y * taskDim.x + pixelCoord1.x; 121 | return gRayTask[pixelIdx1]; 122 | } 123 | 124 | float3 medianFilter(uint2 pixelCoord0) 125 | { 126 | uint2 dir[9] = { 127 | uint2(-1,-1), 128 | uint2(-1,0), 129 | uint2(-1,1), 130 | uint2(0,-1), 131 | uint2(0,0), 132 | uint2(0,1), 133 | uint2(1,-1), 134 | uint2(1,0), 135 | uint2(1,1), 136 | }; 137 | 138 | half2 luminance[9]; 139 | for (int i = 0; i < 8; i++) 140 | { 141 | //bool isContinue = checkPixelNeighbour(threadIdx.xy, photon0, dir[i]); 142 | //uint2 pixelCoord1 = min(taskDim - 1, max(uint2(0, 0), pixelCoord0 + dir[i])); 143 | //uint pixelIdx1 = pixelCoord1.y * taskDim.x + pixelCoord1.x; 144 | 145 | PixelInfo task1 = getRayTask(pixelCoord0 + dir[i]); 146 | if (task1.photonIdx != -1) 147 | { 148 | Photon photon = gSrcPhotonBuffer[task1.photonIdx]; 149 | luminance[i].x = dot(photon.color, float3(0.299, 0.587, 0.114)); 150 | } 151 | else 152 | { 153 | luminance[i].x = 0; 154 | } 155 | luminance[i].y = i; 156 | } 157 | 158 | for (int i = 0; i < 9; i++) 159 | { 160 | for (int j = 0; j < i; j++) 161 | { 162 | if (luminance[j].x > luminance[j+1].x) 163 | { 164 | half2 a = luminance[j + 1]; 165 | luminance[j + 1] = luminance[j]; 166 | luminance[j] = a; 167 | } 168 | } 169 | } 170 | 171 | int idx = luminance[4].y; 172 | PixelInfo task1 = getRayTask(pixelCoord0 + dir[idx]); 173 | if (task1.photonIdx != -1) 174 | { 175 | Photon photon = gSrcPhotonBuffer[task1.photonIdx]; 176 | return photon.color; 177 | } 178 | return 0; 179 | } 180 | 181 | bool isPhotonContinue(Photon photon0, Photon photon1) 182 | { 183 | bool isContinue = true; 184 | float3 normal0 = normalize(cross(photon0.dPdx, photon0.dPdy)); 185 | float3 normal1 = normalize(cross(photon1.dPdx, photon1.dPdy)); 186 | isContinue &= dot(normal0, normal1) > normalThreshold; 187 | 188 | float distanceFactor = 0.5 * (length(photon0.dPdx) + length(photon0.dPdx)); 189 | isContinue &= length(photon0.posW - photon1.posW) / distanceFactor < distanceThreshold; 190 | 191 | isContinue &= dot(normal0, photon0.posW - photon1.posW) < planarThreshold; 192 | return isContinue; 193 | } 194 | 195 | [numthreads(16, 16, 1)] 196 | void main(uint3 groupID : SV_GroupID, uint groupIndex : SV_GroupIndex, uint3 threadIdx : SV_DispatchThreadID) 197 | { 198 | 199 | //uint length, stride; 200 | //gSrcPhotonBuffer.GetDimensions(length, stride); 201 | uint2 pixelCoord0 = threadIdx.xy; 202 | uint rayIdx = threadIdx.y * taskDim.x + threadIdx.x; 203 | PixelInfo task0 = gRayTask[rayIdx]; 204 | int idx0 = task0.photonIdx; 205 | if (idx0 == -1) 206 | { 207 | return; 208 | } 209 | 210 | Photon photon0 = gSrcPhotonBuffer[idx0]; 211 | 212 | uint2 dir[8] = { 213 | uint2(-1,-1), 214 | uint2(-1,0), 215 | uint2(-1,1), 216 | uint2(0,-1), 217 | //uint2(0,0), 218 | uint2(0,1), 219 | uint2(1,-1), 220 | uint2(1,0), 221 | uint2(1,1), 222 | }; 223 | uint continueFlag = 0; 224 | float3 color = photon0.color;// / 9; 225 | int continueCount = 0; 226 | for (int i = 0; i < 8; i++) 227 | { 228 | //bool isContinue = checkPixelNeighbour(threadIdx.xy, photon0, dir[i]); 229 | uint2 pixelCoord1 = min(taskDim - 1, max(uint2(0, 0), pixelCoord0 + dir[i])); 230 | uint pixelIdx1 = pixelCoord1.y * taskDim.x + pixelCoord1.x; 231 | 232 | PixelInfo task1 = gRayTask[pixelIdx1]; 233 | bool isContinue = task1.photonIdx != -1; 234 | Photon photon1; 235 | if (isContinue) 236 | { 237 | photon1 = gSrcPhotonBuffer[task1.photonIdx]; 238 | isContinue &= isPhotonContinue(photon0, photon1); 239 | } 240 | if (isContinue) 241 | { 242 | //color += photon1.color / 9; 243 | continueCount++; 244 | continueFlag |= (1 << i); 245 | } 246 | } 247 | if (removeIsolatedPhoton && continueCount < minNeighbourCount) 248 | { 249 | //float w = saturate((continueCount - 0.0) / (8.0 - 0.0)); 250 | //color *= lerp(0.0,1,w); 251 | photon0.color = 0; 252 | } 253 | //gSrcPhotonBuffer[idx0].color = color; 254 | 255 | //Photon photon1; 256 | //float trimmedLength = length(photon0.dPdx); 257 | //if (getPhoton(pixelCoord0 + uint2(1, 0), photon1) && (continueFlag & (1 << 6))) 258 | //{ 259 | // getTrimLength(photon0.posW, photon0.dPdx, photon1.posW, photon1.dPdx, trimmedLength); 260 | //} 261 | //if (getPhoton(pixelCoord0 + uint2(-1, 0), photon1) && (continueFlag & (1 << 1))) 262 | //{ 263 | // getTrimLength(photon0.posW, photon0.dPdx, photon1.posW, photon1.dPdx, trimmedLength); 264 | //} 265 | //photon0.dPdx = photon0.dPdx * trimmedLength / length(photon0.dPdx); 266 | 267 | //trimmedLength = length(photon0.dPdy); 268 | //if (getPhoton(pixelCoord0 + uint2(0, 1), photon1) && (continueFlag & (1 << 4))) 269 | //{ 270 | // getTrimLength(photon0.posW, photon0.dPdy, photon1.posW, photon1.dPdy, trimmedLength); 271 | //} 272 | //if (getPhoton(pixelCoord0 + uint2(0, -1), photon1) && (continueFlag & (1 << 3))) 273 | //{ 274 | // getTrimLength(photon0.posW, photon0.dPdy, photon1.posW, photon1.dPdy, trimmedLength); 275 | //} 276 | //photon0.dPdy = photon0.dPdy * trimmedLength / length(photon0.dPdy); 277 | 278 | //uint fourNeighbourFlag = (1 << 1) | (1 << 3) | (1 << 4) | (1 << 6); 279 | //if ((continueFlag & fourNeighbourFlag) == 0) 280 | //{ 281 | // photon0.color = 0; 282 | //} 283 | 284 | //float width = length(photon0.dPdx); 285 | //float height = length(photon0.dPdy); 286 | //float area0 = width * height; 287 | //float area = length(cross(photon0.dPdx, photon0.dPdy)); 288 | //float ratio = area / area0; 289 | //if (ratio < trimDirectionThreshold) 290 | //{ 291 | // photon0.color = 0; 292 | //} 293 | 294 | if (enableMedianFilter) 295 | { 296 | photon0.color = medianFilter(pixelCoord0); 297 | } 298 | gDstPhotonBuffer[idx0] = photon0; 299 | } 300 | -------------------------------------------------------------------------------- /Data/SpacialFilter.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | int2 causticsDim; 33 | int2 gBufferDim; 34 | float normalKernel; 35 | float depthKernel; 36 | float colorKernel; 37 | float screenKernel; 38 | int passID; 39 | float gSmallPhotonColorScale; 40 | }; 41 | 42 | Texture2D depthTexThis; 43 | Texture2D normalTexThis; 44 | 45 | Texture2D smallPhotonTex; 46 | 47 | //Texture2D causticsTexLast; 48 | RWTexture2D causticsTexThis; 49 | 50 | SamplerState gSampler; 51 | 52 | [numthreads(16, 16, 1)] 53 | void main(uint3 threadIdx : SV_DispatchThreadID) 54 | { 55 | uint2 causticsPixelPos = threadIdx.xy; 56 | if (any(causticsPixelPos.xy >= causticsDim)) 57 | { 58 | return; 59 | } 60 | float2 uv = float2(causticsPixelPos.xy + 0.5) / causticsDim; 61 | uint2 gBufferPixelPos = uv * gBufferDim; 62 | 63 | float depth0 = depthTexThis[gBufferPixelPos].r; 64 | float2 depthGrad; 65 | depthGrad.x = depthTexThis[gBufferPixelPos + uint2(1, 0)].r; 66 | depthGrad.y = depthTexThis[gBufferPixelPos + uint2(0, 1)].r; 67 | float4 color0 = causticsTexThis[causticsPixelPos].rgba; 68 | float luminance0 = getLuminance(color0.rgb); 69 | 70 | float3 normal0 = normalTexThis[gBufferPixelPos].rgb; 71 | float totalWeight = 0; 72 | float4 totalColor = 0; 73 | int step = (1 << passID); 74 | float hArray[5] = { 1.0/16, 1.0/4, 3.0/8, 1.0/4, 1.0/16 }; 75 | [unroll] 76 | for (int i = 0; i < 5; i++) 77 | { 78 | float hi = hArray[i]; 79 | for (int j = 0; j < 5; j++) 80 | { 81 | float hj = hArray[j]; 82 | float h = pow(hi * hj, screenKernel); 83 | 84 | uint2 offset = uint2(i - 2, j - 2); 85 | uint2 samplePos = gBufferPixelPos + offset * step; 86 | float depth = depthTexThis[samplePos].r; 87 | float3 normal = normalTexThis[samplePos].rgb; 88 | float4 color = causticsTexThis[causticsPixelPos + offset]; 89 | uint smallPhotonData = smallPhotonTex[causticsPixelPos + offset]; 90 | float4 smallPhotonClr = decompressColor(smallPhotonData, gSmallPhotonColorScale); 91 | color += smallPhotonClr; 92 | float luminance = getLuminance(color.rgb); 93 | if (depth == 1) 94 | { 95 | continue; 96 | } 97 | 98 | float depthWeight = exp(-abs((depth - depth0) / (depthKernel * dot(depthGrad, offset) + 0.00001))); 99 | float normalWeight = pow(saturate(dot(normal, normal0)), normalKernel); 100 | float colorWeight = exp(-abs(luminance - luminance0) / colorKernel); 101 | 102 | float weight = h * depthWeight * normalWeight * colorWeight; 103 | totalWeight += weight; 104 | totalColor += weight * color; 105 | } 106 | } 107 | if (totalWeight == 0) 108 | { 109 | totalColor = color0; 110 | } 111 | else 112 | { 113 | totalColor /= totalWeight; 114 | } 115 | causticsTexThis[causticsPixelPos] = totalColor;// float4(totalColor.rgb, 1); 116 | } 117 | -------------------------------------------------------------------------------- /Data/TemporalFilter.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | float4x4 reprojMatrix; 33 | float4x4 invProjMatThis; 34 | float4x4 invProjMatLast; 35 | 36 | int2 causticsDim; 37 | int2 gBufferDim; 38 | 39 | float blendWeight; 40 | float normalKernel; 41 | float depthKernel; 42 | float colorKernel; 43 | }; 44 | 45 | Texture2D depthTexThis; 46 | Texture2D depthTexLast; 47 | 48 | Texture2D normalTexThis; 49 | Texture2D normalTexLast; 50 | 51 | Texture2D causticsTexLast; 52 | RWTexture2D causticsTexThis; 53 | 54 | SamplerState gSampler; 55 | 56 | [numthreads(16, 16, 1)] 57 | void main(uint3 threadIdx : SV_DispatchThreadID) 58 | { 59 | uint2 causticsPixelPos = threadIdx.xy; 60 | if (any(causticsPixelPos.xy >= causticsDim)) 61 | { 62 | return; 63 | } 64 | float2 uv = float2(causticsPixelPos.xy + 0.5) / causticsDim; 65 | uint2 gBufferPixelPos = uv * gBufferDim; 66 | 67 | float depth = depthTexThis[gBufferPixelPos].r; 68 | float3 normal = normalTexThis[gBufferPixelPos].rgb; 69 | float4 color = causticsTexThis[causticsPixelPos]; 70 | 71 | float4 ndc = float4(uv * float2(2, -2) + float2(-1, 1), depth, 1); 72 | float4 ndcLast = mul(ndc, reprojMatrix); 73 | ndcLast.xyz /= ndcLast.w; 74 | float2 uvLast = (ndcLast.xy * float2(1, -1) + 1) * 0.5; 75 | uint2 pixelPosLast = uvLast * causticsDim; 76 | uint2 gBufferPixelPosLast = uvLast * gBufferDim; 77 | 78 | float depthLast = depthTexLast[gBufferPixelPosLast].r; 79 | float3 normalLast = normalTexLast[gBufferPixelPosLast].rgb; 80 | float4 colorLast = causticsTexLast.SampleLevel(gSampler, uvLast, 0); 81 | 82 | float viewDepthThis = toViewSpace(invProjMatThis, depth); 83 | float viewDepthLast = toViewSpace(invProjMatLast, depthLast); 84 | 85 | float weight = 0; 86 | if (depthLast < 1) 87 | { 88 | float normalDiff = (1 - saturate(dot(normal, normalLast))) / normalKernel * 100; 89 | float depthDiff = abs(viewDepthThis - viewDepthLast) / depthKernel; 90 | float colorDiff = length(colorLast - color) / colorKernel; 91 | weight = blendWeight * exp(-1 * (normalDiff * normalDiff + depthDiff * depthDiff + colorDiff * colorDiff)); 92 | } 93 | 94 | //causticsTexThis[causticsPixelPos] = float4(normalLast, 1); 95 | causticsTexThis[causticsPixelPos] = color * (1 - weight) + 96 | //causticsTexLast[pixelPosLast] * weight; 97 | colorLast * weight; 98 | } 99 | -------------------------------------------------------------------------------- /Data/UpdateRayDensity.cs.hlsl: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # * Redistributions in binary form must reproduce the above copyright 10 | # notice, this list of conditions and the following disclaimer in the 11 | # documentation and/or other materials provided with the distribution. 12 | # * Neither the name of NVIDIA CORPORATION nor the names of its 13 | # contributors may be used to endorse or promote products derived 14 | # from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 17 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | ***************************************************************************/ 28 | #include "Common.hlsl" 29 | 30 | shared cbuffer PerFrameCB 31 | { 32 | int2 coarseDim; 33 | float minPhotonPixelSize; 34 | float smoothWeight; 35 | int maxTaskPerPixel; 36 | float updateSpeed; 37 | float varianceGain; 38 | float derivativeGain; 39 | }; 40 | 41 | StructuredBuffer gPixelInfo; 42 | RWStructuredBuffer gRayArgument; 43 | RWTexture2D gRayDensityTex; 44 | 45 | void getAreaValue(uint2 pos, out float avgArea, out float avgArea2) 46 | { 47 | int idx = coarseDim.x * pos.y + pos.x; 48 | avgArea = (gPixelInfo[idx].screenArea / float(gPixelInfo[idx].count + 0.01)); 49 | avgArea2 = (gPixelInfo[idx].screenAreaSq / float(gPixelInfo[idx].count + 0.01)); 50 | } 51 | 52 | [numthreads(16, 16, 1)] 53 | void updateRayDensityTex(uint3 threadIdx : SV_DispatchThreadID) 54 | { 55 | if (all(threadIdx == uint3(0, 0, 0))) 56 | { 57 | gRayArgument[0].rayTaskCount = 0; 58 | } 59 | 60 | int idx = coarseDim.x * threadIdx.y + threadIdx.x; 61 | 62 | float area, areaSq; 63 | getAreaValue(threadIdx.xy, area, areaSq); 64 | float stdVariance = (abs(areaSq - area * area)); 65 | 66 | float targetArea = minPhotonPixelSize * minPhotonPixelSize; 67 | 68 | float4 value = gRayDensityTex[threadIdx.xy]; 69 | float oldDensity = value.r; 70 | float weight = smoothWeight * updateSpeed; 71 | oldDensity += gRayDensityTex[threadIdx.xy + uint2(1, 0)].r * weight; 72 | oldDensity += gRayDensityTex[threadIdx.xy + uint2(0, 1)].r * weight; 73 | oldDensity += gRayDensityTex[threadIdx.xy + uint2(-1, 0)].r * weight; 74 | oldDensity += gRayDensityTex[threadIdx.xy + uint2(0, -1)].r * weight; 75 | oldDensity /= (1 + weight * 4); 76 | 77 | //float density = 1 / (area + 0.001); 78 | //float targetDensity = 1 / (targetArea * 0.01 + 0.001); 79 | //float newDensity = oldDensity + updateSpeed * 100 * (targetDensity - density) + stdVariance * varianceGain * 0.01 - value.g * derivativeGain; 80 | 81 | float newDensity = oldDensity * area / targetArea + stdVariance * varianceGain * 0.01 - value.g * derivativeGain; 82 | newDensity = newDensity * updateSpeed + oldDensity * (1- updateSpeed); 83 | newDensity = clamp(newDensity, 0.1, maxTaskPerPixel); 84 | gRayDensityTex[threadIdx.xy] = float4(newDensity, newDensity - value.r, 0, 0); 85 | 86 | //gPixelInfo[idx].screenArea = 0; 87 | //gPixelInfo[idx].screenAreaSq = 0; 88 | //gPixelInfo[idx].count = 0; 89 | } 90 | -------------------------------------------------------------------------------- /Data/compile_all.bat: -------------------------------------------------------------------------------- 1 | 2 | del "PhotonTracing.rt.hlsl.h" 3 | fxc /O3 /T cs_5_1 "PhotonTracing.rt.hlsl" /E TexturedSceneGeom_VS /Fh "PhotonTracing.rt.hlsl.h" 4 | 5 | rem del "bin\PhotonScatter_VS.h" 6 | rem fxc /O3 /T vs_5_1 "src/ForwardRendering.hlsl" /E PhotonScatter_VS /Fh "bin/PhotonScatter_VS.h" /Fe "err/PhotonScatter_VS.txt" 7 | 8 | rem del "bin\CausticsMapVS.h" 9 | rem fxc /O3 /T vs_5_1 "src/ForwardRendering.hlsl" /E CausticsMapVS /Fh "bin/CausticsMapVS.h" /Fe "err/CausticsMapVS.txt" 10 | 11 | rem del "bin\SimpleSceneGeom_VS.h" 12 | rem fxc /O3 /T vs_5_1 "src/ForwardRendering.hlsl" /E SimpleSceneGeom_VS /Fh "bin/SimpleSceneGeom_VS.h" /Fe "err/SimpleSceneGeom_VS.txt" 13 | 14 | rem del "bin\CausticsSceneGeom_VS.h" 15 | rem fxc /O3 /T vs_5_1 "src/ForwardRendering.hlsl" /E CausticsSceneGeom_VS /Fh "bin/CausticsSceneGeom_VS.h" /Fe "err/CausticsSceneGeom_VS.txt" 16 | 17 | rem del "bin\CausticsMapPS.h" 18 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E CausticsMapPS /Fh "bin/CausticsMapPS.h" /Fe "err/CausticsMapPS.txt" 19 | 20 | rem del "bin\CausticsScene_PS.h" 21 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E CausticsScene_PS /Fh "bin/CausticsScene_PS.h" /Fe "err/CausticsScene_PS.txt" 22 | 23 | rem del "bin\SimpleCausticsScene_PS.h" 24 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E SimpleCausticsScene_PS /Fh "bin/SimpleCausticsScene_PS.h" /Fe "err/SimpleCausticsScene_PS.txt" 25 | 26 | rem del "bin\SimpleScene_PS.h" 27 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E SimpleScene_PS /Fh "bin/SimpleScene_PS.h" /Fe "err/SimpleScene_PS.txt" 28 | 29 | rem del "bin\Combine_PS_PS.h" 30 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E Combine_PS /Fh "bin/Combine_PS.h" /Fe "err/Combine_PS.txt" 31 | 32 | rem del "bin\BilateralBlur2_PS.h" 33 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E BilateralBlur2_PS /Fh "bin/BilateralBlur2_PS.h" /Fe "err/BilateralBlur2_PS.txt" 34 | 35 | rem del "bin\BilateralBlur1_PS.h" 36 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E BilateralBlur1_PS /Fh "bin/BilateralBlur1_PS.h" /Fe "err/BilateralBlur1_PS.txt" 37 | 38 | rem del "bin\ScatteredHoleFill1_PS.h" 39 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E ScatteredHoleFill1_PS /Fh "bin/ScatteredHoleFill1_PS.h" /Fe "err/ScatteredHoleFill1_PS.txt" 40 | 41 | rem del "bin\ScatteredHoleFill2_PS.h" 42 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E ScatteredHoleFill2_PS /Fh "bin/ScatteredHoleFill2_PS.h" /Fe "err/ScatteredHoleFill2_PS.txt" 43 | 44 | rem del "bin\PhotonScatter_PS.h" 45 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E PhotonScatter_PS /Fh "bin/PhotonScatter_PS.h" /Fe "err/PhotonScatter_PS.txt" 46 | 47 | rem del "bin\TexturedScene_PS.h" 48 | rem fxc /enable_unbounded_descriptor_tables /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E TexturedScene_PS /Fh "bin/TexturedScene_PS.h" /Fe "err/TexturedScene_PS.txt" 49 | 50 | rem del "bin\Screen_Quad_VS.h" 51 | rem fxc /O3 /T vs_5_1 "src/MSAA_Detect.hlsl" /E Screen_Quad_VS /Fh "bin/Screen_Quad_VS.h" /Fe "err/Screen_Quad_VS.txt" 52 | 53 | rem del "bin\FXAA_PS.h" 54 | rem fxc /O3 /T ps_5_1 "src/FXAA.hlsl" /E FXAA_PS /Fh "bin/FXAA_PS.h" /Fe "err/FXAA_PS.txt" 55 | 56 | rem del "bin\Debug1PS.h" 57 | rem fxc /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E Debug1PS /Fh "bin/Debug1PS.h" /Fe "err/Debug1PS.txt" 58 | 59 | rem del "bin\Debug2PS.h" 60 | rem fxc /O3 /T ps_5_1 "src/ForwardRendering.hlsl" /E Debug2PS /Fh "bin/Debug2PS.h" /Fe "err/Debug2PS.txt" 61 | 62 | rem del "bin\CountRays_PS.h" 63 | rem fxc /O3 /T ps_5_1 "src/CountRays.hlsl" /E CountRays_PS /Fh "bin/CountRays_PS.h" /Fe "err/CountRays_PS.txt" 64 | 65 | rem del "bin\ClearRays_PS.h" 66 | rem fxc /O3 /T ps_5_1 "src/CountRays.hlsl" /E ClearRays_PS /Fh "bin/ClearRays_PS.h" /Fe "err/ClearRays_PS.txt" 67 | 68 | rem del "bin\OutputListLength_PS.h" 69 | rem fxc /O3 /T ps_5_1 "src/CountRays.hlsl" /E OutputListLength_PS /Fh "bin/OutputListLength_PS.h" /Fe "err/OutputListLength_PS.txt" 70 | 71 | rem del "bin\StencilRed_PS.h" 72 | rem fxc /O3 /T ps_5_1 "src/CountRays.hlsl" /E StencilRed_PS /Fh "bin/StencilRed_PS.h" /Fe "err/StencilRed_PS_PS.txt" 73 | 74 | rem del "bin\Screen_Quad_VS.h" 75 | rem fxc /O3 /T vs_5_1 "src/MSAA_Detect.hlsl" /E Screen_Quad_VS /Fh "bin/Screen_Quad_VS.h" /Fe "err/Screen_Quad_VS.txt" 76 | 77 | rem del "bin\UntexturedSceneGeom_VS.h" 78 | rem fxc /O3 /T vs_5_1 "src/ForwardRendering.hlsl" /E UntexturedSceneGeom_VS /Fh "bin/UntexturedSceneGeom_VS.h" /Fe "err/UntexturedSceneGeom_VS.txt" 79 | 80 | pause 81 | 82 | exit 83 | 84 | -------------------------------------------------------------------------------- /Data/dragonDetail.ini: -------------------------------------------------------------------------------- 1 | 3.01 2 2 | 17.2175 12.5392 -7.7491 3 | 17.4631 11.6594 -8.15611 4 | -------------------------------------------------------------------------------- /Data/far.ini: -------------------------------------------------------------------------------- 1 | 0.4 2 2 | 7 80 40 3 | 0 0 0 4 | -------------------------------------------------------------------------------- /Data/far2.ini: -------------------------------------------------------------------------------- 1 | 3.01 2 2 | -7.73637 56.1664 39.4309 3 | -7.66551 55.3862 38.8093 4 | -------------------------------------------------------------------------------- /Data/fxc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Data/fxc.exe -------------------------------------------------------------------------------- /Data/gaussian.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Data/gaussian.xcf -------------------------------------------------------------------------------- /Data/glass.ini: -------------------------------------------------------------------------------- 1 | 6.67 2.28 2 | 25.4573 30.7123 70.6907 3 | 25.4311 30.1912 69.8375 4 | -------------------------------------------------------------------------------- /Data/init.ini: -------------------------------------------------------------------------------- 1 | 3.01 2 2 | 17.2175 12.5392 -7.7491 3 | 17.4631 11.6594 -8.15611 4 | -------------------------------------------------------------------------------- /Data/len.ini: -------------------------------------------------------------------------------- 1 | 0.49 2 2 | -7.85069 13.0574 27.2206 3 | -7.82691 12.1032 26.9223 4 | -------------------------------------------------------------------------------- /Data/uniform.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Data/uniform.xcf -------------------------------------------------------------------------------- /Media/Caustics/copo.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'copo.blend' 2 | # Material Count: 3 3 | 4 | newmtl Material 5 | Ns 225.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.0 0.0 0.0 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl Material.001 15 | Ns 225.000000 16 | Ka 1.000000 1.000000 1.000000 17 | Kd 0.800000 0.800000 0.800000 18 | Ks 0.500000 0.500000 0.500000 19 | Ke 0.0 0.0 0.0 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl Material.002 25 | Ns 225.000000 26 | Ka 1.000000 1.000000 1.000000 27 | Kd 0.800000 0.800000 0.800000 28 | Ks 0.500000 0.500000 0.500000 29 | Ke 0.0 0.0 0.0 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | -------------------------------------------------------------------------------- /Media/Caustics/dragon.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/dragon.fbx -------------------------------------------------------------------------------- /Media/Caustics/gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/gaussian.png -------------------------------------------------------------------------------- /Media/Caustics/glass3.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/glass3.fbx -------------------------------------------------------------------------------- /Media/Caustics/glassCup.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/glassCup.fbx -------------------------------------------------------------------------------- /Media/Caustics/monkey.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/monkey.fbx -------------------------------------------------------------------------------- /Media/Caustics/prism.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/prism.blend1 -------------------------------------------------------------------------------- /Media/Caustics/prism.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/prism.fbx -------------------------------------------------------------------------------- /Media/Caustics/quad.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/quad.blend1 -------------------------------------------------------------------------------- /Media/Caustics/quad.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'quad.blend' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | -------------------------------------------------------------------------------- /Media/Caustics/quad.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.80 (sub 75) OBJ File: 'quad.blend' 2 | # www.blender.org 3 | mtllib quad.mtl 4 | o Plane.001 5 | v -1.000000 0.000000 1.000000 6 | v 1.000000 0.000000 1.000000 7 | v -1.000000 0.000000 -1.000000 8 | v 1.000000 0.000000 -1.000000 9 | vt 1.000000 0.000000 10 | vt 0.000000 1.000000 11 | vt 0.000000 0.000000 12 | vt 1.000000 1.000000 13 | vn 0.0000 1.0000 0.0000 14 | usemtl None 15 | s off 16 | f 2/1/1 3/2/1 1/3/1 17 | f 2/1/1 4/4/1 3/2/1 18 | -------------------------------------------------------------------------------- /Media/Caustics/ring.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/ring.fbx -------------------------------------------------------------------------------- /Media/Caustics/ring.fscene: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "camera_speed": 1.0, 4 | "lighting_scale": 1.0, 5 | "active_camera": "Camera0", 6 | "models": [ 7 | { 8 | "file": "ring.fbx", 9 | "name": "ring", 10 | "instances": [ 11 | { 12 | "name": "Falcor-Sample0", 13 | "translation": [ 14 | 0.0, 15 | 0.0, 16 | 0.0 17 | ], 18 | "scaling": [ 19 | 1.0, 20 | 1.0, 21 | 1.0 22 | ], 23 | "rotation": [ 24 | 0.0, 25 | 0.0, 26 | 0.0 27 | ] 28 | } 29 | ] 30 | } 31 | ], 32 | "lights": [ 33 | { 34 | "name": "DirLight0", 35 | "type": "dir_light", 36 | "intensity": [5,5,5], 37 | "direction": [-0.2,-0.9,0] 38 | } 39 | ], 40 | "cameras": [ 41 | { 42 | "name": "Camera0", 43 | "pos": [ 44 | 7, 45 | 80, 46 | 40 47 | ], 48 | "target": [0,0,0 49 | ], 50 | "up": [ 51 | 0, 52 | 1, 53 | 0 54 | ], 55 | "focal_length": 21.0, 56 | "depth_range": [ 57 | 0.10000000149011612, 58 | 10000.0 59 | ], 60 | "aspect_ratio": 1.7769999504089356 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /Media/Caustics/sphere.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'quad.blend' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 500 6 | Ka 0.8 0.8 0.8 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | -------------------------------------------------------------------------------- /Media/Caustics/sphere.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.80 (sub 75) OBJ File: 'quad.blend' 2 | # www.blender.org 3 | mtllib sphere.mtl 4 | o Plane.002_Plane.003 5 | v -1.000000 0.000000 1.000000 6 | v 1.000000 0.000000 1.000000 7 | v -1.000000 0.000000 -1.000000 8 | v 1.000000 0.000000 -1.000000 9 | v 0.000000 0.348042 0.000000 10 | vt 0.000000 0.000000 11 | vt 1.000000 0.000000 12 | vt 0.500000 0.500000 13 | vt 1.000000 1.000000 14 | vt 0.000000 1.000000 15 | vn 0.0000 0.9444 0.3287 16 | vn 0.3287 0.9444 0.0000 17 | vn 0.0000 0.9444 -0.3287 18 | vn -0.3287 0.9444 0.0000 19 | usemtl None 20 | s off 21 | f 1/1/1 2/2/1 5/3/1 22 | f 2/2/2 4/4/2 5/3/2 23 | f 4/4/3 3/5/3 5/3/3 24 | f 3/5/4 1/1/4 5/3/4 25 | -------------------------------------------------------------------------------- /Media/Caustics/uniform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/Media/Caustics/uniform.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mesh Caustics Demo 2 | ================== 3 | 4 | This demo demonstrates an real-time adaptive caustics algorithm. 5 | 6 | ![introduction01](ReadmeImage/intro01.gif) 7 | ![introduction02](ReadmeImage/intro02.png) 8 | ![introduction03](ReadmeImage/intro03.png) 9 | 10 | ## Getting Started 11 | 12 | To build the demo, one should take the following steps: 13 | 1. Download NVIDIA falcor 3.1 14 | 2. Make a folder called "Caustics" under \Source\Samples\Raytracing 15 | 3. Checkout the repo under the "Caustics" folder 16 | 4. Copy content under "Source\Samples\Raytracing\Caustics\Media" folder to "Media" folder under falcor root directory. 17 | 5. Add "Caustics.vcxproj" to falcor solution 18 | 6. Build falcor with caustics project -------------------------------------------------------------------------------- /ReadmeImage/algorithm01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/algorithm01.png -------------------------------------------------------------------------------- /ReadmeImage/algorithm02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/algorithm02.png -------------------------------------------------------------------------------- /ReadmeImage/algorithm03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/algorithm03.png -------------------------------------------------------------------------------- /ReadmeImage/algorithm04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/algorithm04.png -------------------------------------------------------------------------------- /ReadmeImage/intro01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/intro01.gif -------------------------------------------------------------------------------- /ReadmeImage/intro02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/intro02.png -------------------------------------------------------------------------------- /ReadmeImage/intro03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/league1991/RTCaustics/dd958a0788a5c002ca8144a66d554d5d7a967249/ReadmeImage/intro03.png --------------------------------------------------------------------------------