aboutsummaryrefslogtreecommitdiff
path: root/src/shaders/Resolve_PS.hlsl
diff options
context:
space:
mode:
authorNathan Hoobler <[email protected]>2016-03-22 11:40:34 -0400
committerNathan Hoobler <[email protected]>2016-03-22 11:40:34 -0400
commitb4ab266c9010aaff5404f6a508a2e592eb367d36 (patch)
tree1e9eefa78e90485397b50ce5e780a1d0cb38b493 /src/shaders/Resolve_PS.hlsl
downloadvolumetriclighting-b4ab266c9010aaff5404f6a508a2e592eb367d36.tar.xz
volumetriclighting-b4ab266c9010aaff5404f6a508a2e592eb367d36.zip
initial commit
Diffstat (limited to 'src/shaders/Resolve_PS.hlsl')
-rw-r--r--src/shaders/Resolve_PS.hlsl179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/shaders/Resolve_PS.hlsl b/src/shaders/Resolve_PS.hlsl
new file mode 100644
index 0000000..72c07f9
--- /dev/null
+++ b/src/shaders/Resolve_PS.hlsl
@@ -0,0 +1,179 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+/*
+Define the shader permutations for code generation
+%% MUX_BEGIN %%
+
+- SAMPLEMODE:
+ - SAMPLEMODE_SINGLE
+ - SAMPLEMODE_MSAA
+
+%% MUX_END %%
+*/
+
+#include "ShaderCommon.h"
+
+struct RESOLVE_OUTPUT
+{
+ float3 color : SV_TARGET0;
+ float2 depth : SV_TARGET1;
+};
+
+#if (SAMPLEMODE == SAMPLEMODE_MSAA)
+Texture2DMS<float4> tGodraysBuffer : register(t0);
+Texture2DMS<float> tGodraysDepth : register(t1);
+#elif (SAMPLEMODE == SAMPLEMODE_SINGLE)
+Texture2D<float4> tGodraysBuffer : register(t0);
+Texture2D<float> tGodraysDepth : register(t1);
+#endif
+
+#if (defined(__PSSL__) && (SAMPLEMODE == SAMPLEMODE_MSAA))
+Texture2D<int2> tFMask_color : register(t2);
+#endif
+
+#if defined(__PSSL__)
+static const int FMASK_UNKNOWN = 1 << 3; // color "unknown" is always represented as high bit in the 4bit fragment index
+
+int2 getFmask(Texture2D <int2> tex, int sample_count, int2 coord)
+{
+ // if 8 or less coverage samples, only load one VGPR (32bits / 4bits per sample)
+ // if more than 8 coverage samples, we need to load 2 VGPRs
+ int2 fmask;
+ if (sample_count <= 8)
+ {
+ fmask.x = tex.Load(int3(coord, 0)).x;
+ fmask.y = 0x88888888; // all invalid -- though in theory we shouldn't need to refer to them at all.
+ }
+ else
+ {
+ fmask.xy = tex.Load(int3(coord, 0)).xy;
+ }
+ return fmask;
+}
+
+int getFptr(int index, int2 fmask)
+{
+ const int bitShift = 4; // fmask load always returns a 4bit fragment index (fptr) per coverage sample, regardless of actual number of fragments.
+ const int mask = (1 << bitShift) - 1;
+ if (index < 8)
+ return (fmask.x >> (index*bitShift)) & mask;
+ else
+ return (fmask.y >> ((index-8)*bitShift)) & mask;
+}
+#endif
+
+RESOLVE_OUTPUT main(VS_QUAD_OUTPUT input)
+{
+ float3 result_color = 0.0f;
+ float result_depth = 0.0f;
+ float result_depth_sqr = 0.0f;
+
+#if (SAMPLEMODE == SAMPLEMODE_MSAA)
+ uint2 buffer_size;
+ uint buffer_samples;
+ tGodraysBuffer.GetDimensions(buffer_size.x, buffer_size.y, buffer_samples);
+#elif (SAMPLEMODE == SAMPLEMODE_SINGLE)
+ uint buffer_samples = 1;
+#endif
+
+ int2 base_tc = int2(input.vTex * g_vViewportSize);
+ const float FILTER_SCALE = 1.0f;
+ const int KERNEL_WIDTH = 1;
+ float total_weight = 0.0f;
+ [unroll]
+ for (int ox=-KERNEL_WIDTH; ox<=KERNEL_WIDTH; ++ox)
+ {
+ if ((base_tc.x + ox) < 0 || (base_tc.x + ox) >= g_vViewportSize.x) continue;
+
+ [unroll]
+ for (int oy=-KERNEL_WIDTH; oy<=KERNEL_WIDTH; ++oy)
+ {
+ if ((base_tc.y + oy) < 0 || (base_tc.y + oy) >= g_vViewportSize.y) continue;
+
+ int2 offset = int2(ox, oy);
+ int2 tc = base_tc + offset;
+
+#if (defined(__PSSL__) && (SAMPLEMODE == SAMPLEMODE_MSAA))
+ int2 fmask = getFmask(tFMask_color, buffer_samples, tc);
+#endif
+
+#if (SAMPLEMODE == SAMPLEMODE_MSAA)
+ for (uint s=0; s<buffer_samples; ++s)
+ {
+ float2 so = offset + tGodraysBuffer.GetSamplePosition(s);
+#elif (SAMPLEMODE == SAMPLEMODE_SINGLE)
+ {
+ float2 so = offset;
+#endif
+ bool is_valid_sample = false;
+#if (SAMPLEMODE == SAMPLEMODE_MSAA)
+# if defined(__PSSL__)
+ float3 sample_value = float3(0,0,0);
+ float sample_depth = 0.0f;
+ int fptr = getFptr(s, fmask);
+ if (fptr != FMASK_UNKNOWN)
+ {
+ sample_value = tGodraysBuffer.Load(tc, fptr).rgb;
+ sample_depth = tGodraysDepth.Load( tc, fptr ).r;
+ is_valid_sample = true;
+ }
+# else // !defined(__PSSL__)
+ is_valid_sample = true;
+ float3 sample_value = tGodraysBuffer.Load( tc, s ).rgb;
+ float sample_depth = tGodraysDepth.Load( tc, s ).r;
+# endif
+#elif (SAMPLEMODE == SAMPLEMODE_SINGLE)
+ is_valid_sample = true;
+ float3 sample_value = tGodraysBuffer.Load( int3(tc, 0) ).rgb;
+ float sample_depth = tGodraysDepth.Load( int3(tc, 0) ).r;
+#endif
+ sample_depth = LinearizeDepth(sample_depth, g_fZNear, g_fZFar);
+ if (!all(isfinite(sample_value)))
+ {
+ is_valid_sample = false;
+ }
+
+ if (is_valid_sample)
+ {
+ so *= g_fResMultiplier;
+ float weight = GaussianApprox(so, FILTER_SCALE);
+ result_color += weight * sample_value;
+ result_depth += weight * sample_depth;
+ result_depth_sqr += weight * sample_depth*sample_depth;
+ total_weight += weight;
+ }
+ }
+ }
+ }
+
+ RESOLVE_OUTPUT output;
+ output.color = (total_weight > 0.0f) ? result_color/total_weight : float3(0.f, 0.f, 0.f);
+ output.depth = (total_weight > 0.0f) ? float2(result_depth, result_depth_sqr)/total_weight : 1.0f;
+ return output;
+}