mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 23:01:50 +00:00
- add some comments to shadowmap.fp
This commit is contained in:
parent
36946a47fe
commit
d65d462268
1 changed files with 41 additions and 14 deletions
|
@ -2,20 +2,22 @@
|
||||||
in vec2 TexCoord;
|
in vec2 TexCoord;
|
||||||
layout(location=0) out vec4 FragColor;
|
layout(location=0) out vec4 FragColor;
|
||||||
|
|
||||||
|
// A node in an AABB binary tree with lines stored in the leaf nodes
|
||||||
struct GPUNode
|
struct GPUNode
|
||||||
{
|
{
|
||||||
vec2 aabb_min;
|
vec2 aabb_min; // Min xy values for the axis-aligned box containing the node and its subtree
|
||||||
vec2 aabb_max;
|
vec2 aabb_max; // Max xy values
|
||||||
int left;
|
int left; // Left subnode index
|
||||||
int right;
|
int right; // Right subnode index
|
||||||
int line_index;
|
int line_index; // Line index if it is a leaf node, otherwise -1
|
||||||
int padding;
|
int padding; // Unused - maintains 16 byte alignment
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 2D line segment, referenced by leaf nodes
|
||||||
struct GPULine
|
struct GPULine
|
||||||
{
|
{
|
||||||
vec2 pos;
|
vec2 pos; // Line start position
|
||||||
vec2 delta;
|
vec2 delta; // Line end position - line start position
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 2) buffer LightNodes
|
layout(std430, binding = 2) buffer LightNodes
|
||||||
|
@ -33,6 +35,7 @@ layout(std430, binding = 4) buffer LightList
|
||||||
vec4 lights[];
|
vec4 lights[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Overlap test between line segment and axis-aligned bounding box. Returns true if they overlap.
|
||||||
bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb_max2d)
|
bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb_max2d)
|
||||||
{
|
{
|
||||||
// To do: simplify test to use a 2D test
|
// To do: simplify test to use a 2D test
|
||||||
|
@ -60,6 +63,8 @@ bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb
|
||||||
return true; // overlap;
|
return true; // overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Intersection test between two line segments.
|
||||||
|
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
|
||||||
float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydelta, float rayd, float raydist2)
|
float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydelta, float rayd, float raydist2)
|
||||||
{
|
{
|
||||||
const float epsilon = 0.0000001;
|
const float epsilon = 0.0000001;
|
||||||
|
@ -82,11 +87,14 @@ float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydel
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if an AABB tree node is a leaf node. Leaf nodes contains a line.
|
||||||
bool isLeaf(int node_index)
|
bool isLeaf(int node_index)
|
||||||
{
|
{
|
||||||
return nodes[node_index].line_index != -1;
|
return nodes[node_index].line_index != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform ray intersection test between the ray line segment and all the lines in the AABB binary tree.
|
||||||
|
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
|
||||||
float rayTest(vec2 ray_start, vec2 ray_end)
|
float rayTest(vec2 ray_start, vec2 ray_end)
|
||||||
{
|
{
|
||||||
vec2 raydelta = ray_end - ray_start;
|
vec2 raydelta = ray_end - ray_start;
|
||||||
|
@ -98,6 +106,9 @@ float rayTest(vec2 ray_start, vec2 ray_end)
|
||||||
|
|
||||||
float t = 1.0;
|
float t = 1.0;
|
||||||
|
|
||||||
|
// Walk the AABB binary tree searching for nodes touching the ray line segment's AABB box.
|
||||||
|
// When it reaches a leaf node, use a line segment intersection test to see if we got a hit.
|
||||||
|
|
||||||
int stack[16];
|
int stack[16];
|
||||||
int stack_pos = 1;
|
int stack_pos = 1;
|
||||||
stack[0] = nodes.length() - 1;
|
stack[0] = nodes.length() - 1;
|
||||||
|
@ -131,6 +142,8 @@ float rayTest(vec2 ray_start, vec2 ray_end)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
// Find the light that belongs to this texel in the shadowmap texture we output to:
|
||||||
|
|
||||||
int lightIndex = int(gl_FragCoord.y);
|
int lightIndex = int(gl_FragCoord.y);
|
||||||
|
|
||||||
vec4 light = lights[lightIndex];
|
vec4 light = lights[lightIndex];
|
||||||
|
@ -139,18 +152,32 @@ void main()
|
||||||
|
|
||||||
if (radius > 0.0)
|
if (radius > 0.0)
|
||||||
{
|
{
|
||||||
vec2 pixelpos;
|
// We found an active light. Calculate the ray direction for the texel.
|
||||||
|
//
|
||||||
|
// The texels are laid out so that there are four projections:
|
||||||
|
//
|
||||||
|
// * top-left to top-right
|
||||||
|
// * top-right to bottom-right
|
||||||
|
// * bottom-right to bottom-left
|
||||||
|
// * bottom-left to top-left
|
||||||
|
//
|
||||||
|
vec2 raydir;
|
||||||
float u = gl_FragCoord.x / ShadowmapQuality * 4.0;
|
float u = gl_FragCoord.x / ShadowmapQuality * 4.0;
|
||||||
switch (int(u))
|
switch (int(u))
|
||||||
{
|
{
|
||||||
case 0: pixelpos = vec2(u * 2.0 - 1.0, 1.0); break;
|
case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break;
|
||||||
case 1: pixelpos = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
|
case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
|
||||||
case 2: pixelpos = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
|
case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
|
||||||
case 3: pixelpos = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
|
case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
|
||||||
}
|
}
|
||||||
pixelpos = lightpos + pixelpos * radius;
|
|
||||||
|
|
||||||
|
// Find the position for the ray starting at the light position and travelling until light contribution is zero:
|
||||||
|
vec2 pixelpos = lightpos + raydir * radius;
|
||||||
|
|
||||||
|
// Check if we hit any line between the light and the end position:
|
||||||
float t = rayTest(lightpos, pixelpos);
|
float t = rayTest(lightpos, pixelpos);
|
||||||
|
|
||||||
|
// Calculate the square distance for the hit, if any:
|
||||||
vec2 delta = (pixelpos - lightpos) * t;
|
vec2 delta = (pixelpos - lightpos) * t;
|
||||||
float dist2 = dot(delta, delta);
|
float dist2 = dot(delta, delta);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue