summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer_rd/shaders
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-10-10 23:14:56 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 12:03:52 +0100
commit561b431d85314000fe70d42e39713e5da394c3b5 (patch)
treea8260a08943abb9ed38e855a337d770d4d414cdb /servers/visual/rasterizer_rd/shaders
parenta95fb114baf6c8deb79073810ad8ea33efd4deb9 (diff)
Dynamic object support for GI Probes (a bit buggy still)
Diffstat (limited to 'servers/visual/rasterizer_rd/shaders')
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub2
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe.glsl425
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl50
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl194
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl40
5 files changed, 626 insertions, 85 deletions
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index bce700f7b0..ff83b46a9b 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -13,4 +13,6 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('copy.glsl');
env.RD_GLSL('giprobe.glsl');
env.RD_GLSL('giprobe_debug.glsl');
+ env.RD_GLSL('giprobe_sdf.glsl');
+
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe.glsl b/servers/visual/rasterizer_rd/shaders/giprobe.glsl
index a723490e8b..d756058356 100644
--- a/servers/visual/rasterizer_rd/shaders/giprobe.glsl
+++ b/servers/visual/rasterizer_rd/shaders/giprobe.glsl
@@ -4,8 +4,18 @@
VERSION_DEFINES
+#ifdef MODE_DYNAMIC
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+#else
+
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+#endif
+
+#ifndef MODE_DYNAMIC
+
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333,0.33333,0.33333)
@@ -28,11 +38,14 @@ layout(set=0,binding=2,std430) buffer CellDataBuffer {
CellData data[];
} cell_data;
+
+#endif // MODE DYNAMIC
+
#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_OMNI 1
#define LIGHT_TYPE_SPOT 2
-#ifdef MODE_COMPUTE_LIGHT
+#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
struct Light {
@@ -64,7 +77,6 @@ layout(set=0,binding=3,std140) uniform Lights {
#ifdef MODE_SECOND_BOUNCE
layout (set=0,binding=5) uniform texture3D color_texture;
-layout (set=0,binding=6) uniform sampler texture_sampler;
#ifdef MODE_ANISOTROPIC
layout (set=0,binding=7) uniform texture3D aniso_pos_texture;
@@ -73,6 +85,7 @@ layout (set=0,binding=8) uniform texture3D aniso_neg_texture;
#endif // MODE_SECOND_BOUNCE
+#ifndef MODE_DYNAMIC
layout(push_constant, binding = 0, std430) uniform Params {
@@ -96,6 +109,11 @@ layout(set=0,binding=4,std430) buffer Outputs {
vec4 data[];
} outputs;
+#endif // MODE DYNAMIC
+
+layout (set=0,binding=9) uniform texture3D texture_sdf;
+layout (set=0,binding=10) uniform sampler texture_sampler;
+
#ifdef MODE_WRITE_TEXTURE
layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
@@ -111,63 +129,97 @@ layout (r16ui,set=0,binding=7) uniform restrict writeonly uimage3D aniso_neg_tex
#endif
-#ifdef MODE_COMPUTE_LIGHT
+#ifdef MODE_DYNAMIC
-uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
+layout(push_constant, binding = 0, std430) uniform Params {
- uint result = NO_CHILDREN;
+ ivec3 limits;
+ uint light_count;
+ ivec3 x_dir;
+ float z_base;
+ ivec3 y_dir;
+ float z_sign;
+ ivec3 z_dir;
+ float pos_multiplier;
+ ivec2 rect_pos;
+ ivec2 rect_size;
+ ivec2 prev_rect_ofs;
+ ivec2 prev_rect_size;
+ bool flip_x;
+ bool flip_y;
+ float dynamic_range;
+ bool keep_downsample_color;
- ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
+} params;
- while (distance > -distance_adv) { //use this to avoid precision errors
+#ifdef MODE_DYNAMIC_LIGHTING
- uint cell = 0;
+layout (rgba8,set=0,binding=5) uniform restrict readonly image2D source_albedo;
+layout (rgba8,set=0,binding=6) uniform restrict readonly image2D source_normal;
+layout (rgba8,set=0,binding=7) uniform restrict readonly image2D source_orm;
+//layout (set=0,binding=8) uniform texture2D source_depth;
+layout (rgba16f,set=0,binding=11) uniform restrict image2D emission;
+layout (r32f,set=0,binding=12) uniform restrict image2D depth;
- ivec3 pos = ivec3(from);
+#endif
- if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
+#ifdef MODE_DYNAMIC_SHRINK
- ivec3 ofs = ivec3(0);
- ivec3 half_size = size / 2;
+layout (rgba16f,set=0,binding=5) uniform restrict readonly image2D source_light;
+layout (r32f,set=0,binding=6) uniform restrict readonly image2D source_depth;
- for (int i = 0; i < params.stack_size - 1; i++) {
+#ifdef MODE_DYNAMIC_SHRINK_WRITE
- bvec3 greater = greaterThanEqual(pos,ofs+half_size);
+layout (rgba16f,set=0,binding=7) uniform restrict writeonly image2D light;
+layout (r32f,set=0,binding=8) uniform restrict writeonly image2D depth;
- ofs += mix(ivec3(0),half_size,greater);
+#endif // MODE_DYNAMIC_SHRINK_WRITE
- uint child = 0; //wonder if this can be done faster
- if (greater.x) {
- child|=1;
- }
- if (greater.y) {
- child|=2;
- }
- if (greater.z) {
- child|=4;
- }
+#ifdef MODE_DYNAMIC_SHRINK_PLOT
- cell = cell_children.data[cell].children[child];
- if (cell == NO_CHILDREN)
- break;
+layout (rgba8,set=0,binding=11) uniform restrict image3D color_texture;
- half_size >>= ivec3(1);
- }
+#ifdef MODE_ANISOTROPIC
+
+layout (r16ui,set=0,binding=12) uniform restrict writeonly uimage3D aniso_pos_texture;
+layout (r16ui,set=0,binding=13) uniform restrict writeonly uimage3D aniso_neg_texture;
+
+#endif // MODE ANISOTROPIC
+
+#endif //MODE_DYNAMIC_SHRINK_PLOT
+
+#endif // MODE_DYNAMIC_SHRINK
+
+//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
+
+
+#endif // MODE DYNAMIC
+
+#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
+
+float raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
- if ( cell != NO_CHILDREN) {
- return cell; //found cell!
- }
+
+ vec3 cell_size = 1.0 / vec3(params.limits);
+
+ while (distance > 0.0) { //use this to avoid precision errors
+ float advance = texture(sampler3D(texture_sdf,texture_sampler),from * cell_size).r * 255.0 - 1.0;
+ if (advance<0.0) {
+ break;
}
- from += direction * distance_adv;
- distance -= distance_adv;
+ advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv
+
+ from += direction * advance;
+ distance -= advance;
}
- return NO_CHILDREN;
+ return max(0.0,distance);
+
}
-bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
+bool compute_light_vector(uint light, vec3 pos,out float attenuation, out vec3 light_pos) {
if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
@@ -226,13 +278,84 @@ float get_normal_advance(vec3 p_normal) {
return 1.0 / dot(normal,unorm);
}
-#endif
+void clip_segment(vec4 plane, vec3 begin, inout vec3 end) {
+
+ vec3 segment = begin - end;
+ float den = dot(plane.xyz,segment);
+
+ //printf("den is %i\n",den);
+ if (den < 0.0001) {
+ return;
+ }
+
+ float dist = (dot(plane.xyz,begin) - plane.w) / den;
+
+ if (dist < 0.0001 || dist > 1.0001) {
+ return;
+ }
+
+ end = begin + segment * -dist;
+}
+
+bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) {
+ float attenuation;
+ vec3 light_pos;
+
+ if (!compute_light_vector(index,pos,attenuation,light_pos)) {
+ return false;
+ }
+
+ light_dir = normalize(pos - light_pos);
+
+ if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal,light_dir)>=0)) {
+ return false; //not facing the light, or attenuation is near zero
+ }
+
+ if (lights.data[index].has_shadow) {
+
+ float distance_adv = get_normal_advance(light_dir);
+
+
+ vec3 to = pos;
+ to-= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
+
+ //clip
+ clip_segment(mix(vec4(-1.0,0.0,0.0,0.0),vec4(1.0,0.0,0.0,float(params.limits.x-1)),bvec4(light_dir.x < 0.0)),to,light_pos);
+ clip_segment(mix(vec4(0.0,-1.0,0.0,0.0),vec4(0.0,1.0,0.0,float(params.limits.y-1)),bvec4(light_dir.y < 0.0)),to,light_pos);
+ clip_segment(mix(vec4(0.0,0.0,-1.0,0.0),vec4(0.0,0.0,1.0,float(params.limits.z-1)),bvec4(light_dir.z < 0.0)),to,light_pos);
+
+
+ float distance = length(to-light_pos);
+ if (distance < 0.1) {
+ return false; // hit
+ }
+
+ distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
+ light_pos = to - light_dir * distance;
+
+ //from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
+ float dist = raymarch(distance,distance_adv,light_pos,light_dir);
+
+ if (dist > distance_adv) {
+ return false;
+ }
+
+
+ }
+
+ light = lights.data[index].color * attenuation * lights.data[index].energy;
+ return true;
+}
+
+#endif // MODE COMPUTE LIGHT
void main() {
+#ifndef MODE_DYNAMIC
+
uint cell_index = gl_GlobalInvocationID.x;;
if (cell_index >= params.cell_count) {
return;
@@ -242,6 +365,8 @@ void main() {
uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
+#endif
+
/////////////////COMPUTE LIGHT///////////////////////////////
#ifdef MODE_COMPUTE_LIGHT
@@ -249,7 +374,7 @@ void main() {
vec3 pos = vec3(posu) + vec3(0.5);
vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff,(cell_data.data[cell_index].emission >> 9) & 0x1ff,(cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0);
- vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
+ vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz;
#ifdef MODE_ANISOTROPIC
vec3 accum[6]=vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
@@ -260,41 +385,13 @@ void main() {
for(uint i=0;i<params.light_count;i++) {
- float attenuation;
- vec3 light_pos;
-
- if (!compute_light_vector(i,cell_index,pos,attenuation,light_pos)) {
+ vec3 light;
+ vec3 light_dir;
+ if (!compute_light_at_pos(i,pos,normal.xyz,light,light_dir)) {
continue;
}
- vec3 light_dir = pos - light_pos;
- float distance = length(light_dir);
- light_dir=normalize(light_dir);
-
- if (attenuation < 0.01 || (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0)) {
- continue; //not facing the light, or attenuation is near zero
- }
-
- if (lights.data[i].has_shadow) {
-
- float distance_adv = get_normal_advance(light_dir);
-
-
- distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
-
- vec3 from = pos - light_dir * distance; //approximate
- from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
-
-
-
- uint result = raymarch(distance,distance_adv,from,light_dir);
-
- if (result != cell_index) {
- continue; //was occluded
- }
- }
-
- vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
+ light*= albedo.rgb;
#ifdef MODE_ANISOTROPIC
for(uint j=0;j<6;j++) {
@@ -302,11 +399,11 @@ void main() {
accum[j]+=max(0.0,dot(accum_dirs[j],-light_dir))*light;
}
#else
- if (length(normal.xyz) > 0.2) {
- accum+=max(0.0,dot(normal.xyz,-light_dir))*light;
+ if (length(normal) > 0.2) {
+ accum+=max(0.0,dot(normal,-light_dir))*light;
} else {
//all directions
- accum+=light+emission;
+ accum+=light;
}
#endif
}
@@ -314,12 +411,17 @@ void main() {
#ifdef MODE_ANISOTROPIC
- outputs.data[cell_index*6+0]=vec4(accum[0] + emission,0.0);
- outputs.data[cell_index*6+1]=vec4(accum[1] + emission,0.0);
- outputs.data[cell_index*6+2]=vec4(accum[2] + emission,0.0);
- outputs.data[cell_index*6+3]=vec4(accum[3] + emission,0.0);
- outputs.data[cell_index*6+4]=vec4(accum[4] + emission,0.0);
- outputs.data[cell_index*6+5]=vec4(accum[5] + emission,0.0);
+ for(uint i=0;i<6;i++) {
+ vec3 light = accum[i];
+ if (length(normal) > 0.2) {
+ light += max(0.0,dot(accum_dirs[i],-normal)) * emission;
+ } else {
+ light += emission;
+ }
+
+ outputs.data[cell_index*6+i] = vec4(light,0.0);
+ }
+
#else
outputs.data[cell_index]=vec4(accum + emission,0.0);
@@ -540,4 +642,167 @@ void main() {
}
#endif
+
+///////////////////DYNAMIC LIGHTING/////////////////////////////
+
+#ifdef MODE_DYNAMIC
+
+ ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(pos_xy,params.rect_size))) {
+ return; //out of bounds
+ }
+
+ ivec2 uv_xy = pos_xy;
+ if (params.flip_x) {
+ uv_xy.x = params.rect_size.x - pos_xy.x - 1;
+ }
+ if (params.flip_y) {
+ uv_xy.y = params.rect_size.y - pos_xy.y - 1;
+ }
+
+
+#ifdef MODE_DYNAMIC_LIGHTING
+
+
+ {
+
+
+ float z = params.z_base + imageLoad(depth,uv_xy).x * params.z_sign;
+
+ ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z);
+
+ vec3 normal = imageLoad(source_normal,uv_xy).xyz * 2.0 - 1.0;
+ normal = vec3(params.x_dir) * normal.x * mix(1.0,-1.0,params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0,-1.0,params.flip_y) - vec3(params.z_dir) * normal.z;
+
+
+
+
+ vec4 albedo = imageLoad(source_albedo,uv_xy);
+
+ //determine the position in space
+
+ vec3 accum = vec3(0.0);
+ for(uint i=0;i<params.light_count;i++) {
+
+ vec3 light;
+ vec3 light_dir;
+ if (!compute_light_at_pos(i,vec3(pos) * params.pos_multiplier,normal,light,light_dir)) {
+ continue;
+ }
+
+ light*= albedo.rgb;
+
+ accum+=max(0.0,dot(normal,-light_dir))*light;
+
+ }
+
+ accum+=imageLoad(emission,uv_xy).xyz;
+
+ imageStore(emission,uv_xy,vec4(accum,albedo.a));
+ imageStore(depth,uv_xy,vec4(z));
+
+ }
+
+#endif // MODE DYNAMIC LIGHTING
+
+#ifdef MODE_DYNAMIC_SHRINK
+
+ {
+ vec4 accum = vec4(0.0);
+ float accum_z = 0.0;
+ float count = 0.0;
+
+ for(int i=0;i<4;i++) {
+ ivec2 ofs = pos_xy*2 + ivec2(i&1,i>>1) - params.prev_rect_ofs;
+ if (any(lessThan(ofs,ivec2(0))) || any(greaterThanEqual(ofs,params.prev_rect_size))) {
+ continue;
+ }
+ if (params.flip_x) {
+ ofs.x = params.prev_rect_size.x - ofs.x - 1;
+ }
+ if (params.flip_y) {
+ ofs.y = params.prev_rect_size.y - ofs.y - 1;
+ }
+
+ vec4 light = imageLoad(source_light,ofs);
+ if (light.a==0.0) { //ignore empty
+ continue;
+ }
+ accum += light;
+ float z = imageLoad(source_depth,ofs).x;
+ accum_z += z*0.5; //shrink half too
+ count+=1.0;
+ }
+
+
+ accum/=4.0;
+
+ if (count==0.0) {
+ accum_z=0.0; //avoid nan
+ } else {
+ accum_z/=count;
+ }
+
+#ifdef MODE_DYNAMIC_SHRINK_WRITE
+
+ imageStore(light,uv_xy,accum);
+ imageStore(depth,uv_xy,vec4(accum_z));
+#endif
+
+#ifdef MODE_DYNAMIC_SHRINK_PLOT
+
+
+ if (accum.a<0.001) {
+ return; //do not blit if alpha is too low
+ }
+
+ ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z);
+
+ float z_frac = fract(accum_z);
+
+ for(int i = 0; i< 2; i++) {
+ ivec3 pos3d = pos + abs(params.z_dir) * i;
+ if (any(lessThan(pos3d,ivec3(0))) || any(greaterThanEqual(pos3d,params.limits))) {
+ //skip if offlimits
+ continue;
+ }
+ vec4 color_blit = accum * (i==0 ? 1.0 - z_frac : z_frac );
+ vec4 color = imageLoad(color_texture,pos3d);
+ color.rgb *=params.dynamic_range;
+
+#if 0
+ color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a);
+ color.a+=color_blit.a;
+#else
+
+
+ float sa = 1.0 - color_blit.a;
+ vec4 result;
+ result.a = color.a * sa + color_blit.a;
+ if (result.a==0.0) {
+ result = vec4(0.0);
+ } else {
+ result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a;
+ color = result;
+ }
+
+#endif
+ color.rgb /= params.dynamic_range;
+ imageStore(color_texture,pos3d,color);
+ //imageStore(color_texture,pos3d,vec4(1,1,1,1));
+
+#ifdef MODE_ANISOTROPIC
+ //do not care about anisotropy for dynamic objects, just store full lit in all directions
+ imageStore(aniso_pos_texture,pos3d,uvec4(0xFFFF));
+ imageStore(aniso_neg_texture,pos3d,uvec4(0xFFFF));
+
+#endif // ANISOTROPIC
+ }
+#endif // MODE_DYNAMIC_SHRINK_PLOT
+
+
+ }
+#endif
+
+#endif // MODE DYNAMIC
}
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl
index 71ecaffde7..7218d2da3a 100644
--- a/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl
+++ b/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl
@@ -32,6 +32,8 @@ layout(push_constant, binding = 0, std430) uniform Params {
float dynamic_range;
float alpha;
uint level;
+ ivec3 bounds;
+ uint pad;
} params;
@@ -80,10 +82,13 @@ void main() {
vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5;
-
+#ifdef MODE_DEBUG_LIGHT_FULL
+ uvec3 posu = uvec3( gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y,gl_InstanceIndex / (params.bounds.y * params.bounds.x) );
+#else
uint cell_index = gl_InstanceIndex + params.cell_offset;
uvec3 posu = uvec3(cell_data.data[cell_index].position&0x7FF,(cell_data.data[cell_index].position>>11)&0x3FF,cell_data.data[cell_index].position>>21);
+#endif
#ifdef MODE_DEBUG_EMISSION
color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff,(cell_data.data[cell_index].emission >> 9) & 0x1ff,(cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0);
@@ -138,16 +143,24 @@ void main() {
color_interp.xyz *= strength;
#else
- color_interp.xyz = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level)).xyz * params.dynamic_range;
+ color_interp = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level));
+ color_interp.xyz * params.dynamic_range;
#endif
#endif
float scale = (1<<params.level);
- color_interp.a = params.alpha;
gl_Position = params.projection * vec4((vec3(posu)+vertex)*scale,1.0);
+#ifdef MODE_DEBUG_LIGHT_FULL
+ if (color_interp.a == 0.0) {
+ gl_Position = vec4(0.0); //force clip and not draw
+ }
+#else
+ color_interp.a = params.alpha;
+#endif
+
}
[fragment]
@@ -162,4 +175,35 @@ layout(location=0) out vec4 frag_color;
void main() {
frag_color = color_interp;
+
+#ifdef MODE_DEBUG_LIGHT_FULL
+
+ //there really is no alpha, so use dither
+
+ int x = int(gl_FragCoord.x) % 4;
+ int y = int(gl_FragCoord.y) % 4;
+ int index = x + y * 4;
+ float limit = 0.0;
+ if (x < 8) {
+ if (index == 0) limit = 0.0625;
+ if (index == 1) limit = 0.5625;
+ if (index == 2) limit = 0.1875;
+ if (index == 3) limit = 0.6875;
+ if (index == 4) limit = 0.8125;
+ if (index == 5) limit = 0.3125;
+ if (index == 6) limit = 0.9375;
+ if (index == 7) limit = 0.4375;
+ if (index == 8) limit = 0.25;
+ if (index == 9) limit = 0.75;
+ if (index == 10) limit = 0.125;
+ if (index == 11) limit = 0.625;
+ if (index == 12) limit = 1.0;
+ if (index == 13) limit = 0.5;
+ if (index == 14) limit = 0.875;
+ if (index == 15) limit = 0.375;
+ }
+ if (frag_color.a < limit) {
+ discard;
+ }
+#endif
}
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl
new file mode 100644
index 0000000000..02f0f67a15
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl
@@ -0,0 +1,194 @@
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+
+#define MAX_DISTANCE 100000
+
+#define NO_CHILDREN 0xFFFFFFFF
+#define GREY_VEC vec3(0.33333,0.33333,0.33333)
+
+struct CellChildren {
+ uint children[8];
+};
+
+layout(set=0,binding=1,std430) buffer CellChildrenBuffer {
+ CellChildren data[];
+} cell_children;
+
+
+struct CellData {
+ uint position; // xyz 10 bits
+ uint albedo; //rgb albedo
+ uint emission; //rgb normalized with e as multiplier
+ uint normal; //RGB normal encoded
+};
+
+layout(set=0,binding=2,std430) buffer CellDataBuffer {
+ CellData data[];
+} cell_data;
+
+layout (r8ui,set=0,binding=3) uniform restrict writeonly uimage3D sdf_tex;
+
+
+layout(push_constant, binding = 0, std430) uniform Params {
+
+ uint offset;
+ uint end;
+ uint pad0;
+ uint pad1;
+} params;
+
+void main() {
+
+ vec3 pos = vec3(gl_GlobalInvocationID);
+ float closest_dist = 100000.0;
+
+ for(uint i=params.offset;i<params.end;i++) {
+ vec3 posu = vec3(uvec3(cell_data.data[i].position&0x7FF,(cell_data.data[i].position>>11)&0x3FF,cell_data.data[i].position>>21));
+ float dist = length(pos-posu);
+ if (dist < closest_dist) {
+ closest_dist = dist;
+ }
+ }
+
+ uint dist_8;
+
+ if (closest_dist<0.0001) { // same cell
+ dist_8=0; //equals to -1
+ } else {
+ dist_8 = clamp(uint(closest_dist),0,254) + 1; //conservative, 0 is 1, so <1 is considered solid
+ }
+
+ imageStore(sdf_tex,ivec3(gl_GlobalInvocationID),uvec4(dist_8));
+ //imageStore(sdf_tex,pos,uvec4(pos*2,0));
+}
+
+
+#if 0
+layout(push_constant, binding = 0, std430) uniform Params {
+
+ ivec3 limits;
+ uint stack_size;
+} params;
+
+
+float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) {
+
+ vec3 delta = vec3(max(ivec3(0),max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1)))));
+ return length(delta);
+}
+
+void main() {
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID);
+
+ uint stack[10]=uint[](0,0,0,0,0,0,0,0,0,0);
+ uint stack_indices[10]=uint[](0,0,0,0,0,0,0,0,0,0);
+ ivec3 stack_positions[10]=ivec3[](ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0),ivec3(0));
+
+ const uint cell_orders[8]=uint[](
+ 0x11f58d1,
+ 0xe2e70a,
+ 0xd47463,
+ 0xbb829c,
+ 0x8d11f5,
+ 0x70ae2e,
+ 0x463d47,
+ 0x29cbb8
+ );
+
+ bool cell_found = false;
+ bool cell_found_exact = false;
+ ivec3 closest_cell_pos;
+ float closest_distance = MAX_DISTANCE;
+ int stack_pos = 0;
+
+ while(true) {
+
+ uint index = stack_indices[stack_pos]>>24;
+
+ if (index == 8) {
+ //go up
+ if (stack_pos==0) {
+ break; //done going through octree
+ }
+ stack_pos--;
+ continue;
+ }
+
+ stack_indices[stack_pos] = (stack_indices[stack_pos]&((1<<24)-1))|((index + 1)<<24);
+
+
+ uint cell_index = (stack_indices[stack_pos]>>(index*3))&0x7;
+ uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index];
+
+ if (child_cell == NO_CHILDREN) {
+ continue;
+ }
+
+ ivec3 child_cell_size = params.limits >> (stack_pos+1);
+ ivec3 child_cell_pos = stack_positions[stack_pos];
+
+ child_cell_pos+=mix(ivec3(0),child_cell_size,bvec3(uvec3(index&1,index&2,index&4)!=uvec3(0)));
+
+ bool is_leaf = stack_pos == (params.stack_size-2);
+
+ if (child_cell_pos==pos && is_leaf) {
+ //we may actually end up in the exact cell.
+ //if this happens, just abort
+ cell_found_exact=true;
+ break;
+ }
+
+ if (cell_found) {
+ //discard by distance
+ float distance = distance_to_aabb(pos,child_cell_pos,child_cell_size);
+ if (distance >= closest_distance) {
+ continue; //pointless, just test next child
+ } else if (is_leaf) {
+ //closer than what we have AND end of stack, save and continue
+ closest_cell_pos = child_cell_pos;
+ closest_distance = distance;
+ continue;
+ }
+ } else if (is_leaf) {
+ //first solid cell we find, save and continue
+ closest_distance = distance_to_aabb(pos,child_cell_pos,child_cell_size);
+ closest_cell_pos = child_cell_pos;
+ cell_found=true;
+ continue;
+ }
+
+
+
+
+ bvec3 direction = greaterThan(( pos - ( child_cell_pos + (child_cell_size >>1) ) ) , ivec3(0) );
+ uint cell_order = 0;
+ cell_order|=mix(0,1,direction.x);
+ cell_order|=mix(0,2,direction.y);
+ cell_order|=mix(0,4,direction.z);
+
+ stack[stack_pos+1]=child_cell;
+ stack_indices[stack_pos+1]=cell_orders[cell_order]; //start counting
+ stack_positions[stack_pos+1]=child_cell_pos;
+ stack_pos++; //go up stack
+
+ }
+
+ uint dist_8;
+
+ if (cell_found_exact) {
+ dist_8=0; //equals to -1
+ } else {
+ float closest_distance = length(vec3(pos-closest_cell_pos));
+ dist_8 = clamp(uint(closest_distance),0,254) + 1; //conservative, 0 is 1, so <1 is considered solid
+ }
+
+ imageStore(sdf_tex,pos,uvec4(dist_8));
+
+}
+#endif
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index a54a84536a..1ffccdc4ee 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -344,17 +344,30 @@ FRAGMENT_SHADER_GLOBALS
/* clang-format on */
+#ifdef MODE_RENDER_DEPTH
+
+#ifdef MODE_RENDER_MATERIAL
+
+layout(location = 0) out vec4 albedo_output_buffer;
+layout(location = 1) out vec4 normal_output_buffer;
+layout(location = 2) out vec4 orm_output_buffer;
+layout(location = 3) out vec4 emission_output_buffer;
+layout(location = 4) out float depth_output_buffer;
+
+#endif
+
+#else // RENDER DEPTH
+
#ifdef MODE_MULTIPLE_RENDER_TARGETS
layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
-#ifndef MODE_RENDER_DEPTH
layout(location = 0) out vec4 frag_color;
#endif
-#endif
+#endif // RENDER DEPTH
@@ -1668,6 +1681,29 @@ FRAGMENT_SHADER_CODE
#ifdef MODE_RENDER_DEPTH
+
+#ifdef MODE_RENDER_MATERIAL
+
+ albedo_output_buffer.rgb = albedo;
+ albedo_output_buffer.a = alpha;
+
+ normal_output_buffer.rgb = normal * 0.5 + 0.5;
+ normal_output_buffer.a = 0.0;
+ depth_output_buffer.r = -vertex.z;
+
+#if defined(AO_USED)
+ orm_output_buffer.r = ao;
+#else
+ orm_output_buffer.r = 0.0;
+#endif
+ orm_output_buffer.g = roughness;
+ orm_output_buffer.b = metallic;
+ orm_output_buffer.a = sss_strength;
+
+ emission_output_buffer.rgb = emission;
+ emission_output_buffer.a = 0.0;
+#endif
+
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else