-
Notifications
You must be signed in to change notification settings - Fork 3
/
final_gathering.comp
135 lines (104 loc) · 4.96 KB
/
final_gathering.comp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#version 430
#extension GL_ARB_shading_language_include : require
#include </data/shaders/ism/ism_utils.glsl>
#include </data/shaders/common/reprojection.glsl>
struct VPL {
vec3 position;
vec3 normal;
vec3 color;
};
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout (r11f_g11f_b10f, binding = 0) restrict writeonly uniform image2D img_output;
layout (r16ui, binding = 1) restrict readonly uniform uimage3D lightListIds;
layout (r16ui, binding = 2) restrict readonly uniform uimage2D lightLists;
const int totalVplCount = 1024;
layout (packed, binding = 0) uniform vplBuffer_
{
VPL vplBuffer[totalVplCount];
};
uniform sampler2D faceNormalSampler;
uniform sampler2D depthSampler;
uniform sampler2D ismDepthSampler;
uniform mat4 projectionMatrix;
uniform mat4 projectionInverseMatrix;
uniform mat4 viewMatrix;
uniform mat4 viewInvertedMatrix;
uniform mat4 viewProjectionInvertedMatrix;
uniform float zFar;
uniform float zNear;
uniform ivec2 viewport;
uniform float giIntensityFactor;
uniform float vplClampingValue;
uniform int vplStartIndex = 0;
uniform int vplEndIndex = totalVplCount;
int vplCount = vplEndIndex - vplStartIndex;
#define SCALE_ISMS false
float ismIndexOffset = SCALE_ISMS ? vplStartIndex : 0;
int ismCount = (SCALE_ISMS) ? vplCount : totalVplCount;
int ismIndices1d = int(pow(2, ceil(log2(ismCount) / 2))); // next even power of two
// global replacements
#define SHOW_VPL_POSITIONS false
#define ENABLE_SHADOWING true
#define USE_INTERLEAVING true
const uint interleavedSize = USE_INTERLEAVING ? 4 : 1;
const uint interleavedPixels = interleavedSize*interleavedSize;
// number of bits that will be taken from gl_WorkGroupID to determine the interleavedPixel
const uint interleaveBits = uint(log2(interleavedSize));
// set interleaveBits rightmost bits to 1
const uint interleavedPixelBitmask = (1u << interleaveBits) - 1u;
const uint clusterPixelSize = 128;
void main()
{
uvec2 largeInterleaveBlockPosition = (gl_WorkGroupID.xy >> interleaveBits) * gl_WorkGroupSize.xy * interleavedSize;
uvec2 offsetInLargeInterleaveBlock = gl_LocalInvocationID.xy * interleavedSize;
uvec2 interleavedPixel = gl_WorkGroupID.xy & interleavedPixelBitmask;
ivec2 fragCoord = ivec2(largeInterleaveBlockPosition + offsetInLargeInterleaveBlock + interleavedPixel);
vec2 v_uv = vec2(fragCoord) / viewport;
// TODO maybe view rays again? could re-use view z for cluster coord
float depthSample = texelFetch(depthSampler, fragCoord, 0).r;
vec4 ndc = vec4(v_uv, depthSample, 1.0) * 2.0 - 1.0;
vec4 fragWorldCoordWithW = viewProjectionInvertedMatrix * ndc;
vec3 fragWorldCoord = fragWorldCoordWithW.xyz / fragWorldCoordWithW.w;
vec3 fragNormal = texelFetch(faceNormalSampler, fragCoord, 0).xyz * 2.0 - 1.0;
const int numDepthSlices = 16;
const int numSlicesIntoFirstSlice = 3;
float scaleFactor = (numDepthSlices + numSlicesIntoFirstSlice) / log2(50);
float depth = linearDepth(depthSample, projectionMatrix);
int clusterZ = int(max(log2(-depth) * scaleFactor - numSlicesIntoFirstSlice, 0));
uvec2 clusterCoord = uvec2(fragCoord.xy) / clusterPixelSize;
uint lightListId = imageLoad(lightListIds, ivec3(clusterCoord, clusterZ)).r;
uint interleavedPixel1d = interleavedPixel.x + interleavedPixel.y * interleavedSize;
uint startIndex = totalVplCount / interleavedPixels * interleavedPixel1d;
uint numLights = imageLoad(lightLists, ivec2(lightListId, startIndex)).r;
vec3 acc = vec3(0.0);
for (uint lightIndex = 1; lightIndex < numLights; lightIndex++) {
uint vplIndex = imageLoad(lightLists, ivec2(lightListId, startIndex + lightIndex)).r;
VPL vpl = vplBuffer[vplIndex];
vec3 diff = fragWorldCoord - vpl.position ;
float dist = length(diff);
vec3 normalizedDiff = diff / dist;
if(SHOW_VPL_POSITIONS) {
float isNearLight = 1.0 - step(0.15, dist);
acc += isNearLight * vpl.color / dist / dist * 0.0001;
}
// geometry term
float angleFactor = max(0.0, dot(vpl.normal, normalizedDiff)) * max(0.0, dot(fragNormal, -normalizedDiff));
if (angleFactor <= 0.0)
continue;
float attenuation = 1.0 / pow(dist, 4.0);
float geometryTerm = angleFactor * attenuation;
geometryTerm = min(geometryTerm, vplClampingValue);
if (ENABLE_SHADOWING) {
float ismIndex = vplIndex - ismIndexOffset;
vec3 v = paraboloid_project(diff, dist, vpl.normal, zFar, ismIndex, ismIndices1d, false);
float occluderDepth = textureLod(ismDepthSampler, v.xy, 0).x;
float shadowValue = v.z - occluderDepth;
float shadowBias = 0.02;
shadowValue = smoothstep(1.0 - shadowBias, 1.0, 1 - shadowValue);
geometryTerm *= shadowValue;
}
acc += vpl.color * geometryTerm;
}
vec3 resultColor = vec3(acc * giIntensityFactor / vplCount) * interleavedPixels;
imageStore(img_output, fragCoord, vec4(resultColor, 0.0));
}