Initial commit: Final state of the master project
This commit is contained in:
234
Research/shaders/Shader.frag
Normal file
234
Research/shaders/Shader.frag
Normal file
@@ -0,0 +1,234 @@
|
||||
#version 440 core
|
||||
|
||||
in vec3 pos;
|
||||
in vec2 uv;
|
||||
in vec3 normal;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D textureSampler;
|
||||
uniform usampler3D octreeSampler;
|
||||
|
||||
layout(location = $width$) uniform int width;
|
||||
layout(location = $height$) uniform int height;
|
||||
layout(location = $angle$) uniform float angle;
|
||||
layout(location = $aspect$) uniform float aspect;
|
||||
|
||||
layout(location = $lightDirection$) uniform vec3 lightDirection;
|
||||
layout(location = $cameraPosition$) uniform vec3 cameraPosition;
|
||||
|
||||
|
||||
//************************************
|
||||
// Intersection test between ray and cube, also gives intersection points as p0 + tmin * ray and p0 + tmax * ray
|
||||
//************************************
|
||||
bool rayCube(vec3 p0, vec3 ray, vec3 center, float extent, out float tmin, out float tmax, out uint minFace, out uint maxFace) {
|
||||
|
||||
// Translate ray origin based on cube center
|
||||
p0 -= center;
|
||||
|
||||
// Get t from ray and cube's plane equations and use it to get the intersection coordinates
|
||||
float t1 = -(dot(p0, vec3(1., 0., 0.)) - extent) / dot(ray, vec3(1., 0., 0.)); vec3 test1 = p0 + t1*ray;
|
||||
float t2 = -(dot(p0, vec3(-1., 0., 0.)) - extent) / dot(ray, vec3(-1., 0., 0.)); vec3 test2 = p0 + t2*ray;
|
||||
float t3 = -(dot(p0, vec3(0., 1., 0.)) - extent) / dot(ray, vec3(0., 1., 0.)); vec3 test3 = p0 + t3*ray;
|
||||
float t4 = -(dot(p0, vec3(0., -1., 0.)) - extent) / dot(ray, vec3(0., -1., 0.)); vec3 test4 = p0 + t4*ray;
|
||||
float t5 = -(dot(p0, vec3(0., 0., 1.)) - extent) / dot(ray, vec3(0., 0., 1.)); vec3 test5 = p0 + t5*ray;
|
||||
float t6 = -(dot(p0, vec3(0., 0., -1.)) - extent) / dot(ray, vec3(0., 0., -1.)); vec3 test6 = p0 + t6*ray;
|
||||
|
||||
// Check if t was not negative and that the ray-plane intersection falls within the cube face
|
||||
if (t1 < 0. || any(greaterThanEqual(test1.yz, vec2(extent))) || any(lessThanEqual(test1.yz, vec2(-extent))))
|
||||
t1 = 0.;
|
||||
if (t2 < 0. || any(greaterThanEqual(test2.yz, vec2(extent))) || any(lessThanEqual(test2.yz, vec2(-extent))))
|
||||
t2 = 0.;
|
||||
if (t3 < 0. || any(greaterThanEqual(test3.xz, vec2(extent))) || any(lessThanEqual(test3.xz, vec2(-extent))))
|
||||
t3 = 0.;
|
||||
if (t4 < 0. || any(greaterThanEqual(test4.xz, vec2(extent))) || any(lessThanEqual(test4.xz, vec2(-extent))))
|
||||
t4 = 0.;
|
||||
if (t5 < 0. || any(greaterThanEqual(test5.xy, vec2(extent))) || any(lessThanEqual(test5.xy, vec2(-extent))))
|
||||
t5 = 0.;
|
||||
if (t6 < 0. || any(greaterThanEqual(test6.xy, vec2(extent))) || any(lessThanEqual(test6.xy, vec2(-extent))))
|
||||
t6 = 0.;
|
||||
|
||||
// Initialize tmin and tmax values that define the two intersection points
|
||||
tmin = 9999999999.;
|
||||
tmax = 0.;
|
||||
|
||||
// Use the lowest value of t that is not 0 for tmin
|
||||
if (t1 > 0. && t1 <= tmin) tmin = t1;
|
||||
if (t2 > 0. && t2 <= tmin) tmin = t2;
|
||||
if (t3 > 0. && t3 <= tmin) tmin = t3;
|
||||
if (t4 > 0. && t4 <= tmin) tmin = t4;
|
||||
if (t5 > 0. && t5 <= tmin) tmin = t5;
|
||||
if (t6 > 0. && t6 <= tmin) tmin = t6;
|
||||
|
||||
// Use the highest value of t that is not 0 for tmax
|
||||
if (t1 > 0. && t1 >= tmax) tmax = t1;
|
||||
if (t2 > 0. && t2 >= tmax) tmax = t2;
|
||||
if (t3 > 0. && t3 >= tmax) tmax = t3;
|
||||
if (t4 > 0. && t4 >= tmax) tmax = t4;
|
||||
if (t5 > 0. && t5 >= tmax) tmax = t5;
|
||||
if (t6 > 0. && t6 >= tmax) tmax = t6;
|
||||
|
||||
// If tmin = tmax, the ray origin is within the cube, so set tmin to 0
|
||||
if (tmin == tmax)
|
||||
tmin = 0.;
|
||||
|
||||
// Figure out which face the ray exits
|
||||
if (t1 == tmin) minFace = 1;
|
||||
if (t2 == tmin) minFace = 2;
|
||||
if (t3 == tmin) minFace = 3;
|
||||
if (t4 == tmin) minFace = 4;
|
||||
if (t5 == tmin) minFace = 5;
|
||||
if (t6 == tmin) minFace = 6;
|
||||
|
||||
if (t1 == tmax) maxFace = 1;
|
||||
if (t2 == tmax) maxFace = 2;
|
||||
if (t3 == tmax) maxFace = 3;
|
||||
if (t4 == tmax) maxFace = 4;
|
||||
if (t5 == tmax) maxFace = 5;
|
||||
if (t6 == tmax) maxFace = 6;
|
||||
|
||||
// If tmax is not 0, an intersection was found
|
||||
return tmax > 0.;
|
||||
}
|
||||
|
||||
//************************************
|
||||
// Sample the octree at a location, return if geometry is present here and return deepest level reached when traversing
|
||||
//************************************
|
||||
uvec4 sampleOctree(vec3 loc) {
|
||||
ivec3 texSize = textureSize(octreeSampler, 0);
|
||||
|
||||
// Set location in range (0,2^$max_level$)
|
||||
uint range = 1 << $max_level$;
|
||||
loc = range + range * loc / $extent$;
|
||||
uvec3 uLoc = uvec3(loc.x, loc.y, loc.z);
|
||||
|
||||
uvec3 result = uvec3(0);
|
||||
|
||||
// Traverse octree
|
||||
uint i = 0;
|
||||
for (; i <= $max_level$; ++i) {
|
||||
|
||||
if (i == $max_level$)
|
||||
{ // Leaf node was reached, fetch the full color:
|
||||
return uvec4(texelFetch(octreeSampler, ivec3(result), 0).rgb, i);
|
||||
}
|
||||
|
||||
// Read the childmask (stored in "blue"):
|
||||
uint childMask = texelFetch(octreeSampler, ivec3(result), 0).b;
|
||||
|
||||
// If the mask is empty, we got a child node
|
||||
if (childMask == 0)
|
||||
break;
|
||||
|
||||
// Find the index of the child in which the sampleposition is located
|
||||
range = 1 << ($max_level$ - i);
|
||||
uint childIndex = ((uLoc.x & range) == range ? 1 : 0)
|
||||
+ ((uLoc.y & range) == range ? 2 : 0)
|
||||
+ ((uLoc.z & range) == range ? 4 : 0);
|
||||
|
||||
uint mask = 1 << childIndex;
|
||||
if ((childMask & mask) == 0) // The child doesn't exist, even though this is not a leaf node
|
||||
break;//return vec4(255, 255, 0, float($max_level$ + 1));
|
||||
// Based on this index and the childmask, find out what the index of the childpointer is
|
||||
uint childPointerIndex = 0;
|
||||
for(int j = 0; j < 8; j++)
|
||||
{
|
||||
uint mask = 1 << j;
|
||||
if ((childMask & mask) == mask)
|
||||
childPointerIndex++;
|
||||
if (j == childIndex)
|
||||
break;
|
||||
}
|
||||
// Find sample position in 3D texture corresponding to current node and location
|
||||
uvec3 samplePos = result;
|
||||
samplePos.x += childPointerIndex;
|
||||
if (samplePos.x >= texSize.x)
|
||||
{
|
||||
samplePos.x = samplePos.x % texSize.x;
|
||||
samplePos.y++;
|
||||
if (samplePos.y >= texSize.y)
|
||||
{
|
||||
samplePos.y = samplePos.y % texSize.y;
|
||||
samplePos.z++;
|
||||
}
|
||||
//return vec4(255, 255, 0, float($max_level$ + 1));
|
||||
}
|
||||
|
||||
result = texelFetch(octreeSampler, ivec3(samplePos), 0).rgb;
|
||||
|
||||
// If not, this is not a leaf node, so result actually contains a pointer to the 3D location of the child
|
||||
// Multiply the location by two to go to next level
|
||||
//loc *= 2.;
|
||||
}
|
||||
// Return level reached, and the pointer found there?
|
||||
return uvec4(result, i);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
uint maxLoop = 4096;
|
||||
|
||||
// Set color using textures
|
||||
color = texture(textureSampler, uv);
|
||||
|
||||
// Get ray and sample point
|
||||
vec3 ray = normalize(pos - cameraPosition);
|
||||
|
||||
vec3 samplePoint = cameraPosition;
|
||||
float extent = $extent$;
|
||||
float tmin, tmax;
|
||||
uint minFace = 0;
|
||||
uint maxFace;
|
||||
uint crap;
|
||||
|
||||
// Calculate the rayCube intersection with the root:
|
||||
float tmaxRoot, tminRoot;
|
||||
if (!rayCube(cameraPosition, ray, vec3(0.), extent, tminRoot, tmaxRoot, crap, crap))
|
||||
return;
|
||||
float t = tminRoot;
|
||||
|
||||
// Keep testing ray box intersection, but prevent endless looping
|
||||
int loop = 0;
|
||||
while (t < tmaxRoot && loop < maxLoop) {
|
||||
|
||||
samplePoint = cameraPosition + t * ray + 0.001 * ray;
|
||||
|
||||
// Sample octree at sample point and store reached level
|
||||
uvec4 result = sampleOctree(samplePoint);
|
||||
uint reached_level = result.w;
|
||||
|
||||
// If the reached level is max_level + 1, we have reached geometry, so color the pixel and break from loop
|
||||
if (reached_level == $max_level$) {
|
||||
color.rgb = /*(loop / 120.) * (0. + (float(minFace) * 0.16666666)) **/ (vec3(result) / 255.);
|
||||
//color.rgb = samplePoint / $extent$;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set cube center to 0 and current extent to overall extent
|
||||
vec3 cubeCenter = vec3(0.);
|
||||
float currentExtent = extent;
|
||||
// Convert relative sample point to (-1,1) range for easier computations
|
||||
vec3 relativeSamplePoint = samplePoint / extent;
|
||||
|
||||
// Loop through all reached levels
|
||||
for (int j = 0; j <= reached_level; ++j) {
|
||||
// At every level, compute the cube center of the node that was sampled at this level and the sample point relative to this node
|
||||
cubeCenter += sign(relativeSamplePoint) * .5 * currentExtent;
|
||||
relativeSamplePoint = sign(relativeSamplePoint) * (-1. + 2. * abs(relativeSamplePoint));
|
||||
currentExtent *= .5;
|
||||
}
|
||||
|
||||
// Use the obtained cube center to do another ray-box intersection test
|
||||
rayCube(cameraPosition, ray, cubeCenter, currentExtent, tmin, tmax, minFace, maxFace);
|
||||
|
||||
t = tmax;
|
||||
|
||||
++loop;
|
||||
}
|
||||
if (loop == maxLoop)
|
||||
color.rgb = vec3(1, 0,0);
|
||||
|
||||
// Discard pixels that are transparent
|
||||
if (color.a < 0.5)
|
||||
discard;
|
||||
}
|
||||
Reference in New Issue
Block a user