summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer_rd/shaders
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-10-03 17:39:08 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 12:03:20 +0100
commitacf0f6c8a7955517ef71ec95c683a6ff7bd5f437 (patch)
tree2bbadc4c770579be1f63317363b1843efff4d6f1 /servers/visual/rasterizer_rd/shaders
parent52f96abd8ba4323ff358f34683f9502ec24b9961 (diff)
GIProbes working.
Diffstat (limited to 'servers/visual/rasterizer_rd/shaders')
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub3
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe.glsl543
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl160
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe_lighting.glsl241
-rw-r--r--servers/visual/rasterizer_rd/shaders/giprobe_write.glsl353
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl302
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl123
7 files changed, 1415 insertions, 310 deletions
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index 660523e29f..bce700f7b0 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -11,5 +11,6 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('sky.glsl');
env.RD_GLSL('tonemap.glsl');
env.RD_GLSL('copy.glsl');
- env.RD_GLSL('giprobe_lighting.glsl');
+ env.RD_GLSL('giprobe.glsl');
+ env.RD_GLSL('giprobe_debug.glsl');
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe.glsl b/servers/visual/rasterizer_rd/shaders/giprobe.glsl
new file mode 100644
index 0000000000..35b8d6ba6b
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/giprobe.glsl
@@ -0,0 +1,543 @@
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+#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;
+
+#define LIGHT_TYPE_DIRECTIONAL 0
+#define LIGHT_TYPE_OMNI 1
+#define LIGHT_TYPE_SPOT 2
+
+#ifdef MODE_COMPUTE_LIGHT
+
+struct Light {
+
+ uint type;
+ float energy;
+ float radius;
+ float attenuation;
+
+ vec3 color;
+ float spot_angle_radians;
+
+ vec3 position;
+ float spot_attenuation;
+
+ vec3 direction;
+ bool has_shadow;
+};
+
+
+layout(set=0,binding=3,std140) uniform Lights {
+ Light data[MAX_LIGHTS];
+} lights;
+
+
+
+#endif // MODE COMPUTE LIGHT
+
+
+#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;
+layout (set=0,binding=8) uniform texture3D aniso_neg_texture;
+#endif // MODE ANISOTROPIC
+
+#endif // MODE_SECOND_BOUNCE
+
+
+layout(push_constant, binding = 0, std430) uniform Params {
+
+ ivec3 limits;
+ uint stack_size;
+
+ float emission_scale;
+ float propagation;
+ float dynamic_range;
+
+ uint light_count;
+ uint cell_offset;
+ uint cell_count;
+ float aniso_strength;
+ uint pad;
+
+} params;
+
+
+layout(set=0,binding=4,std430) buffer Outputs {
+ vec4 data[];
+} outputs;
+
+#ifdef MODE_WRITE_TEXTURE
+
+layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
+
+#ifdef MODE_ANISOTROPIC
+
+layout (r16ui,set=0,binding=6) uniform restrict writeonly uimage3D aniso_pos_tex;
+layout (r16ui,set=0,binding=7) uniform restrict writeonly uimage3D aniso_neg_tex;
+
+#endif
+
+
+#endif
+
+
+#ifdef MODE_COMPUTE_LIGHT
+
+uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
+
+ uint result = NO_CHILDREN;
+
+ ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
+
+ while (distance > -distance_adv) { //use this to avoid precision errors
+
+ uint cell = 0;
+
+ ivec3 pos = ivec3(from);
+
+ if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
+
+ ivec3 ofs = ivec3(0);
+ ivec3 half_size = size / 2;
+
+ for (int i = 0; i < params.stack_size - 1; i++) {
+
+ bvec3 greater = greaterThanEqual(pos,ofs+half_size);
+
+ ofs += mix(ivec3(0),half_size,greater);
+
+ 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;
+ }
+
+ cell = cell_children.data[cell].children[child];
+ if (cell == NO_CHILDREN)
+ break;
+
+ half_size >>= ivec3(1);
+ }
+
+ if ( cell != NO_CHILDREN) {
+ return cell; //found cell!
+ }
+
+ }
+
+ from += direction * distance_adv;
+ distance -= distance_adv;
+ }
+
+ return NO_CHILDREN;
+}
+
+bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
+
+
+ if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
+
+ light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
+ attenuation = 1.0;
+
+ } else {
+
+ light_pos = lights.data[light].position;
+ float distance = length(pos - light_pos);
+ if (distance >= lights.data[light].radius) {
+ return false;
+ }
+
+
+ attenuation = pow( clamp( 1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation );
+
+
+ if (lights.data[light].type==LIGHT_TYPE_SPOT) {
+
+ vec3 rel = normalize(pos - light_pos);
+ float angle = acos(dot(rel,lights.data[light].direction));
+ if (angle > lights.data[light].spot_angle_radians) {
+ return false;
+ }
+
+ float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
+ attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
+ }
+ }
+
+ return true;
+}
+
+float get_normal_advance(vec3 p_normal) {
+
+ vec3 normal = p_normal;
+ vec3 unorm = abs(normal);
+
+ if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+ } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+ } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3(1.0, 0.0, 0.0);
+ }
+
+ return 1.0 / dot(normal,unorm);
+}
+
+#endif
+
+
+
+
+void main() {
+
+ uint cell_index = gl_GlobalInvocationID.x;;
+ if (cell_index >= params.cell_count) {
+ return;
+ }
+ cell_index += 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);
+ vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
+
+/////////////////COMPUTE LIGHT///////////////////////////////
+
+#ifdef MODE_COMPUTE_LIGHT
+
+ vec3 pos = vec3(posu) + vec3(0.5);
+
+ vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission&0x3FF,(cell_data.data[cell_index].emission>>10)&0x7FF,cell_data.data[cell_index].emission>>21)) * params.emission_scale;
+ vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
+
+#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));
+ const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
+#else
+ vec3 accum = vec3(0.0);
+#endif
+
+ 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)) {
+ continue;
+ }
+
+ vec3 light_dir = pos - light_pos;
+ float distance = length(light_dir);
+ light_dir=normalize(light_dir);
+
+ if (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0) {
+ continue; //not facing the light
+ }
+
+ 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;
+
+#ifdef MODE_ANISOTROPIC
+ for(uint j=0;j<6;j++) {
+
+ accum[j]+=max(0.0,dot(accum_dirs[j],-light_dir))*light+emission;
+ }
+#else
+ if (length(normal.xyz) > 0.2) {
+ accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
+ } else {
+ //all directions
+ accum+=light+emission;
+ }
+#endif
+ }
+
+
+#ifdef MODE_ANISOTROPIC
+
+ outputs.data[cell_index*6+0]=vec4(accum[0],0.0);
+ outputs.data[cell_index*6+1]=vec4(accum[1],0.0);
+ outputs.data[cell_index*6+2]=vec4(accum[2],0.0);
+ outputs.data[cell_index*6+3]=vec4(accum[3],0.0);
+ outputs.data[cell_index*6+4]=vec4(accum[4],0.0);
+ outputs.data[cell_index*6+5]=vec4(accum[5],0.0);
+#else
+ outputs.data[cell_index]=vec4(accum,0.0);
+
+#endif
+
+
+
+#endif //MODE_COMPUTE_LIGHT
+
+/////////////////SECOND BOUNCE///////////////////////////////
+#ifdef MODE_SECOND_BOUNCE
+ vec3 pos = vec3(posu) + vec3(0.5);
+ ivec3 ipos = ivec3(posu);
+ vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
+
+
+#ifdef MODE_ANISOTROPIC
+ vec3 accum[6];
+ const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
+
+ /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range;
+ vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb;
+ vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb;
+ accum[0]=src_col * src_aniso_pos.x;
+ accum[1]=src_col * src_aniso_neg.x;
+ accum[2]=src_col * src_aniso_pos.y;
+ accum[3]=src_col * src_aniso_neg.y;
+ accum[4]=src_col * src_aniso_pos.z;
+ accum[5]=src_col * src_aniso_neg.z;*/
+
+ accum[0] = outputs.data[cell_index*6+0].rgb;
+ accum[1] = outputs.data[cell_index*6+1].rgb;
+ accum[2] = outputs.data[cell_index*6+2].rgb;
+ accum[3] = outputs.data[cell_index*6+3].rgb;
+ accum[4] = outputs.data[cell_index*6+4].rgb;
+ accum[5] = outputs.data[cell_index*6+5].rgb;
+
+#else
+ vec3 accum = outputs.data[cell_index].rgb;
+
+#endif
+
+ if (length(normal.xyz) > 0.2) {
+
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal.xyz));
+ vec3 bitangent = normalize(cross(tangent, normal.xyz));
+ mat3 normal_mat = mat3(tangent, bitangent, normal.xyz);
+
+#define MAX_CONE_DIRS 6
+
+ vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
+ vec3(0.0, 0.0, 1.0),
+ vec3(0.866025, 0.0, 0.5),
+ vec3(0.267617, 0.823639, 0.5),
+ vec3(-0.700629, 0.509037, 0.5),
+ vec3(-0.700629, -0.509037, 0.5),
+ vec3(0.267617, -0.823639, 0.5));
+
+ float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
+ float tan_half_angle = 0.577;
+
+ for (int i = 0; i < MAX_CONE_DIRS; i++) {
+
+ vec3 direction = normal_mat * cone_dirs[i];
+ vec4 color = vec4(0.0);
+ {
+
+ float dist = 1.5;
+ float max_distance = length(vec3(params.limits));
+ vec3 cell_size = 1.0 / vec3(params.limits);
+
+#ifdef MODE_ANISOTROPIC
+ vec3 aniso_normal = mix(direction,normal.xyz,params.aniso_strength);
+#endif
+ while (dist < max_distance && color.a < 0.95) {
+ float diameter = max(1.0, 2.0 * tan_half_angle * dist);
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+ float half_diameter = diameter * 0.5;
+ //check if outside, then break
+ //if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
+ // break;
+ //}
+
+ float log2_diameter = log2(diameter);
+ vec4 scolor = textureLod(sampler3D(color_texture,texture_sampler), uvw_pos, log2_diameter);
+#ifdef MODE_ANISOTROPIC
+
+ vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture,texture_sampler), uvw_pos, log2_diameter).rgb;
+ vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture,texture_sampler), uvw_pos, log2_diameter).rgb;
+
+ scolor.rgb*=dot(max(vec3(0.0),(aniso_normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-aniso_normal * aniso_neg)),vec3(1.0));
+#endif
+ float a = (1.0 - color.a);
+ color += a * scolor;
+ dist += half_diameter;
+
+ }
+
+ }
+ color *= cone_weights[i] * params.dynamic_range; //restore range
+#ifdef MODE_ANISOTROPIC
+ for(uint j=0;j<6;j++) {
+
+ accum[j]+=max(0.0,dot(accum_dirs[j],direction))*color.rgb;
+ }
+#else
+ accum+=color.rgb;
+#endif
+ }
+ }
+
+#ifdef MODE_ANISOTROPIC
+
+ outputs.data[cell_index*6+0]=vec4(accum[0],0.0);
+ outputs.data[cell_index*6+1]=vec4(accum[1],0.0);
+ outputs.data[cell_index*6+2]=vec4(accum[2],0.0);
+ outputs.data[cell_index*6+3]=vec4(accum[3],0.0);
+ outputs.data[cell_index*6+4]=vec4(accum[4],0.0);
+ outputs.data[cell_index*6+5]=vec4(accum[5],0.0);
+#else
+ outputs.data[cell_index]=vec4(accum,0.0);
+
+#endif
+
+#endif // MODE_SECOND_BOUNCE
+/////////////////UPDATE MIPMAPS///////////////////////////////
+
+#ifdef MODE_UPDATE_MIPMAPS
+
+ {
+#ifdef MODE_ANISOTROPIC
+ vec3 light_accum[6] = vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
+#else
+ vec3 light_accum = vec3(0.0);
+#endif
+ float count = 0.0;
+ for(uint i=0;i<8;i++) {
+ uint child_index = cell_children.data[cell_index].children[i];
+ if (child_index==NO_CHILDREN) {
+ continue;
+ }
+#ifdef MODE_ANISOTROPIC
+ light_accum[0] += outputs.data[child_index*6+0].rgb;
+ light_accum[1] += outputs.data[child_index*6+1].rgb;
+ light_accum[2] += outputs.data[child_index*6+2].rgb;
+ light_accum[3] += outputs.data[child_index*6+3].rgb;
+ light_accum[4] += outputs.data[child_index*6+4].rgb;
+ light_accum[5] += outputs.data[child_index*6+5].rgb;
+
+#else
+ light_accum += outputs.data[child_index].rgb;
+
+#endif
+
+ count+=1.0;
+ }
+
+ float divisor = mix(8.0,count,params.propagation);
+#ifdef MODE_ANISOTROPIC
+ outputs.data[cell_index*6+0]=vec4(light_accum[0] / divisor,0.0);
+ outputs.data[cell_index*6+1]=vec4(light_accum[1] / divisor,0.0);
+ outputs.data[cell_index*6+2]=vec4(light_accum[2] / divisor,0.0);
+ outputs.data[cell_index*6+3]=vec4(light_accum[3] / divisor,0.0);
+ outputs.data[cell_index*6+4]=vec4(light_accum[4] / divisor,0.0);
+ outputs.data[cell_index*6+5]=vec4(light_accum[5] / divisor,0.0);
+
+#else
+ outputs.data[cell_index]=vec4(light_accum / divisor,0.0);
+#endif
+
+
+
+ }
+#endif
+
+///////////////////WRITE TEXTURE/////////////////////////////
+
+#ifdef MODE_WRITE_TEXTURE
+ {
+
+#ifdef MODE_ANISOTROPIC
+ vec3 accum_total = vec3(0.0);
+ accum_total += outputs.data[cell_index*6+0].rgb;
+ accum_total += outputs.data[cell_index*6+1].rgb;
+ accum_total += outputs.data[cell_index*6+2].rgb;
+ accum_total += outputs.data[cell_index*6+3].rgb;
+ accum_total += outputs.data[cell_index*6+4].rgb;
+ accum_total += outputs.data[cell_index*6+5].rgb;
+
+ float accum_total_energy = max(dot(accum_total,GREY_VEC),0.00001);
+ vec3 iso_positive = vec3(dot(outputs.data[cell_index*6+0].rgb,GREY_VEC),dot(outputs.data[cell_index*6+2].rgb,GREY_VEC),dot(outputs.data[cell_index*6+4].rgb,GREY_VEC))/vec3(accum_total_energy);
+ vec3 iso_negative = vec3(dot(outputs.data[cell_index*6+1].rgb,GREY_VEC),dot(outputs.data[cell_index*6+3].rgb,GREY_VEC),dot(outputs.data[cell_index*6+5].rgb,GREY_VEC))/vec3(accum_total_energy);
+
+
+ {
+ uint aniso_pos = uint(clamp(iso_positive.b * 31.0,0.0,31.0));
+ aniso_pos |= uint(clamp(iso_positive.g * 63.0,0.0,63.0))<<5;
+ aniso_pos |= uint(clamp(iso_positive.r * 31.0,0.0,31.0))<<11;
+ imageStore(aniso_pos_tex,ivec3(posu),uvec4(aniso_pos));
+ }
+
+ {
+ uint aniso_neg = uint(clamp(iso_negative.b * 31.0,0.0,31.0));
+ aniso_neg |= uint(clamp(iso_negative.g * 63.0,0.0,63.0))<<5;
+ aniso_neg |= uint(clamp(iso_negative.r * 31.0,0.0,31.0))<<11;
+ imageStore(aniso_neg_tex,ivec3(posu),uvec4(aniso_neg));
+ }
+
+ imageStore(color_tex,ivec3(posu),vec4(accum_total / params.dynamic_range ,albedo.a));
+
+#else
+
+ imageStore(color_tex,ivec3(posu),vec4(outputs.data[cell_index].rgb / params.dynamic_range,albedo.a));
+
+#endif
+
+
+ }
+#endif
+}
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl
new file mode 100644
index 0000000000..deaeb771b9
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl
@@ -0,0 +1,160 @@
+[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+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=1,std140) buffer CellDataBuffer {
+ CellData data[];
+} cell_data;
+
+layout (set=0,binding=2) uniform texture3D color_tex;
+
+layout (set=0,binding=3) uniform sampler tex_sampler;
+
+#ifdef USE_ANISOTROPY
+layout (set=0,binding=4) uniform texture3D aniso_pos_tex;
+layout (set=0,binding=5) uniform texture3D aniso_neg_tex;
+#endif
+
+
+layout(push_constant, binding = 0, std430) uniform Params {
+
+ mat4 projection;
+ uint cell_offset;
+ float dynamic_range;
+ float alpha;
+ uint level;
+
+} params;
+
+layout(location=0) out vec4 color_interp;
+
+void main() {
+
+ const vec3 cube_triangles[36] = vec3[](
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(-1.0f,-1.0f, 1.0f),
+ vec3(-1.0f, 1.0f, 1.0f),
+ vec3(1.0f, 1.0f,-1.0f),
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(-1.0f, 1.0f,-1.0f),
+ vec3(1.0f,-1.0f, 1.0f),
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(1.0f,-1.0f,-1.0f),
+ vec3(1.0f, 1.0f,-1.0f),
+ vec3(1.0f,-1.0f,-1.0f),
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(-1.0f, 1.0f, 1.0f),
+ vec3(-1.0f, 1.0f,-1.0f),
+ vec3(1.0f,-1.0f, 1.0f),
+ vec3(-1.0f,-1.0f, 1.0f),
+ vec3(-1.0f,-1.0f,-1.0f),
+ vec3(-1.0f, 1.0f, 1.0f),
+ vec3(-1.0f,-1.0f, 1.0f),
+ vec3(1.0f,-1.0f, 1.0f),
+ vec3(1.0f, 1.0f, 1.0f),
+ vec3(1.0f,-1.0f,-1.0f),
+ vec3(1.0f, 1.0f,-1.0f),
+ vec3(1.0f,-1.0f,-1.0f),
+ vec3(1.0f, 1.0f, 1.0f),
+ vec3(1.0f,-1.0f, 1.0f),
+ vec3(1.0f, 1.0f, 1.0f),
+ vec3(1.0f, 1.0f,-1.0f),
+ vec3(-1.0f, 1.0f,-1.0f),
+ vec3(1.0f, 1.0f, 1.0f),
+ vec3(-1.0f, 1.0f,-1.0f),
+ vec3(-1.0f, 1.0f, 1.0f),
+ vec3(1.0f, 1.0f, 1.0f),
+ vec3(-1.0f, 1.0f, 1.0f),
+ vec3(1.0f,-1.0f, 1.0f)
+ );
+
+
+ vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5;
+
+ 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);
+
+#ifdef MODE_DEBUG_COLOR
+ color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz;
+#endif
+#ifdef MODE_DEBUG_LIGHT
+
+#ifdef USE_ANISOTROPY
+
+#define POS_X 0
+#define POS_Y 1
+#define POS_Z 2
+#define NEG_X 3
+#define NEG_Y 4
+#define NEG_Z 5
+
+ const uint triangle_aniso[12] = uint[](
+ NEG_X,
+ NEG_Z,
+ NEG_Y,
+ NEG_Z,
+ NEG_X,
+ NEG_Y,
+ POS_Z,
+ POS_X,
+ POS_X,
+ POS_Y,
+ POS_Y,
+ POS_Z
+ );
+
+ color_interp.xyz = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level)).xyz * params.dynamic_range;
+ vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex,tex_sampler),ivec3(posu),int(params.level)).xyz;
+ vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex,tex_sampler),ivec3(posu),int(params.level)).xyz;
+ uint side = triangle_aniso[gl_VertexIndex/3];
+
+ float strength = 0.0;
+ switch(side) {
+ case POS_X: strength = aniso_pos.x; break;
+ case POS_Y: strength = aniso_pos.y; break;
+ case POS_Z: strength = aniso_pos.z; break;
+ case NEG_X: strength = aniso_neg.x; break;
+ case NEG_Y: strength = aniso_neg.y; break;
+ case NEG_Z: strength = aniso_neg.z; break;
+
+ }
+
+ color_interp.xyz *= strength;
+
+#else
+ color_interp.xyz = texelFetch(sampler3D(color_tex,tex_sampler),ivec3(posu),int(params.level)).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);
+
+}
+
+[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location=0) in vec4 color_interp;
+layout(location=0) out vec4 frag_color;
+
+void main() {
+
+ frag_color = color_interp;
+}
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_lighting.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_lighting.glsl
deleted file mode 100644
index cec25f86f9..0000000000
--- a/servers/visual/rasterizer_rd/shaders/giprobe_lighting.glsl
+++ /dev/null
@@ -1,241 +0,0 @@
-[compute]
-
-#version 450
-
-VERSION_DEFINES
-
-layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-
-#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333,0.33333,0.33333)
-
-struct CellPosition {
- uint children[8];
-};
-
-
-layout(set=0,binding=1,std140) buffer CellPositions {
- CellPosition data[];
-} cell_positions;
-
-struct CellMaterial {
- 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,std140) buffer CellMaterials {
- CellMaterial data[];
-} cell_materials;
-
-#define LIGHT_TYPE_DIRECTIONAL 0
-#define LIGHT_TYPE_OMNI 1
-#define LIGHT_TYPE_SPOT 2
-
-struct Light {
-
- uint type;
- float energy;
- float radius;
- float attenuation;
-
- vec3 color;
- float spot_angle_radians;
-
- float advance;
- float max_length;
- uint pad0;
- uint pad2;
-
- vec3 position;
- float spot_attenuation;
-
-
- vec3 direction;
- bool visible;
-
- vec4 clip_planes[3];
-};
-
-layout(set=0,binding=3,std140) buffer Lights {
- Light data[];
-} lights;
-
-
-layout(set=0,binding=4,std140) uniform Params {
- vec3 limits;
- float max_length;
- uint size;
- uint stack_size;
- uint light_count;
- float emission_scale;
-} params;
-
-
-layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
-
-
-uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
-
- uint result = NO_CHILDREN;
-
- while (distance > -distance_adv) { //use this to avoid precision errors
-
- uint cell = 0;
-
- ivec3 pos = ivec3(from);
- ivec3 ofs = ivec3(0);
- ivec3 half_size = ivec3(params.size) / 2;
- if (any(lessThan(pos,ivec3(0))) || any(greaterThanEqual(pos,ivec3(params.size)))) {
- return NO_CHILDREN; //outside range
- }
-
- for (int i = 0; i < params.stack_size - 1; i++) {
-
- bvec3 greater = greaterThanEqual(pos,ofs+half_size);
-
- ofs += mix(ivec3(0),half_size,greater);
-
- 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;
- }
-
- cell = cell_positions.data[cell].children[child];
- if (cell == NO_CHILDREN)
- break;
-
- half_size >>= ivec3(1);
- }
-
- if ( cell != NO_CHILDREN) {
- return cell; //found cell!
- }
-
- from += direction * distance_adv;
- distance -= distance_adv;
- }
-
- return NO_CHILDREN;
-}
-
-bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
-
- if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
-
- light_pos = pos - lights.data[light].direction * params.max_length;
- attenuation = 1.0;
-
- } else {
-
- light_pos = lights.data[light].position;
- float distance = length(pos - light_pos);
- if (distance >= lights.data[light].radius) {
- return false;
- }
-
- attenuation = pow( distance / lights.data[light].radius + 0.0001, lights.data[light].attenuation );
-
-
- if (lights.data[light].type==LIGHT_TYPE_SPOT) {
-
- vec3 rel = normalize(pos - light_pos);
- float angle = acos(dot(rel,lights.data[light].direction));
- if (angle > lights.data[light].spot_angle_radians) {
- return false;
- }
-
- float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
- attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
- }
- }
-
- return true;
-}
-
-void main() {
-
- uint cell_index = gl_GlobalInvocationID.x;
-
- uvec3 posu = uvec3(cell_materials.data[cell_index].position&0x3FF,(cell_materials.data[cell_index].position>>10)&0x3FF,cell_materials.data[cell_index].position>>20);
- vec3 pos = vec3(posu);
-
- vec3 emission = vec3(ivec3(cell_materials.data[cell_index].emission&0x3FF,(cell_materials.data[cell_index].emission>>10)&0x7FF,cell_materials.data[cell_index].emission>>21)) * params.emission_scale;
- vec4 albedo = unpackUnorm4x8(cell_materials.data[cell_index].albedo);
- vec4 normal = unpackSnorm4x8(cell_materials.data[cell_index].normal); //w >0.5 means, all directions
-
-#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));
- const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
-#else
- vec3 accum = vec3(0);
-#endif
-
- 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)) {
- continue;
- }
-
- float distance_adv = lights.data[i].advance;
-
- vec3 light_dir = pos - light_pos;
- float distance = length(light_dir);
-
- light_dir=normalize(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
-
- if (normal.w < 0.5 && dot(normal.xyz,light_dir)>=0) {
- continue; //not facing the light
- }
-
- uint result = raymarch(distance,distance_adv,from,lights.data[i].direction);
-
- if (result != cell_index) {
- continue; //was occluded
- }
-
- vec3 light = lights.data[i].color * albedo.rgb * attenuation;
-
-#ifdef MODE_ANISOTROPIC
- for(uint j=0;j<6;j++) {
- accum[j]+=max(0.0,dot(accum_dir,-light_dir))*light+emission;
- }
-#else
- if (normal.w < 0.5) {
- accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
- } else {
- //all directions
- accum+=light+emission;
- }
-#endif
-
- }
-
-#ifdef MODE_ANISOTROPIC
-
- vec3 accum_total = accum[0]+accum[1]+accum[2]+accum[3]+accum[4]+accum[5];
- float accum_total_energy = max(dot(accum_total,GREY_VEC),0.00001);
- vec3 iso_positive = vec3(dot(aniso[0],GREY_VEC),dot(aniso[2],GREY_VEC),dot(aniso[4],GREY_VEC))/vec3(accum_total_energy);
- vec3 iso_negative = vec3(dot(aniso[1],GREY_VEC),dot(aniso[3],GREY_VEC),dot(aniso[5],GREY_VEC))/vec3(accum_total_energy);
-
- //store in 3D textures, total color, and isotropic magnitudes
-#else
- //store in 3D texture pos, accum
- imageStore(color_tex,ivec3(posu),vec4(accum,albedo.a));
-#endif
-
-}
diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl
new file mode 100644
index 0000000000..01d33c28de
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl
@@ -0,0 +1,353 @@
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+#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;
+
+#define LIGHT_TYPE_DIRECTIONAL 0
+#define LIGHT_TYPE_OMNI 1
+#define LIGHT_TYPE_SPOT 2
+
+#ifdef MODE_COMPUTE_LIGHT
+
+struct Light {
+
+ uint type;
+ float energy;
+ float radius;
+ float attenuation;
+
+ vec3 color;
+ float spot_angle_radians;
+
+ vec3 position;
+ float spot_attenuation;
+
+ vec3 direction;
+ bool has_shadow;
+};
+
+
+layout(set=0,binding=3,std140) uniform Lights {
+ Light data[MAX_LIGHTS];
+} lights;
+
+#endif
+
+layout(push_constant, binding = 0, std430) uniform Params {
+
+ ivec3 limits;
+ uint stack_size;
+
+ float emission_scale;
+ float propagation;
+ float dynamic_range;
+
+ uint light_count;
+ uint cell_offset;
+ uint cell_count;
+ uint pad[2];
+
+} params;
+
+
+layout(set=0,binding=4,std140) uniform Outputs {
+ vec4 data[];
+} output;
+
+
+
+#ifdef MODE_COMPUTE_LIGHT
+
+uint raymarch(float distance,float distance_adv,vec3 from,vec3 direction) {
+
+ uint result = NO_CHILDREN;
+
+ ivec3 size = ivec3(max(max(params.limits.x,params.limits.y),params.limits.z));
+
+ while (distance > -distance_adv) { //use this to avoid precision errors
+
+ uint cell = 0;
+
+ ivec3 pos = ivec3(from);
+
+ if (all(greaterThanEqual(pos,ivec3(0))) && all(lessThan(pos,size))) {
+
+ ivec3 ofs = ivec3(0);
+ ivec3 half_size = size / 2;
+
+ for (int i = 0; i < params.stack_size - 1; i++) {
+
+ bvec3 greater = greaterThanEqual(pos,ofs+half_size);
+
+ ofs += mix(ivec3(0),half_size,greater);
+
+ 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;
+ }
+
+ cell = cell_children.data[cell].children[child];
+ if (cell == NO_CHILDREN)
+ break;
+
+ half_size >>= ivec3(1);
+ }
+
+ if ( cell != NO_CHILDREN) {
+ return cell; //found cell!
+ }
+
+ }
+
+ from += direction * distance_adv;
+ distance -= distance_adv;
+ }
+
+ return NO_CHILDREN;
+}
+
+bool compute_light_vector(uint light,uint cell, vec3 pos,out float attenuation, out vec3 light_pos) {
+
+
+ if (lights.data[light].type==LIGHT_TYPE_DIRECTIONAL) {
+
+ light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
+ attenuation = 1.0;
+
+ } else {
+
+ light_pos = lights.data[light].position;
+ float distance = length(pos - light_pos);
+ if (distance >= lights.data[light].radius) {
+ return false;
+ }
+
+
+ attenuation = pow( clamp( 1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation );
+
+
+ if (lights.data[light].type==LIGHT_TYPE_SPOT) {
+
+ vec3 rel = normalize(pos - light_pos);
+ float angle = acos(dot(rel,lights.data[light].direction));
+ if (angle > lights.data[light].spot_angle_radians) {
+ return false;
+ }
+
+ float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
+ attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
+ }
+ }
+
+ return true;
+}
+
+float get_normal_advance(vec3 p_normal) {
+
+ vec3 normal = p_normal;
+ vec3 unorm = abs(normal);
+
+ if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+ } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+ } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3(1.0, 0.0, 0.0);
+ }
+
+ return 1.0 / dot(normal,unorm);
+}
+
+#endif
+
+
+
+
+void main() {
+
+ uint cell_index = gl_GlobalInvocationID.x;;
+ if (cell_index >= params.cell_count) {
+ return;
+ }
+ cell_index += 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);
+ vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
+
+#ifdef MODE_COMPUTE_LIGHT
+
+ vec3 pos = vec3(posu) + vec3(0.5);
+
+ vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission&0x3FF,(cell_data.data[cell_index].emission>>10)&0x7FF,cell_data.data[cell_index].emission>>21)) * params.emission_scale;
+ vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
+
+#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));
+ const vec3 accum_dirs[6]=vec3[](vec3(1.0,0.0,0.0),vec3(-1.0,0.0,0.0),vec3(0.0,1.0,0.0),vec3(0.0,-1.0,0.0),vec3(0.0,0.0,1.0),vec3(0.0,0.0,-1.0));
+#else
+ vec3 accum = vec3(0.0);
+#endif
+
+ 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)) {
+ continue;
+ }
+
+ vec3 light_dir = pos - light_pos;
+ float distance = length(light_dir);
+ light_dir=normalize(light_dir);
+
+ if (length(normal.xyz) > 0.2 && dot(normal.xyz,light_dir)>=0) {
+ continue; //not facing the light
+ }
+
+ 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;
+
+#ifdef MODE_ANISOTROPIC
+ for(uint j=0;j<6;j++) {
+ accum[j]+=max(0.0,dot(accum_dir,-light_dir))*light+emission;
+ }
+#else
+ if (length(normal.xyz) > 0.2) {
+ accum+=max(0.0,dot(normal.xyz,-light_dir))*light+emission;
+ } else {
+ //all directions
+ accum+=light+emission;
+ }
+#endif
+
+ }
+
+#ifdef MODE_ANISOTROPIC
+
+ output.data[cell_index*6+0]=vec4(accum[0],0.0);
+ output.data[cell_index*6+1]=vec4(accum[1],0.0);
+ output.data[cell_index*6+2]=vec4(accum[2],0.0);
+ output.data[cell_index*6+3]=vec4(accum[3],0.0);
+ output.data[cell_index*6+4]=vec4(accum[4],0.0);
+ output.data[cell_index*6+5]=vec4(accum[5],0.0);
+#else
+ output.data[cell_index]=vec4(accum,0.0);
+
+#endif
+
+#endif //MODE_COMPUTE_LIGHT
+
+
+#ifdef MODE_UPDATE_MIPMAPS
+
+ {
+#ifdef MODE_ANISOTROPIC
+ vec3 light_accum[6] = vec3[](vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));
+#else
+ vec3 light_accum = vec3(0.0);
+#endif
+ float count = 0.0;
+ for(uint i=0;i<8;i++) {
+ uint child_index = cell_children.data[cell_index].children[i];
+ if (child_index==NO_CHILDREN) {
+ continue;
+ }
+#ifdef MODE_ANISOTROPIC
+ light_accum[1] += output.data[child_index*6+0].rgb;
+ light_accum[2] += output.data[child_index*6+1].rgb;
+ light_accum[3] += output.data[child_index*6+2].rgb;
+ light_accum[4] += output.data[child_index*6+3].rgb;
+ light_accum[5] += output.data[child_index*6+4].rgb;
+ light_accum[6] += output.data[child_index*6+5].rgb;
+
+#else
+ light_accum += output.data[child_index].rgb;
+
+#endif
+
+ count+=1.0;
+ }
+
+ float divisor = mix(8.0,count,params.propagation);
+#ifdef MODE_ANISOTROPIC
+ output.data[cell_index*6+0]=vec4(light_accum[0] / divisor,0.0);
+ output.data[cell_index*6+1]=vec4(light_accum[1] / divisor,0.0);
+ output.data[cell_index*6+2]=vec4(light_accum[2] / divisor,0.0);
+ output.data[cell_index*6+3]=vec4(light_accum[3] / divisor,0.0);
+ output.data[cell_index*6+4]=vec4(light_accum[4] / divisor,0.0);
+ output.data[cell_index*6+5]=vec4(light_accum[5] / divisor,0.0);
+
+#else
+ output.data[cell_index]=vec4(light_accum / divisor,0.0);
+#endif
+
+
+
+ }
+#endif
+
+#ifdef MODE_WRITE_TEXTURE
+ {
+
+
+
+ }
+#endif
+}
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index 711da3be9b..95e64f8778 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -57,7 +57,7 @@ layout(location = 6) out vec3 binormal_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
+layout(set = 3, binding = 0, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -73,7 +73,7 @@ VERTEX_SHADER_GLOBALS
// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
-//invariant gl_Position;
+invariant gl_Position;
layout(location =7) flat out uint instance_index;
@@ -274,7 +274,7 @@ VERTEX_SHADER_CODE
#endif //MODE_RENDER_DEPTH
#ifdef USE_OVERRIDE_POSITION
- gl_Position = position;;
+ gl_Position = position;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
@@ -331,7 +331,7 @@ layout(location =8) in float dp_clip;
#define projection_matrix scene_data.projection_matrix;
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
+layout(set = 3, binding = 0, std140) uniform MaterialUniforms {
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -918,6 +918,265 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal,float roughness
#endif //USE_LIGHTMAP
}
+#ifdef USE_VOXEL_CONE_TRACING
+
+//standard voxel cone trace
+vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+
+ float dist = p_bias;
+ vec4 color = vec4(0.0);
+
+ while (dist < max_distance && color.a < 0.95) {
+ float diameter = max(1.0, 2.0 * tan_half_angle * dist);
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+ float half_diameter = diameter * 0.5;
+ //check if outside, then break
+ if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
+ break;
+ }
+ vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
+ float a = (1.0 - color.a);
+ color += a * scolor;
+ dist += half_diameter;
+
+ }
+
+ return color;
+}
+#if 0
+vec4 voxel_cone_trace_skiplod(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+
+ float dist = p_bias;
+ vec4 color = vec4(0.0);
+ float skip_lod = 1.0;
+
+ while (dist < max_distance && color.a < 0.95) {
+ float diameter = max(1.0, 2.0 * tan_half_angle * dist);
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+ float half_diameter = diameter * 0.5;
+ //check if outside, then break
+ if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
+ break;
+ }
+ vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
+ float a = (1.0 - color.a);
+ color += a * scolor;
+
+ float upper_opacity = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, skip_lod).a;
+ float skip_factor = exp2( max( 0.0f, skip_lod * 0.5f - 1.0f ) ) * (1.0f - upper_opacity) + upper_opacity;
+
+ skip_factor = mix( skip_factor, 1.0f, min( -1.0 + upper_opacity * probeParams.vctSpecularSdfFactor + tan_half_angle * 50.0f, 1.0f ) );
+ skip_lod = clamp( skip_lod + (1.0f - upper_opacity) * 2.0f - 1.0f, 1.0f, probeParams.vctSpecSdfMaxMip );
+
+ dist += half_diameter * skip_factor;
+ }
+
+ return color;
+}
+#endif
+
+#ifndef GI_PROBE_HIGH_QUALITY
+//faster version for 45 degrees
+
+#ifdef GI_PROBE_USE_ANISOTROPY
+
+vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+
+ float dist = p_bias;
+ vec4 color = vec4(0.0);
+ float radius = max(0.5, tan_half_angle * dist);
+ float lod_level = log2(radius*2.0);
+
+ while (dist < max_distance && color.a < 0.95) {
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+ //check if outside, then break
+ if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + radius * cell_size)) ) ) {
+ break;
+ }
+
+ vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
+ vec3 aniso_neg = textureLod(sampler3D(aniso_neg,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
+ vec3 aniso_pos = textureLod(sampler3D(aniso_pos,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb;
+
+ scolor.rgb*=dot(max(vec3(0.0),(normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-normal * aniso_neg)),vec3(1.0));
+ lod_level+=1.0;
+
+ float a = (1.0 - color.a);
+ color += a * scolor;
+ dist += radius;
+ radius = max(0.5, tan_half_angle * dist);
+
+
+ }
+
+ return color;
+}
+#else
+
+vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+
+ float dist = p_bias;
+ vec4 color = vec4(0.0);
+ float radius = max(0.5, tan_half_angle * dist);
+ float lod_level = log2(radius*2.0);
+
+ while (dist < max_distance && color.a < 0.95) {
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+
+ //check if outside, then break
+ if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + radius * cell_size)) ) ) {
+ break;
+ }
+ vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
+ lod_level+=1.0;
+
+ float a = (1.0 - color.a);
+ color += a * scolor;
+ dist += radius;
+ radius = max(0.5, tan_half_angle * dist);
+
+ }
+
+ return color;
+}
+
+#endif
+
+
+#elif defined(GI_PROBE_USE_ANISOTROPY)
+
+
+//standard voxel cone trace
+vec4 voxel_cone_trace_anisotropic(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+
+ float dist = p_bias;
+ vec4 color = vec4(0.0);
+
+ while (dist < max_distance && color.a < 0.95) {
+ float diameter = max(1.0, 2.0 * tan_half_angle * dist);
+ vec3 uvw_pos = (pos + dist * direction) * cell_size;
+ float half_diameter = diameter * 0.5;
+ //check if outside, then break
+ if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
+ break;
+ }
+ float log2_diameter = log2(diameter);
+ vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter);
+ vec3 aniso_neg = textureLod(sampler3D(aniso_neg,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
+ vec3 aniso_pos = textureLod(sampler3D(aniso_pos,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb;
+
+ scolor.rgb*=dot(max(vec3(0.0),(normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-normal * aniso_neg)),vec3(1.0));
+
+ float a = (1.0 - color.a);
+ color += a * scolor;
+ dist += half_diameter;
+
+ }
+
+ return color;
+}
+
+
+
+#endif
+
+void gi_probe_compute(uint index, vec3 position, vec3 normal,vec3 ref_vec, mat3 normal_xform, float roughness,vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
+
+
+
+ position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
+ ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
+ normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
+
+ position += normal * gi_probes.data[index].normal_bias;
+
+ //this causes corrupted pixels, i have no idea why..
+ if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
+ return;
+ }
+
+ vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
+ float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
+ //float blend=1.0;
+
+ float max_distance = length(gi_probes.data[index].bounds);
+ vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
+
+ //radiance
+#ifdef GI_PROBE_HIGH_QUALITY
+
+#define MAX_CONE_DIRS 6
+ vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
+ vec3(0.0, 0.0, 1.0),
+ vec3(0.866025, 0.0, 0.5),
+ vec3(0.267617, 0.823639, 0.5),
+ vec3(-0.700629, 0.509037, 0.5),
+ vec3(-0.700629, -0.509037, 0.5),
+ vec3(0.267617, -0.823639, 0.5));
+
+ float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
+ float cone_angle_tan = 0.577;
+#else
+
+#define MAX_CONE_DIRS 4
+
+ vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
+ vec3(0.707107, 0.0, 0.707107),
+ vec3(0.0, 0.707107, 0.707107),
+ vec3(-0.707107, 0.0, 0.707107),
+ vec3(0.0, -0.707107, 0.707107));
+
+ float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25);
+ float cone_angle_tan = 0.98269;
+
+#endif
+ vec3 light = vec3(0.0);
+ for (int i = 0; i < MAX_CONE_DIRS; i++) {
+
+
+ vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
+
+#ifdef GI_PROBE_HIGH_QUALITY
+
+#ifdef GI_PROBE_USE_ANISOTROPY
+ vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+#else
+ vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+#endif // GI_PROBE_USE_ANISOTROPY
+
+#else
+
+#ifdef GI_PROBE_USE_ANISOTROPY
+ vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+#else
+ vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+#endif // GI_PROBE_USE_ANISOTROPY
+
+#endif
+ if (gi_probes.data[index].blend_ambient) {
+ cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
+ }
+ light+=cone_weights[i] * cone_light.rgb;
+ }
+
+ light *= gi_probes.data[index].dynamic_range;
+
+ out_diff += vec4(light * blend, blend);
+
+ //irradiance
+
+ vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
+ if (gi_probes.data[index].blend_ambient) {
+ irr_light.rgb = mix(environment,irr_light.rgb, min(1.0, irr_light.a / 0.95));
+ }
+ irr_light.rgb *= gi_probes.data[index].dynamic_range;
+ //irr_light=vec3(0.0);
+
+ out_spec += vec4(irr_light.rgb * blend, blend);
+}
+
+#endif //USE_VOXEL_CONE_TRACING
+
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -1118,7 +1377,42 @@ FRAGMENT_SHADER_CODE
//lightmap capture
+#ifdef USE_VOXEL_CONE_TRACING
+ { // process giprobes
+ uint index1 = instances.data[instance_index].gi_offset&0xFFFF;
+ if (index1!=0xFFFF) {
+ vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
+ //find arbitrary tangent and bitangent, then build a matrix
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal));
+ vec3 bitangent = normalize(cross(tangent, normal));
+ mat3 normal_mat = mat3(tangent, bitangent, normal);
+
+ vec4 amb_accum = vec4(0.0);
+ vec4 spec_accum = vec4(0.0);
+
+ gi_probe_compute(index1, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
+
+ uint index2 = instances.data[instance_index].gi_offset>>16;
+
+ if (index2!=0xFFFF) {
+ gi_probe_compute(index2, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
+ }
+
+ if (amb_accum.a > 0.0) {
+ amb_accum.rgb /= amb_accum.a;
+ }
+
+ if (spec_accum.a > 0.0) {
+ spec_accum.rgb /= spec_accum.a;
+ }
+
+ specular_light = spec_accum.rgb;
+ ambient_light = amb_accum.rgb;
+ }
+ }
+#endif
{ // process reflections
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
index 81cf47b192..c59d5ed756 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -9,22 +9,7 @@ layout(push_constant, binding = 0, std430) uniform DrawCall {
-/* Set 0 Scene data, screen and sources (changes the least) */
-
-layout(set=0,binding=1) uniform texture2D depth_buffer;
-layout(set=0,binding=2) uniform texture2D color_buffer;
-layout(set=0,binding=3) uniform texture2D normal_buffer;
-layout(set=0,binding=4) uniform texture2D roughness_limit;
-
-#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-
-layout(set = 0, binding = 5) uniform textureCubeArray radiance_cubemap;
-
-#else
-
-layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
-
-#endif
+/* Set 0 Scene data that never changes, ever */
#define SAMPLER_NEAREST_CLAMP 0
@@ -40,11 +25,11 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
#define SAMPLER_NEAREST_WITH_MIMPAMPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
-layout(set = 0, binding = 6) uniform sampler material_samplers[12];
+layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 7) uniform sampler shadow_sampler;
+layout(set = 0, binding = 2) uniform sampler shadow_sampler;
-layout(set=0,binding=8,std140) uniform SceneData {
+layout(set=0,binding=3,std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
@@ -149,28 +134,10 @@ struct InstanceData {
};
-layout(set=0,binding=9,std430) buffer Instances {
+layout(set=0,binding=4,std430) buffer Instances {
InstanceData data[];
} instances;
-struct ReflectionData {
-
- vec3 box_extents;
- float index;
- vec3 box_offset;
- uint mask;
- vec4 params; // intensity, 0, interior , boxproject
- vec4 ambient; // ambient color, energy
- mat4 local_matrix; // up to here for spot and omni, rest is for directional
- // notes: for ambientblend, use distance to edge to blend between already existing global environment
-};
-
-layout(set=0,binding=10,std140) uniform ReflectionProbeData {
- ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
-} reflections;
-
-layout(set=0,binding=11) uniform textureCubeArray reflection_atlas;
-
struct LightData { //this structure needs to be 128 bits
vec3 position;
@@ -185,11 +152,25 @@ struct LightData { //this structure needs to be 128 bits
mat4 shadow_matrix;
};
-layout(set=0,binding=12,std140) uniform Lights {
+layout(set=0,binding=5,std140) uniform Lights {
LightData data[MAX_LIGHT_DATA_STRUCTS];
} lights;
-layout(set=0,binding=13) uniform texture2D shadow_atlas;
+struct ReflectionData {
+
+ vec3 box_extents;
+ float index;
+ vec3 box_offset;
+ uint mask;
+ vec4 params; // intensity, 0, interior , boxproject
+ vec4 ambient; // ambient color, energy
+ mat4 local_matrix; // up to here for spot and omni, rest is for directional
+ // notes: for ambientblend, use distance to edge to blend between already existing global environment
+};
+
+layout(set=0,binding=6,std140) uniform ReflectionProbeData {
+ ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
+} reflections;
struct DirectionalLightData {
@@ -211,51 +192,65 @@ struct DirectionalLightData {
};
-layout(set=0,binding=14,std140) uniform DirectionalLights {
+layout(set=0,binding=7,std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
} directional_lights;
-layout(set=0,binding=15) uniform texture2D directional_shadow_atlas;
+struct GIProbeData {
+ mat4 xform;
+ vec3 bounds;
+ float dynamic_range;
-/*
-layout(set=0,binding=15,std430) buffer Skeletons {
- vec4 data[];
-} skeletons;
-*/
+ float bias;
+ float normal_bias;
+ bool blend_ambient;
+ uint texture_slot;
-/* Set 1 Instancing (Multimesh) */
+ float anisotropy_strength;
+ uint pad0;
+ uint pad1;
+ uint pad2;
+};
-//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
+layout(set=0,binding=8,std140) uniform GIProbes {
+ GIProbeData data[MAX_GI_PROBES];
+} gi_probes;
-layout(set=1,binding=0,std430) buffer Transforms {
- vec4 data[];
-} transforms;
+layout(set=0,binding=9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
-/* Set 2 Instancing (Multimesh) data */
+/* Set 1, Scene data that changes per render pass */
-#if 0
+
+layout(set=1,binding=0) uniform texture2D depth_buffer;
+layout(set=1,binding=1) uniform texture2D color_buffer;
+layout(set=1,binding=2) uniform texture2D normal_buffer;
+layout(set=1,binding=3) uniform texture2D roughness_limit;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
+layout(set = 1, binding = 4) uniform textureCubeArray radiance_cubemap;
#else
-layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
+layout(set = 1, binding = 4) uniform textureCube radiance_cubemap;
#endif
-#ifdef USE_VOXEL_CONE_TRACING
+layout(set=1,binding=5) uniform textureCubeArray reflection_atlas;
-layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
+layout(set=1,binding=6) uniform texture2D shadow_atlas;
-#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
-layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_pos[2];
-layout(set = 3, binding = 6) uniform texture3D gi_probe_aniso_neg[2];
-#endif
+layout(set=1,binding=7) uniform texture2D directional_shadow_atlas;
+
+
+/* Set 2 Skeleton & Instancing (Multimesh) */
+
+layout(set=2,binding=0,std430) buffer Transforms {
+ vec4 data[];
+} transforms;
+
+/* Set 3 User Material */
-#endif
-#endif