diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-10-10 23:14:56 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 12:03:52 +0100 |
commit | 561b431d85314000fe70d42e39713e5da394c3b5 (patch) | |
tree | a8260a08943abb9ed38e855a337d770d4d414cdb /servers/visual/rasterizer_rd/shaders | |
parent | a95fb114baf6c8deb79073810ad8ea33efd4deb9 (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/SCsub | 2 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/giprobe.glsl | 425 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl | 50 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl | 194 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shaders/scene_forward.glsl | 40 |
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 |