diff options
Diffstat (limited to 'servers/rendering/renderer_rd/shaders')
40 files changed, 1009 insertions, 646 deletions
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index d352743908..5405985741 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -18,3 +18,5 @@ if "RD_GLSL" in env["BUILDERS"]:  SConscript("effects/SCsub")  SConscript("environment/SCsub") +SConscript("forward_clustered/SCsub") +SConscript("forward_mobile/SCsub") diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f8e9020f9f..eb5f68849e 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -191,48 +191,6 @@ void main() {  		uv += 1e-5;  	} -#ifdef USE_ATTRIBUTES -#if 0 -	if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone -		//skeleton transform -		ivec4 bone_indicesi = ivec4(bone_indices); - -		uvec2 tex_ofs = bone_indicesi.x * 2; - -		mat2x4 m; -		m = mat2x4( -					texelFetch(skeleton_buffer, tex_ofs + 0), -					texelFetch(skeleton_buffer, tex_ofs + 1)) * -			bone_weights.x; - -		tex_ofs = bone_indicesi.y * 2; - -		m += mat2x4( -					 texelFetch(skeleton_buffer, tex_ofs + 0), -					 texelFetch(skeleton_buffer, tex_ofs + 1)) * -			 bone_weights.y; - -		tex_ofs = bone_indicesi.z * 2; - -		m += mat2x4( -					 texelFetch(skeleton_buffer, tex_ofs + 0), -					 texelFetch(skeleton_buffer, tex_ofs + 1)) * -			 bone_weights.z; - -		tex_ofs = bone_indicesi.w * 2; - -		m += mat2x4( -					 texelFetch(skeleton_buffer, tex_ofs + 0), -					 texelFetch(skeleton_buffer, tex_ofs + 1)) * -			 bone_weights.w; - -		mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse; - -		//outvec = bone_matrix * outvec; -	} -#endif -#endif -  	vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;  	vertex_interp = vertex; @@ -313,6 +271,14 @@ vec4 light_compute(  		vec2 uv,  		vec4 color, bool is_directional) {  	vec4 light = vec4(0.0); +	vec3 light_direction = vec3(0.0); + +	if (is_directional) { +		light_direction = normalize(mix(vec3(light_position.xy, 0.0), vec3(0, 0, 1), light_position.z)); +		light_position = vec3(0.0); +	} else { +		light_direction = normalize(light_position - light_vertex); +	}  #CODE : LIGHT @@ -509,7 +475,13 @@ void main() {  			float a = clamp(d * px_size + 0.5, 0.0, 1.0);  			color.a = a * color.a;  		} - +	} else if (bool(draw_data.flags & FLAGS_USE_LCD)) { +		vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); +		if (lcd_sample.a == 1.0) { +			color.rgb = lcd_sample.rgb * color.a; +		} else { +			color = vec4(0.0, 0.0, 0.0, 0.0); +		}  	} else {  #else  	{ @@ -584,14 +556,14 @@ void main() {  		normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz);  	} -	vec3 base_color = color.rgb; +	vec4 base_color = color;  	if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {  		color = vec4(0.0); //invisible by default due to using light mask  	}  #ifdef MODE_LIGHT_ONLY  	color = vec4(0.0); -#else +#elif !defined(MODE_UNSHADED)  	color *= canvas_data.canvas_modulation;  #endif @@ -608,12 +580,14 @@ void main() {  #ifdef LIGHT_CODE_USED  		vec4 shadow_modulate = vec4(1.0); -		light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, true); +		light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, true);  #else  		if (normal_used) {  			vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array.data[light_base].height)); -			light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used); +			light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used); +		} else { +			light_color.rgb *= base_color.rgb;  		}  #endif @@ -639,20 +613,7 @@ void main() {  		if (i >= light_count) {  			break;  		} -		uint light_base; -		if (i < 8) { -			if (i < 4) { -				light_base = draw_data.lights[0]; -			} else { -				light_base = draw_data.lights[1]; -			} -		} else { -			if (i < 12) { -				light_base = draw_data.lights[2]; -			} else { -				light_base = draw_data.lights[3]; -			} -		} +		uint light_base = draw_data.lights[i >> 2];  		light_base >>= (i & 3) * 8;  		light_base &= 0xFF; @@ -667,7 +628,7 @@ void main() {  		vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);  		light_color.rgb *= light_base_color.rgb; -		light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, false); +		light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, false);  #else  		light_color.rgb *= light_base_color.rgb * light_base_color.a; @@ -676,9 +637,10 @@ void main() {  			vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);  			vec3 pos = light_vertex;  			vec3 light_vec = normalize(light_pos - pos); -			float cNdotL = max(0.0, dot(normal, light_vec)); -			light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used); +			light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used); +		} else { +			light_color.rgb *= base_color.rgb;  		}  #endif  		if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 12f57b0178..1b627a3e81 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@  #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)  #define FLAGS_USE_MSDF (1 << 28) +#define FLAGS_USE_LCD (1 << 29)  #define SAMPLER_NEAREST_CLAMP 0  #define SAMPLER_LINEAR_CLAMP 1 @@ -138,10 +139,10 @@ layout(set = 0, binding = 7) uniform texture2D sdf_texture;  layout(set = 0, binding = 8) uniform sampler material_samplers[12]; -layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalShaderUniformData {  	vec4 data[];  } -global_variables; +global_shader_uniforms;  /* SET1: Is reserved for the material */ diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index 2fe230f0bf..8c26a67926 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -64,7 +64,7 @@ void main() {  #version 450  #VERSION_DEFINES - +#ifndef MOLTENVK_USED // Metal will corrupt GPU state otherwise  #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) && defined(has_GL_KHR_shader_subgroup_vote)  #extension GL_KHR_shader_subgroup_ballot : enable @@ -73,6 +73,7 @@ void main() {  #define USE_SUBGROUPS  #endif +#endif  layout(location = 0) in float depth_interp;  layout(location = 1) in flat uint element_index; @@ -141,7 +142,11 @@ void main() {  		}  	}  #else -	if (!gl_HelperInvocation) { +// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs +#ifndef MOLTENVK_USED +	if (!gl_HelperInvocation) +#endif +	{  		atomicOr(cluster_render.data[usage_write_offset], usage_write_bit);  	}  #endif @@ -161,7 +166,11 @@ void main() {  		}  	}  #else -	if (!gl_HelperInvocation) { +// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs +#ifndef MOLTENVK_USED +	if (!gl_HelperInvocation) +#endif +	{  		atomicOr(cluster_render.data[z_write_offset], z_write_bit);  	}  #endif diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub index 741da8fe69..f06a2d86e2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/SCsub @@ -4,7 +4,7 @@ Import("env")  if "RD_GLSL" in env["BUILDERS"]:      # find all include files -    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] +    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]      # find all shader code(all glsl files excluding our include files)      glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl index 96f5c3e9f2..31aabbe9d2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl @@ -53,30 +53,31 @@ void main() {  #ifdef MODE_GAUSSIAN_BLUR -	// Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect - -	// note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount. - -	if (bool(blur.flags & FLAG_HORIZONTAL)) { -		vec2 pix_size = blur.pixel_size; -		pix_size *= 0.5; //reading from larger buffer, so use more samples -		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; -		color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; -		color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; -		color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; -		color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; -		color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; -		color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; -		frag_color = color; -	} else { -		vec2 pix_size = blur.pixel_size; -		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; -		color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; -		color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; -		color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; -		color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; -		frag_color = color; -	} +	// For Gaussian Blur we use 13 taps in a single pass instead of 12 taps over 2 passes. +	// This minimizes the number of times we change framebuffers which is very important for mobile. +	// Source: http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +	vec4 A = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, -1.0)); +	vec4 B = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, -1.0)); +	vec4 C = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, -1.0)); +	vec4 D = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, -0.5)); +	vec4 E = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, -0.5)); +	vec4 F = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 0.0)); +	vec4 G = texture(source_color, uv_interp); +	vec4 H = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 0.0)); +	vec4 I = texture(source_color, uv_interp + blur.pixel_size * vec2(-0.5, 0.5)); +	vec4 J = texture(source_color, uv_interp + blur.pixel_size * vec2(0.5, 0.5)); +	vec4 K = texture(source_color, uv_interp + blur.pixel_size * vec2(-1.0, 1.0)); +	vec4 L = texture(source_color, uv_interp + blur.pixel_size * vec2(0.0, 1.0)); +	vec4 M = texture(source_color, uv_interp + blur.pixel_size * vec2(1.0, 1.0)); + +	float base_weight = 0.5 / 4.0; +	float lesser_weight = 0.125 / 4.0; + +	frag_color = (D + E + I + J) * base_weight; +	frag_color += (A + B + G + F) * lesser_weight; +	frag_color += (B + C + H + G) * lesser_weight; +	frag_color += (F + G + L + K) * lesser_weight; +	frag_color += (G + H + M + L) * lesser_weight;  #endif  #ifdef MODE_GAUSSIAN_GLOW @@ -129,7 +130,7 @@ void main() {  #ifdef GLOW_USE_AUTO_EXPOSURE -		frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; +		frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_scale;  #endif  		frag_color *= blur.glow_exposure; diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl index 730504571a..06ca198f37 100644 --- a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl @@ -16,7 +16,7 @@ layout(push_constant, std430) uniform Blur {  	float glow_exposure; // 04 - 36  	float glow_white; // 04 - 40  	float glow_luminance_cap; // 04 - 44 -	float glow_auto_exposure_grey; // 04 - 48 +	float glow_auto_exposure_scale; // 04 - 48  	float luminance_multiplier; // 04 - 52  	float res1; // 04 - 56 diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index 0438671dd2..fe770ac065 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl @@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;  #ifdef MODE_GEN_BLUR_SIZE  float get_depth_at_pos(vec2 uv) { -	float depth = textureLod(source_depth, uv, 0.0).x; +	float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;  	if (params.orthogonal) {  		depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;  	} else { @@ -41,11 +41,25 @@ float get_depth_at_pos(vec2 uv) {  float get_blur_size(float depth) {  	if (params.blur_near_active && depth < params.blur_near_begin) { -		return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative +		if (params.use_physical_near) { +			// Physically-based. +			float d = abs(params.blur_near_begin - depth); +			return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative. +		} else { +			// Non-physically-based. +			return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative. +		}  	}  	if (params.blur_far_active && depth > params.blur_far_begin) { -		return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; +		if (params.use_physical_far) { +			// Physically-based. +			float d = abs(params.blur_far_begin - depth); +			return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP; +		} else { +			// Non-physically-based. +			return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; +		}  	}  	return 0.0; @@ -172,6 +186,7 @@ void main() {  	uv += pixel_size * 0.5; //half pixel to read centers  	vec4 color = texture(color_texture, uv); +	float initial_blur = color.a;  	float accum = 1.0;  	float radius = params.blur_scale; @@ -179,8 +194,8 @@ void main() {  		vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;  		vec4 sample_color = texture(color_texture, suv);  		float sample_size = abs(sample_color.a); -		if (sample_color.a > color.a) { -			sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0); +		if (sample_color.a > initial_blur) { +			sample_size = clamp(sample_size, 0.0, abs(initial_blur) * 2.0);  		}  		float m = smoothstep(radius - 0.5, radius + 0.5, sample_size); diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl index b90a527554..4a2b0edc18 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl @@ -20,6 +20,11 @@ layout(push_constant, std430) uniform Params {  	bool use_jitter;  	float jitter_seed; +	bool use_physical_near; +	bool use_physical_far; + +	float blur_size_near; +	float blur_size_far;  	uint pad[2];  }  params; diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a3b3938ee9..1b487835d2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl @@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;  #ifdef MODE_GEN_BLUR_SIZE  float get_depth_at_pos(vec2 uv) { -	float depth = textureLod(source_depth, uv, 0.0).x; +	float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;  	if (params.orthogonal) {  		depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;  	} else { @@ -63,11 +63,25 @@ float get_depth_at_pos(vec2 uv) {  float get_blur_size(float depth) {  	if (params.blur_near_active && depth < params.blur_near_begin) { -		return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative +		if (params.use_physical_near) { +			// Physically-based. +			float d = abs(params.blur_near_begin - depth); +			return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative. +		} else { +			// Non-physically-based. +			return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative. +		}  	}  	if (params.blur_far_active && depth > params.blur_far_begin) { -		return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; +		if (params.use_physical_far) { +			// Physically-based. +			float d = abs(params.blur_far_begin - depth); +			return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP; +		} else { +			// Non-physically-based. +			return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; +		}  	}  	return 0.0; @@ -207,12 +221,9 @@ void main() {  		vec4 sample_color = texture(source_color, uv_adj);  		sample_color.a = texture(source_weight, uv_adj).r; -		float limit; - -		if (sample_color.a < color.a) { -			limit = abs(sample_color.a); -		} else { -			limit = abs(color.a); +		float limit = abs(sample_color.a); +		if (sample_color.a > color.a) { +			limit = clamp(limit, 0.0, abs(color.a) * 2.0);  		}  		limit -= DEPTH_GAP; diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index 3a4ef86ef0..5cc2ed7622 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -31,7 +31,7 @@ layout(push_constant, std430) uniform Params {  	float glow_exposure;  	float glow_white;  	float glow_luminance_cap; -	float glow_auto_exposure_grey; +	float glow_auto_exposure_scale;  	// DOF.  	float camera_z_far;  	float camera_z_near; @@ -185,7 +185,7 @@ void main() {  	if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {  #ifdef GLOW_USE_AUTO_EXPOSURE -		color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey; +		color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_scale;  #endif  		color *= params.glow_exposure; @@ -194,10 +194,10 @@ void main() {  		color = min(color * feedback, vec4(params.glow_luminance_cap));  	} -#endif +#endif // MODE_GLOW  	imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_GAUSSIAN_BLUR  #ifdef MODE_SIMPLE_COPY @@ -227,7 +227,7 @@ void main() {  	imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_SIMPLE_COPY  #ifdef MODE_SIMPLE_COPY_DEPTH @@ -239,7 +239,7 @@ void main() {  	imageStore(dest_buffer, pos + params.target, vec4(color.r)); -#endif +#endif // MODE_SIMPLE_COPY_DEPTH  #ifdef MODE_LINEARIZE_DEPTH_COPY @@ -253,7 +253,7 @@ void main() {  	}  	imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // MODE_LINEARIZE_DEPTH_COPY  #if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA) @@ -276,7 +276,7 @@ void main() {  	vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne  #endif  	imageStore(dest_buffer, pos + params.target, color); -#endif +#endif // defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)  #ifdef MODE_SET_COLOR  	imageStore(dest_buffer, pos + params.target, params.set_color); diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 1c17eabb56..46bb99794d 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -13,6 +13,14 @@  #endif // has_VK_KHR_multiview  #endif //MULTIVIEW +#define FLAG_FLIP_Y (1 << 0) +#define FLAG_USE_SECTION (1 << 1) +#define FLAG_FORCE_LUMINANCE (1 << 2) +#define FLAG_ALPHA_TO_ZERO (1 << 3) +#define FLAG_SRGB (1 << 4) +#define FLAG_ALPHA_TO_ONE (1 << 5) +#define FLAG_LINEAR (1 << 6) +  #ifdef MULTIVIEW  layout(location = 0) out vec3 uv_interp;  #else @@ -22,11 +30,10 @@ layout(location = 0) out vec2 uv_interp;  layout(push_constant, std430) uniform Params {  	vec4 section;  	vec2 pixel_size; -	bool flip_y; -	bool use_section; +	float luminance_multiplier; +	uint flags; -	bool force_luminance; -	uint pad[3]; +	vec4 color;  }  params; @@ -37,13 +44,13 @@ void main() {  	uv_interp.z = ViewIndex;  #endif  	vec2 vpos = uv_interp.xy; -	if (params.use_section) { +	if (bool(params.flags & FLAG_USE_SECTION)) {  		vpos = params.section.xy + vpos * params.section.zw;  	}  	gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0); -	if (params.flip_y) { +	if (bool(params.flags & FLAG_FLIP_Y)) {  		uv_interp.y = 1.0 - uv_interp.y;  	}  } @@ -63,16 +70,21 @@ void main() {  #endif // has_VK_KHR_multiview  #endif //MULTIVIEW +#define FLAG_FLIP_Y (1 << 0) +#define FLAG_USE_SECTION (1 << 1) +#define FLAG_FORCE_LUMINANCE (1 << 2) +#define FLAG_ALPHA_TO_ZERO (1 << 3) +#define FLAG_SRGB (1 << 4) +#define FLAG_ALPHA_TO_ONE (1 << 5) +#define FLAG_LINEAR (1 << 6) +  layout(push_constant, std430) uniform Params {  	vec4 section;  	vec2 pixel_size; -	bool flip_y; -	bool use_section; +	float luminance_multiplier; +	uint flags; -	bool force_luminance; -	bool alpha_to_zero; -	bool srgb; -	uint pad; +	vec4 color;  }  params; @@ -104,7 +116,15 @@ vec3 linear_to_srgb(vec3 color) {  	return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));  } +vec3 srgb_to_linear(vec3 color) { +	return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045))); +} +  void main() { +#ifdef MODE_SET_COLOR +	frag_color = params.color; +#else +  #ifdef MULTIVIEW  	vec3 uv = uv_interp;  #else @@ -155,15 +175,22 @@ void main() {  #endif /* MODE_TWO_SOURCES */  #endif /* MULTIVIEW */ -	if (params.force_luminance) { +	if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {  		color.rgb = vec3(max(max(color.r, color.g), color.b));  	} -	if (params.alpha_to_zero) { +	if (bool(params.flags & FLAG_ALPHA_TO_ZERO)) {  		color.rgb *= color.a;  	} -	if (params.srgb) { +	if (bool(params.flags & FLAG_SRGB)) {  		color.rgb = linear_to_srgb(color.rgb);  	} +	if (bool(params.flags & FLAG_ALPHA_TO_ONE)) { +		color.a = 1.0; +	} +	if (bool(params.flags & FLAG_LINEAR)) { +		color.rgb = srgb_to_linear(color.rgb); +	} -	frag_color = color; +	frag_color = color / params.luminance_multiplier; +#endif // MODE_SET_COLOR  } diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl index c8eb78a2f0..c8eb78a2f0 100644 --- a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index d85ab3af2e..9d8294a7da 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -30,12 +30,7 @@ layout(push_constant, std430) uniform Params {  	bool orthogonal;  	float filter_mipmap_levels;  	bool use_half_res; -	uint metallic_mask; -  	uint view_index; -	uint pad1; -	uint pad2; -	uint pad3;  }  params; @@ -126,7 +121,7 @@ void main() {  	// clip z and w advance to line advance  	vec2 line_advance = normalize(line_dir); // down to pixel -	float step_size = length(line_advance) / length(line_dir); +	float step_size = 1.0 / length(line_dir);  	float z_advance = z_dir * step_size; // adapt z advance to line advance  	float w_advance = w_dir * step_size; // adapt w advance to line advance @@ -144,6 +139,14 @@ void main() {  	float depth;  	vec2 prev_pos = pos; +	if (ivec2(pos + line_advance - 0.5) == ssC) { +		// It is possible for rounding to cause our first pixel to check to be the pixel we're reflecting. +		// Make sure we skip it +		pos += line_advance; +		z += z_advance; +		w += w_advance; +	} +  	bool found = false;  	float steps_taken = 0.0; @@ -154,8 +157,8 @@ void main() {  		w += w_advance;  		// convert to linear depth - -		depth = imageLoad(source_depth, ivec2(pos - 0.5)).r; +		ivec2 test_pos = ivec2(pos - 0.5); +		depth = imageLoad(source_depth, test_pos).r;  		if (sc_multiview) {  			depth = depth * 2.0 - 1.0;  			depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near)); @@ -166,13 +169,21 @@ void main() {  		z_to = z / w;  		if (depth > z_to) { -			// if depth was surpassed -			if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far) { -				// check the depth tolerance and far clip -				// check that normal is valid -				found = true; +			// Test if our ray is hitting the "right" side of the surface, if not we're likely self reflecting and should skip. +			vec4 test_normal_roughness = imageLoad(source_normal_roughness, test_pos); +			vec3 test_normal = test_normal_roughness.xyz * 2.0 - 1.0; +			test_normal = normalize(test_normal); +			test_normal.y = -test_normal.y; //because this code reads flipped + +			if (dot(ray_dir, test_normal) < 0.001) { +				// if depth was surpassed +				if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far * 0.95) { +					// check the depth tolerance and far clip +					// check that normal is valid +					found = true; +				} +				break;  			} -			break;  		}  		steps_taken += 1.0; @@ -182,17 +193,18 @@ void main() {  	if (found) {  		float margin_blend = 1.0; -		vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin -		if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) { -			// clip outside screen + margin +		vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin +		if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) { +			// clip at the screen edges  			imageStore(ssr_image, ssC, vec4(0.0));  			return;  		}  		{ -			//blend fading out towards external margin -			vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0))); -			margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y)); +			//blend fading out towards inner margin +			// 0.5 = midpoint of reflection +			vec2 margin_grad = mix(params.screen_size - pos, pos, lessThan(pos, params.screen_size * 0.5)); +			margin_blend = smoothstep(0.0, margin.x * margin.y, margin_grad.x * margin_grad.y);  			//margin_blend = 1.0;  		} @@ -230,18 +242,20 @@ void main() {  			}  		} -		// Isn't this going to be overwritten after our endif? -		final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size)); -  		imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8  #endif // MODE_ROUGH  		final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); -		//change blend by metallic -		vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask); -		final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0)); +		// Schlick term. +		float metallic = texelFetch(source_metallic, ssC << 1, 0).w; +		float f0 = mix(0.04, 1.0, metallic); // Assume a "specular" amount of 0.5 +		normal.y = -normal.y; +		float m = clamp(1.0 - dot(normalize(normal), -view_dir), 0.0, 1.0); +		float m2 = m * m; +		m = m2 * m2 * m; // pow(m,5) +		final_color.a *= f0 + (1.0 - f0) * m; // Fresnel Schlick term.  		imageStore(ssr_image, ssC, final_color); diff --git a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl index fb35d3cde6..fb35d3cde6 100644 --- a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl index b0a0839836..02566d8e35 100644 --- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl @@ -32,7 +32,9 @@  // Based on Spartan Engine's TAA implementation (without TAA upscale).  // <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl> +#ifndef MOLTENVK_USED  #define USE_SUBGROUPS +#endif // MOLTENVK_USED  #define GROUP_SIZE 8  #define FLT_MIN 0.00000001 diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl index 62a7b0e7d7..52aee8b648 100644 --- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl @@ -75,7 +75,7 @@ layout(push_constant, std430) uniform Params {  	float exposure;  	float white; -	float auto_exposure_grey; +	float auto_exposure_scale;  	float luminance_multiplier;  	vec2 pixel_size; @@ -360,15 +360,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {  	const float FXAA_SPAN_MAX = 8.0;  #ifdef MULTIVIEW -	vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, 0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(0.5, 0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;  #else -	vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; -	vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-0.5, -0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbNE = textureLod(source_color, uv_interp + vec2(0.5, -0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-0.5, 0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier; +	vec3 rgbSE = textureLod(source_color, uv_interp + vec2(0.5, 0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;  #endif  	vec3 rgbM = color;  	vec3 luma = vec3(0.299, 0.587, 0.114); @@ -440,7 +440,7 @@ void main() {  #ifndef SUBPASS  	if (params.use_auto_exposure) { -		exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey); +		exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);  	}  #endif @@ -462,12 +462,6 @@ void main() {  	}  #endif -	if (params.use_debanding) { -		// For best results, debanding should be done before tonemapping. -		// Otherwise, we're adding noise to an already-quantized image. -		color.rgb += screen_space_dither(gl_FragCoord.xy); -	} -  	color.rgb = apply_tonemapping(color.rgb, params.white);  	color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion @@ -498,5 +492,11 @@ void main() {  		color.rgb = apply_color_correction(color.rgb);  	} +	if (params.use_debanding) { +		// Debanding should be done at the end of tonemapping, but before writing to the LDR buffer. +		// Otherwise, we're adding noise to an already-quantized image. +		color.rgb += screen_space_dither(gl_FragCoord.xy); +	} +  	frag_color = color;  } diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl index 5ef83c0b44..b450bb9fe9 100644 --- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -63,10 +63,18 @@ void main() {  #ifdef MULTIVIEW  	vec4 color = textureLod(source_color, uv, 0.0); +	frag_color = uint(color.r * 255.0);  #else /* MULTIVIEW */  	vec4 color = textureLod(source_color, uv, 0.0); -#endif /* MULTIVIEW */ -	// See if we can change the sampler to one that returns int... -	frag_color = uint(color.r * 256.0); +	// for user supplied VRS map we do a color mapping +	color.r *= 3.0; +	frag_color = int(color.r) << 2; + +	color.g *= 3.0; +	frag_color += int(color.g); + +	// note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported +	// 4x8, 8x4 and 8x8 are only available on some GPUs +#endif /* MULTIVIEW */  } diff --git a/servers/rendering/renderer_rd/shaders/environment/SCsub b/servers/rendering/renderer_rd/shaders/environment/SCsub index 741da8fe69..f06a2d86e2 100644 --- a/servers/rendering/renderer_rd/shaders/environment/SCsub +++ b/servers/rendering/renderer_rd/shaders/environment/SCsub @@ -4,7 +4,7 @@ Import("env")  if "RD_GLSL" in env["BUILDERS"]:      # find all include files -    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] +    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]      # find all shader code(all glsl files excluding our include files)      glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index 6ea8cb1377..ab927df678 100644 --- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -32,6 +32,8 @@ struct ProbeCascadeData {  	float to_probe;  	ivec3 probe_world_offset;  	float to_cell; // 1/bounds * grid_size +	vec3 pad; +	float exposure_normalization;  };  layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer; @@ -83,6 +85,9 @@ struct VoxelGIData {  	float normal_bias; // 4 - 88  	bool blend_ambient; // 4 - 92  	uint mipmaps; // 4 - 96 + +	vec3 pad; // 12 - 108 +	float exposure_normalization; // 4 - 112  };  layout(set = 0, binding = 16, std140) uniform VoxelGIs { @@ -241,7 +246,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_  		pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;  		diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb; -		diffuse_accum += vec4(diffuse * weight, weight); +		diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);  		{  			vec3 specular = vec3(0.0); @@ -255,7 +260,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_  				specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25);  			} -			specular_accum += specular * weight; +			specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;  		}  	} @@ -574,7 +579,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3  		}  	} -	light.rgb *= voxel_gi_instances.data[index].dynamic_range; +	light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;  	if (!voxel_gi_instances.data[index].blend_ambient) {  		light.a = 1.0;  	} @@ -583,7 +588,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3  	//radiance  	vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias); -	irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range; +	irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;  	if (!voxel_gi_instances.data[index].blend_ambient) {  		irr_light.a = 1.0;  	} diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl index af5f7d0a58..177dab16c7 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl @@ -21,6 +21,7 @@ struct CascadeData {  	float to_cell; // 1/bounds * grid_size  	ivec3 probe_world_offset;  	uint pad; +	vec4 pad2;  };  layout(set = 0, binding = 9, std140) uniform Cascades { @@ -37,16 +38,14 @@ layout(push_constant, std430) uniform Params {  	uint max_cascades;  	ivec2 screen_size; -	bool use_occlusion;  	float y_mult; -	int probe_axis_size;  	float z_near; -	float reserved1; -	float reserved2; -	mat4 cam_transform; -	mat4 inv_projection; +	mat3x4 inv_projection; +	// We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery. +	float cam_basis[3][3]; +	float cam_origin[3];  }  params; @@ -82,13 +81,21 @@ void main() {  	vec3 ray_pos;  	vec3 ray_dir;  	{ -		ray_pos = params.cam_transform[3].xyz; +		ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]);  		ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);  		ray_dir.z = params.z_near; -		ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz; -		ray_dir = normalize(mat3(params.cam_transform) * ray_dir); +		ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz; + +		mat3 cam_basis; +		{ +			vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]); +			vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]); +			vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]); +			cam_basis = mat3(c0, c1, c2); +		} +		ray_dir = normalize(cam_basis * ray_dir);  	}  	ray_pos.y *= params.y_mult; diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl index 75b1ad2130..a0ef169f03 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl @@ -73,6 +73,7 @@ struct CascadeData {  	float to_cell; // 1/bounds * grid_size  	ivec3 probe_world_offset;  	uint pad; +	vec4 pad2;  };  layout(set = 0, binding = 1, std140) uniform Cascades { diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl index b95fad650e..9f7449b8aa 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl @@ -45,6 +45,7 @@ struct CascadeData {  	float to_cell; // 1/bounds * grid_size  	ivec3 probe_world_offset;  	uint pad; +	vec4 pad2;  };  layout(set = 0, binding = 8, std140) uniform Cascades { diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl index 9c03297f5c..4bdb0dcc72 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl @@ -20,6 +20,7 @@ struct CascadeData {  	float to_cell; // 1/bounds * grid_size  	ivec3 probe_world_offset;  	uint pad; +	vec4 pad2;  };  layout(set = 0, binding = 7, std140) uniform Cascades { diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 5b4594da99..d523461600 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -15,10 +15,10 @@ layout(location = 0) out vec2 uv_interp;  layout(push_constant, std430) uniform Params {  	mat3 orientation;  	vec4 projections[MAX_VIEWS]; -	vec4 position_multiplier; +	vec3 position;  	float time; +	vec3 pad;  	float luminance_multiplier; -	float pad[2];  }  params; @@ -55,10 +55,10 @@ layout(location = 0) in vec2 uv_interp;  layout(push_constant, std430) uniform Params {  	mat3 orientation;  	vec4 projections[MAX_VIEWS]; -	vec4 position_multiplier; +	vec3 position;  	float time; +	vec3 pad;  	float luminance_multiplier; -	float pad[2];  }  params; @@ -77,26 +77,29 @@ params;  layout(set = 0, binding = 0) uniform sampler material_samplers[12]; -layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUniformData {  	vec4 data[];  } -global_variables; +global_shader_uniforms;  layout(set = 0, binding = 2, std140) uniform SceneData { -	bool volumetric_fog_enabled; -	float volumetric_fog_inv_length; -	float volumetric_fog_detail_spread; - -	float fog_aerial_perspective; - -	vec3 fog_light_color; -	float fog_sun_scatter; - -	bool fog_enabled; -	float fog_density; - -	float z_far; -	uint directional_light_count; +	bool volumetric_fog_enabled; // 4 - 4 +	float volumetric_fog_inv_length; // 4 - 8 +	float volumetric_fog_detail_spread; // 4 - 12 +	float volumetric_fog_sky_affect; // 4 - 16 + +	bool fog_enabled; // 4 - 20 +	float fog_sky_affect; // 4 - 24 +	float fog_density; // 4 - 28 +	float fog_sun_scatter; // 4 - 32 + +	vec3 fog_light_color; // 12 - 44 +	float fog_aerial_perspective; // 4 - 48 + +	float z_far; // 4 - 52 +	uint directional_light_count; // 4 - 56 +	uint pad1; // 4 - 60 +	uint pad2; // 4 - 64  }  scene_data; @@ -150,6 +153,15 @@ layout(set = 3, binding = 0) uniform texture3D volumetric_fog_texture;  layout(location = 0) out vec4 frag_color; +#ifdef USE_DEBANDING +// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +vec3 interleaved_gradient_noise(vec2 pos) { +	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); +	float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; +	return vec3(res, -res, res) / 255.0; +} +#endif +  vec4 volumetric_fog_process(vec2 screen_uv) {  	vec3 fog_pos = vec3(screen_uv, 1.0); @@ -169,9 +181,7 @@ vec4 fog_process(vec3 view, vec3 sky_color) {  		}  	} -	float fog_amount = clamp(1.0 - exp(-scene_data.z_far * scene_data.fog_density), 0.0, 1.0); - -	return vec4(fog_color, fog_amount); +	return vec4(fog_color, 1.0);  }  void main() { @@ -200,17 +210,17 @@ void main() {  #ifdef USE_CUBEMAP_PASS  #ifdef USES_HALF_RES_COLOR -	half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier; +	half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;  #endif  #ifdef USES_QUARTER_RES_COLOR -	quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier; +	quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;  #endif  #else  #ifdef USES_HALF_RES_COLOR -	half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier; +	half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;  #endif  #ifdef USES_QUARTER_RES_COLOR -	quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier; +	quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;  #endif  #endif @@ -220,7 +230,7 @@ void main() {  	} -	frag_color.rgb = color * params.position_multiplier.w; +	frag_color.rgb = color;  	frag_color.a = alpha;  #if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) @@ -228,12 +238,12 @@ void main() {  	// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.  	if (scene_data.fog_enabled) {  		vec4 fog = fog_process(cube_normal, frag_color.rgb); -		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); +		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.fog_sky_affect);  	}  	if (scene_data.volumetric_fog_enabled) {  		vec4 fog = volumetric_fog_process(uv); -		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); +		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.volumetric_fog_sky_affect);  	}  	if (custom_fog.a > 0.0) { @@ -242,12 +252,17 @@ void main() {  #endif // DISABLE_FOG -	// Blending is disabled for Sky, so alpha doesn't blend -	// alpha is used for subsurface scattering so make sure it doesn't get applied to Sky +	// Blending is disabled for Sky, so alpha doesn't blend. +	// Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky.  	if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {  		frag_color.a = 0.0;  	} -	// For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer -	frag_color.rgb = frag_color.rgb / params.luminance_multiplier; +	// For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. +	// For both mobile and clustered, we also bake in the exposure value for the environment and camera. +	frag_color.rgb = frag_color.rgb * params.luminance_multiplier; + +#ifdef USE_DEBANDING +	frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy); +#endif  } diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index fb3c725b1f..4658afd02d 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -28,10 +28,10 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;  layout(set = 0, binding = 1) uniform sampler material_samplers[12]; -layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {  	vec4 data[];  } -global_variables; +global_shader_uniforms;  layout(push_constant, std430) uniform Params {  	vec3 position; diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index e74cfad65c..28507e6c12 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -84,6 +84,9 @@ struct VoxelGIData {  	float normal_bias; // 4 - 88  	bool blend_ambient; // 4 - 92  	uint mipmaps; // 4 - 96 + +	vec3 pad; // 12 - 108 +	float exposure_normalization; // 4 - 112  };  layout(set = 0, binding = 11, std140) uniform VoxelGIs { @@ -105,6 +108,8 @@ struct SDFVoxelGICascadeData {  	float to_probe;  	ivec3 probe_world_offset;  	float to_cell; // 1/bounds * grid_size +	vec3 pad; +	float exposure_normalization;  };  layout(set = 1, binding = 0, std140) uniform SDFGI { @@ -270,6 +275,9 @@ const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](  		vec3(0.9375, 0.25925926, 0.12),  		vec3(0.03125, 0.59259259, 0.32)); +// Higher values will make light in volumetric fog fade out sooner when it's occluded by shadow. +const float INV_FOG_FADE = 10.0; +  void main() {  	vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size); @@ -373,48 +381,50 @@ void main() {  	float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));  	//compute directional lights -	if (total_density > 0.001) { +	if (total_density > 0.00005) {  		for (uint i = 0; i < params.directional_light_count; i++) { -			vec3 shadow_attenuation = vec3(1.0); - -			if (directional_lights.data[i].shadow_enabled) { -				float depth_z = -view_pos.z; - -				vec4 pssm_coord; -				vec3 light_dir = directional_lights.data[i].direction; -				vec4 v = vec4(view_pos, 1.0); -				float z_range; - -				if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { -					pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); -					pssm_coord /= pssm_coord.w; -					z_range = directional_lights.data[i].shadow_z_range.x; - -				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { -					pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); -					pssm_coord /= pssm_coord.w; -					z_range = directional_lights.data[i].shadow_z_range.y; - -				} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { -					pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); -					pssm_coord /= pssm_coord.w; -					z_range = directional_lights.data[i].shadow_z_range.z; - -				} else { -					pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); -					pssm_coord /= pssm_coord.w; -					z_range = directional_lights.data[i].shadow_z_range.w; -				} +			if (directional_lights.data[i].volumetric_fog_energy > 0.001) { +				vec3 shadow_attenuation = vec3(1.0); + +				if (directional_lights.data[i].shadow_opacity > 0.001) { +					float depth_z = -view_pos.z; + +					vec4 pssm_coord; +					vec3 light_dir = directional_lights.data[i].direction; +					vec4 v = vec4(view_pos, 1.0); +					float z_range; + +					if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { +						pssm_coord = (directional_lights.data[i].shadow_matrix1 * v); +						pssm_coord /= pssm_coord.w; +						z_range = directional_lights.data[i].shadow_z_range.x; + +					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { +						pssm_coord = (directional_lights.data[i].shadow_matrix2 * v); +						pssm_coord /= pssm_coord.w; +						z_range = directional_lights.data[i].shadow_z_range.y; + +					} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { +						pssm_coord = (directional_lights.data[i].shadow_matrix3 * v); +						pssm_coord /= pssm_coord.w; +						z_range = directional_lights.data[i].shadow_z_range.z; + +					} else { +						pssm_coord = (directional_lights.data[i].shadow_matrix4 * v); +						pssm_coord /= pssm_coord.w; +						z_range = directional_lights.data[i].shadow_z_range.w; +					} -				float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r; -				float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade); +					float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r; +					float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * INV_FOG_FADE); -				shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance +					shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance -				shadow_attenuation = mix(vec3(0.0), vec3(1.0), shadow); -			} +					shadow_attenuation = mix(vec3(1.0 - directional_lights.data[i].shadow_opacity), vec3(1.0), shadow); +				} -			total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g); +				total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g) * directional_lights.data[i].volumetric_fog_energy; +			}  		}  		// Compute light from sky @@ -481,12 +491,12 @@ void main() {  					float d = distance(omni_lights.data[light_index].position, view_pos);  					float shadow_attenuation = 1.0; -					if (d * omni_lights.data[light_index].inv_radius < 1.0) { +					if (omni_lights.data[light_index].volumetric_fog_energy > 0.001 && d * omni_lights.data[light_index].inv_radius < 1.0) {  						float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);  						vec3 light = omni_lights.data[light_index].color; -						if (omni_lights.data[light_index].shadow_enabled) { +						if (omni_lights.data[light_index].shadow_opacity > 0.001) {  							//has shadow  							vec4 uv_rect = omni_lights.data[light_index].atlas_rect;  							vec2 flip_offset = omni_lights.data[light_index].direction.xy; @@ -509,9 +519,9 @@ void main() {  							float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r; -							shadow_attenuation = exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade); +							shadow_attenuation = mix(1.0 - omni_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * INV_FOG_FADE));  						} -						total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g); +						total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g) * omni_lights.data[light_index].volumetric_fog_energy;  					}  				}  			} @@ -562,7 +572,7 @@ void main() {  					float d = length(light_rel_vec);  					float shadow_attenuation = 1.0; -					if (d * spot_lights.data[light_index].inv_radius < 1.0) { +					if (spot_lights.data[light_index].volumetric_fog_energy > 0.001 && d * spot_lights.data[light_index].inv_radius < 1.0) {  						float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);  						vec3 spot_dir = spot_lights.data[light_index].direction; @@ -572,7 +582,7 @@ void main() {  						vec3 light = spot_lights.data[light_index].color; -						if (spot_lights.data[light_index].shadow_enabled) { +						if (spot_lights.data[light_index].shadow_opacity > 0.001) {  							//has shadow  							vec4 uv_rect = spot_lights.data[light_index].atlas_rect;  							vec2 flip_offset = spot_lights.data[light_index].direction.xy; @@ -595,9 +605,9 @@ void main() {  							float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r; -							shadow_attenuation = exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade); +							shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));  						} -						total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g); +						total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;  					}  				}  			} @@ -619,7 +629,7 @@ void main() {  					light += a * slight;  				} -				light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject; +				light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject * voxel_gi_instances.data[i].exposure_normalization;  				total_light += light.rgb;  			} @@ -686,7 +696,7 @@ void main() {  					vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb; -					ambient_accum.rgb += ambient * weight; +					ambient_accum.rgb += ambient * weight * sdfgi.cascades[i].exposure_normalization;  					ambient_accum.a += weight;  				} diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub new file mode 100644 index 0000000000..f06a2d86e2 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: +    # find all include files +    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")] + +    # find all shader code(all glsl files excluding our include files) +    glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + +    # make sure we recompile shaders if include files change +    env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + +    # compile shaders +    for glsl_file in glsl_files: +        env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 5947fc5351..896f51ca01 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib;  //only for pure render depth when normal is not used  #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib;  #endif  #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib;  #endif  #if defined(COLOR_USED) @@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib;  layout(location = 11) in vec4 weight_attrib;  #endif +vec3 oct_to_vec3(vec2 e) { +	vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); +	float t = max(-v.z, 0.0); +	v.xy += t * -sign(v.xy); +	return normalize(v); +} +  /* Varyings */  layout(location = 0) out vec3 vertex_interp; @@ -90,9 +97,7 @@ layout(location = 8) out vec4 prev_screen_position;  #ifdef MATERIAL_UNIFORMS_USED  layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ -  #MATERIAL_UNIFORMS -  } material;  #endif @@ -122,12 +127,52 @@ invariant gl_Position;  #GLOBALS -void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { +#ifdef USE_DOUBLE_PRECISION +// Helper functions for emulating double precision when adding floats. +vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) { +	vec3 s = a + b; +	out_p = b - (s - a); +	return s; +} + +vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) { +	vec3 s = a + b; +	vec3 v = s - a; +	out_p = (a - (s - v)) + (b - v); +	return s; +} + +vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) { +	vec3 s, t, se, te; +	s = two_sum(base_a, base_b, se); +	t = two_sum(prec_a, prec_b, te); +	se += t; +	s = quick_two_sum(s, se, se); +	se += te; +	s = quick_two_sum(s, se, out_precision); +	return s; +} +#endif + +void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {  	vec4 instance_custom = vec4(0.0);  #if defined(COLOR_USED)  	color_interp = color_attrib;  #endif +	mat4 inv_view_matrix = scene_data.inv_view_matrix; + +#ifdef USE_DOUBLE_PRECISION +	vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); +	model_matrix[0][3] = 0.0; +	model_matrix[1][3] = 0.0; +	model_matrix[2][3] = 0.0; +	vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]); +	inv_view_matrix[0][3] = 0.0; +	inv_view_matrix[1][3] = 0.0; +	inv_view_matrix[2][3] = 0.0; +#endif +  	mat3 model_normal_matrix;  	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {  		model_normal_matrix = transpose(inverse(mat3(model_matrix))); @@ -135,11 +180,12 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  		model_normal_matrix = mat3(model_matrix);  	} +	mat4 matrix; +	mat4 read_model_matrix = model_matrix; +  	if (is_multimesh) {  		//multimesh, instances are for it -		mat4 matrix; -  #ifdef USE_PARTICLE_TRAILS  		uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;  		uint stride = 3 + 1 + 1; //particles always uses this format @@ -201,7 +247,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  			}  		} -		uint offset = stride * gl_InstanceIndex; +		uint offset = stride * (gl_InstanceIndex + multimesh_offset);  		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {  			matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); @@ -225,18 +271,26 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  #endif  		//transpose  		matrix = transpose(matrix); -		model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) +		// Normally we can bake the multimesh transform into the model matrix, but when using double precision +		// we avoid baking it in so we can emulate high precision. +		read_model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +		model_matrix = read_model_matrix; +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)  		model_normal_matrix = model_normal_matrix * mat3(matrix);  	}  	vec3 vertex = vertex_attrib;  #ifdef NORMAL_USED -	vec3 normal = normal_attrib * 2.0 - 1.0; +	vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);  #endif  #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -	vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; -	float binormalf = tangent_attrib.a * 2.0 - 1.0; +	vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; +	vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); +	float binormalf = sign(signed_tangent_attrib.y);  	vec3 binormal = normalize(cross(normal, tangent) * binormalf);  #endif @@ -289,7 +343,22 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  // using local coordinates (default)  #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) +#ifdef USE_DOUBLE_PRECISION +	// We separate the basis from the origin because the basis is fine with single point precision. +	// Then we combine the translations from the model matrix and the view matrix using emulated doubles. +	// We add the result to the vertex and ignore the final lost precision. +	vec3 model_origin = model_matrix[3].xyz; +	if (is_multimesh) { +		vertex = mat3(matrix) * vertex; +		model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); +	} +	vertex = mat3(model_matrix) * vertex; +	vec3 temp_precision; // Will be ignored. +	vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision); +	vertex = mat3(scene_data.view_matrix) * vertex; +#else  	vertex = (modelview * vec4(vertex, 1.0)).xyz; +#endif  #ifdef NORMAL_USED  	normal = modelview_normal * normal;  #endif @@ -318,10 +387,6 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  	vertex_interp = vertex; -#ifdef MOTION_VECTORS -	screen_pos = projection_matrix * vec4(vertex_interp, 1.0); -#endif -  #ifdef NORMAL_USED  	normal_interp = normal;  #endif @@ -359,6 +424,10 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc  	gl_Position = projection_matrix * vec4(vertex_interp, 1.0);  #endif +#ifdef MOTION_VECTORS +	screen_pos = gl_Position; +#endif +  #ifdef MODE_RENDER_DEPTH  	if (scene_data.pancake_shadows) {  		if (gl_Position.z <= 0.00001) { @@ -389,13 +458,13 @@ void main() {  	mat4 model_matrix = instances.data[instance_index].transform;  #if defined(MOTION_VECTORS)  	global_time = scene_data_block.prev_data.time; -	vertex_shader(instance_index, is_multimesh, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); +	vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);  	global_time = scene_data_block.data.time; -	vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position); +	vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);  #else  	global_time = scene_data_block.data.time;  	vec4 screen_position; -	vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position); +	vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);  #endif  } @@ -482,7 +551,6 @@ layout(location = 10) in flat uint instance_index_interp;  //defines to keep compatibility with vertex -#define model_matrix instances.data[draw_call.instance_index].transform  #ifdef USE_MULTIVIEW  #define projection_matrix scene_data.projection_matrix_view[ViewIndex]  #define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex] @@ -545,7 +613,7 @@ layout(location = 0) out vec4 frag_color;  layout(location = 2) out vec2 motion_vector;  #endif -#include "scene_forward_aa_inc.glsl" +#include "../scene_forward_aa_inc.glsl"  #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -554,20 +622,20 @@ layout(location = 2) out vec2 motion_vector;  #define SPECULAR_SCHLICK_GGX  #endif -#include "scene_forward_lights_inc.glsl" +#include "../scene_forward_lights_inc.glsl" -#include "scene_forward_gi_inc.glsl" +#include "../scene_forward_gi_inc.glsl"  #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)  #ifndef MODE_RENDER_DEPTH  vec4 volumetric_fog_process(vec2 screen_uv, float z) { -	vec3 fog_pos = vec3(screen_uv, z * scene_data_block.data.volumetric_fog_inv_length); +	vec3 fog_pos = vec3(screen_uv, z * implementation_data.volumetric_fog_inv_length);  	if (fog_pos.z < 0.0) {  		return vec4(0.0);  	} else if (fog_pos.z < 1.0) { -		fog_pos.z = pow(fog_pos.z, scene_data_block.data.volumetric_fog_detail_spread); +		fog_pos.z = pow(fog_pos.z, implementation_data.volumetric_fog_detail_spread);  	}  	return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); @@ -621,7 +689,7 @@ vec4 fog_process(vec3 vertex) {  void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {  	uint item_min_max = cluster_buffer.data[p_offset]; -	item_min = item_min_max & 0xFFFF; +	item_min = item_min_max & 0xFFFFu;  	item_max = item_min_max >> 16;  	item_from = item_min >> 5; @@ -729,6 +797,17 @@ void fragment_shader(in SceneData scene_data) {  	vec2 alpha_texture_coordinate = vec2(0.0, 0.0);  #endif // ALPHA_ANTIALIASING_EDGE_USED +	mat4 inv_view_matrix = scene_data.inv_view_matrix; +	mat4 read_model_matrix = instances.data[instance_index].transform; +#ifdef USE_DOUBLE_PRECISION +	read_model_matrix[0][3] = 0.0; +	read_model_matrix[1][3] = 0.0; +	read_model_matrix[2][3] = 0.0; +	inv_view_matrix[0][3] = 0.0; +	inv_view_matrix[1][3] = 0.0; +	inv_view_matrix[2][3] = 0.0; +#endif +  	{  #CODE : FRAGMENT  	} @@ -747,7 +826,8 @@ void fragment_shader(in SceneData scene_data) {  // alpha hash can be used in unison with alpha antialiasing  #ifdef ALPHA_HASH_USED -	if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { +	vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; +	if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {  		discard;  	}  #endif // ALPHA_HASH_USED @@ -813,7 +893,7 @@ void fragment_shader(in SceneData scene_data) {  		fog = fog_process(vertex);  	} -	if (scene_data.volumetric_fog_enabled) { +	if (implementation_data.volumetric_fog_enabled) {  		vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z);  		if (scene_data.fog_enabled) {  			//must use the full blending equation here to blend fogs @@ -841,8 +921,8 @@ void fragment_shader(in SceneData scene_data) {  #ifndef MODE_RENDER_DEPTH -	uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> scene_data.cluster_shift; -	uint cluster_offset = (scene_data.cluster_width * cluster_pos.y + cluster_pos.x) * (scene_data.max_cluster_element_count_div_32 + 32); +	uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> implementation_data.cluster_shift; +	uint cluster_offset = (implementation_data.cluster_width * cluster_pos.y + cluster_pos.x) * (implementation_data.max_cluster_element_count_div_32 + 32);  	uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0)); @@ -852,14 +932,14 @@ void fragment_shader(in SceneData scene_data) {  	{ // process decals -		uint cluster_decal_offset = cluster_offset + scene_data.cluster_type_size * 2; +		uint cluster_decal_offset = cluster_offset + implementation_data.cluster_type_size * 2;  		uint item_min;  		uint item_max;  		uint item_from;  		uint item_to; -		cluster_get_item_range(cluster_decal_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); +		cluster_get_item_range(cluster_decal_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);  #ifdef USE_SUBGROUPS  		item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -877,9 +957,9 @@ void fragment_shader(in SceneData scene_data) {  			while (merged_mask != 0) {  				uint bit = findMSB(merged_mask); -				merged_mask &= ~(1 << bit); +				merged_mask &= ~(1u << bit);  #ifdef USE_SUBGROUPS -				if (((1 << bit) & mask) == 0) { //do not process if not originally here +				if (((1u << bit) & mask) == 0) { //do not process if not originally here  					continue;  				}  #endif @@ -947,9 +1027,9 @@ void fragment_shader(in SceneData scene_data) {  				if (decals.data[decal_index].emission_rect != vec4(0.0)) {  					//emission is additive, so its independent from albedo  					if (sc_decal_use_mipmaps) { -						emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; +						emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;  					} else { -						emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; +						emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;  					}  				}  			} @@ -978,6 +1058,11 @@ void fragment_shader(in SceneData scene_data) {  	vec3 diffuse_light = vec3(0.0, 0.0, 0.0);  	vec3 ambient_light = vec3(0.0, 0.0, 0.0); +#ifndef MODE_UNSHADED +	// Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI. +	emission *= scene_data.emissive_exposure_normalization; +#endif +  #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)  	if (scene_data.use_reflection_cubemap) { @@ -988,8 +1073,10 @@ void fragment_shader(in SceneData scene_data) {  		vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);  		vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));  		vec3 ref_vec = reflect(-view, bent_normal); +		ref_vec = mix(ref_vec, bent_normal, roughness * roughness);  #else  		vec3 ref_vec = reflect(-view, normal); +		ref_vec = mix(ref_vec, normal, roughness * roughness);  #endif  		float horizon = min(1.0 + dot(ref_vec, normal), 1.0); @@ -1005,6 +1092,7 @@ void fragment_shader(in SceneData scene_data) {  		specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;  #endif //USE_RADIANCE_CUBEMAP_ARRAY +		specular_light *= scene_data.IBL_exposure_normalization;  		specular_light *= horizon * horizon;  		specular_light *= scene_data.ambient_light_color_energy.a;  	} @@ -1025,7 +1113,7 @@ void fragment_shader(in SceneData scene_data) {  #else  			vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;  #endif //USE_RADIANCE_CUBEMAP_ARRAY - +			cubemap_ambient *= scene_data.IBL_exposure_normalization;  			ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);  		}  	} @@ -1046,6 +1134,7 @@ void fragment_shader(in SceneData scene_data) {  		ambient_light *= attenuation;  		specular_light *= attenuation; +		ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);  		float horizon = min(1.0 + dot(ref_vec, normal), 1.0);  		ref_vec = scene_data.radiance_inverse_xform * ref_vec;  		float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; @@ -1083,15 +1172,16 @@ void fragment_shader(in SceneData scene_data) {  		const float c4 = 0.886227;  		const float c5 = 0.247708;  		ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) + -				c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z + -				c4 * lightmap_captures.data[index].sh[0].rgb - -				c5 * lightmap_captures.data[index].sh[6].rgb + -				2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y + -				2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z + -				2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z + -				2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x + -				2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + -				2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); +								 c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z + +								 c4 * lightmap_captures.data[index].sh[0].rgb - +								 c5 * lightmap_captures.data[index].sh[6].rgb + +								 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y + +								 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z + +								 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z + +								 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x + +								 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + +								 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) * +				scene_data.emissive_exposure_normalization;  	} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap  		bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); @@ -1109,20 +1199,22 @@ void fragment_shader(in SceneData scene_data) {  			uint idx = instances.data[instance_index].gi_offset >> 20;  			vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); +			float en = lightmaps.data[idx].exposure_normalization; -			ambient_light += lm_light_l0 * 0.282095f; -			ambient_light += lm_light_l1n1 * 0.32573 * n.y; -			ambient_light += lm_light_l1_0 * 0.32573 * n.z; -			ambient_light += lm_light_l1p1 * 0.32573 * n.x; +			ambient_light += lm_light_l0 * 0.282095f * en; +			ambient_light += lm_light_l1n1 * 0.32573 * n.y * en; +			ambient_light += lm_light_l1_0 * 0.32573 * n.z * en; +			ambient_light += lm_light_l1p1 * 0.32573 * n.x * en;  			if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick  				vec3 r = reflect(normalize(-vertex), normal); -				specular_light += lm_light_l1n1 * 0.32573 * r.y; -				specular_light += lm_light_l1_0 * 0.32573 * r.z; -				specular_light += lm_light_l1p1 * 0.32573 * r.x; +				specular_light += lm_light_l1n1 * 0.32573 * r.y * en; +				specular_light += lm_light_l1_0 * 0.32573 * r.z * en; +				specular_light += lm_light_l1p1 * 0.32573 * r.x * en;  			}  		} else { -			ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb; +			uint idx = instances.data[instance_index].gi_offset >> 20; +			ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;  		}  	}  #else @@ -1203,6 +1295,7 @@ void fragment_shader(in SceneData scene_data) {  		uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;  		vec3 ref_vec = normalize(reflect(-view, normal)); +		ref_vec = mix(ref_vec, normal, roughness * roughness);  		//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)); @@ -1235,7 +1328,7 @@ void fragment_shader(in SceneData scene_data) {  		vec2 coord; -		if (scene_data.gi_upscale_for_msaa) { +		if (implementation_data.gi_upscale_for_msaa) {  			vec2 base_coord = screen_uv;  			vec2 closest_coord = base_coord;  #ifdef USE_MULTIVIEW @@ -1277,10 +1370,10 @@ void fragment_shader(in SceneData scene_data) {  	}  #endif // !USE_LIGHTMAP -	if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) { +	if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) {  		float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;  		ao = min(ao, ssao); -		ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect); +		ao_light_affect = mix(ao_light_affect, max(ao_light_affect, implementation_data.ssao_light_affect), implementation_data.ssao_ao_affect);  	}  	{ // process reflections @@ -1288,20 +1381,32 @@ void fragment_shader(in SceneData scene_data) {  		vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);  		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); -		uint cluster_reflection_offset = cluster_offset + scene_data.cluster_type_size * 3; +		uint cluster_reflection_offset = cluster_offset + implementation_data.cluster_type_size * 3;  		uint item_min;  		uint item_max;  		uint item_from;  		uint item_to; -		cluster_get_item_range(cluster_reflection_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); +		cluster_get_item_range(cluster_reflection_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);  #ifdef USE_SUBGROUPS  		item_from = subgroupBroadcastFirst(subgroupMin(item_from));  		item_to = subgroupBroadcastFirst(subgroupMax(item_to));  #endif +#ifdef LIGHT_ANISOTROPY_USED +		// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy +		vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; +		vec3 anisotropic_tangent = cross(anisotropic_direction, view); +		vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); +		vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else +		vec3 bent_normal = normal; +#endif +		vec3 ref_vec = normalize(reflect(-view, bent_normal)); +		ref_vec = mix(ref_vec, bent_normal, roughness * roughness); +  		for (uint i = item_from; i < item_to; i++) {  			uint mask = cluster_buffer.data[cluster_reflection_offset + i];  			mask &= cluster_get_range_clip_mask(i, item_min, item_max); @@ -1313,9 +1418,9 @@ void fragment_shader(in SceneData scene_data) {  			while (merged_mask != 0) {  				uint bit = findMSB(merged_mask); -				merged_mask &= ~(1 << bit); +				merged_mask &= ~(1u << bit);  #ifdef USE_SUBGROUPS -				if (((1 << bit) & mask) == 0) { //do not process if not originally here +				if (((1u << bit) & mask) == 0) { //do not process if not originally here  					continue;  				}  #endif @@ -1324,16 +1429,8 @@ void fragment_shader(in SceneData scene_data) {  				if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) {  					continue; //not masked  				} -#ifdef LIGHT_ANISOTROPY_USED -				// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy -				vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; -				vec3 anisotropic_tangent = cross(anisotropic_direction, view); -				vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); -				vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); -#else -				vec3 bent_normal = normal; -#endif -				reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + +				reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);  			}  		} @@ -1349,18 +1446,24 @@ void fragment_shader(in SceneData scene_data) {  	}  	//finalize ambient light here -	ambient_light *= albedo.rgb; -	ambient_light *= ao; +	{ +#if defined(AMBIENT_LIGHT_DISABLED) +		ambient_light = vec3(0.0, 0.0, 0.0); +#else +		ambient_light *= albedo.rgb; +		ambient_light *= ao; + +		if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) { +			vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0); +			ambient_light *= 1.0 - ssil.a; +			ambient_light += ssil.rgb * albedo.rgb; +		} +#endif // AMBIENT_LIGHT_DISABLED +	}  	// convert ao to direct light ao  	ao = mix(1.0, ao, ao_light_affect); -	if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) { -		vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0); -		ambient_light *= 1.0 - ssil.a; -		ambient_light += ssil.rgb * albedo.rgb; -	} -  	//this saves some VGPRs  	vec3 f0 = F0(metallic, specular, albedo); @@ -1381,7 +1484,7 @@ void fragment_shader(in SceneData scene_data) {  		float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;  		vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; -		specular_light *= env.x * f0 + env.y; +		specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0);  #endif  	} @@ -1417,7 +1520,7 @@ void fragment_shader(in SceneData scene_data) {  			float shadow = 1.0; -			if (directional_lights.data[i].shadow_enabled) { +			if (directional_lights.data[i].shadow_opacity > 0.001) {  				float depth_z = -vertex.z;  				vec3 light_dir = directional_lights.data[i].direction;  				vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); @@ -1626,7 +1729,7 @@ void fragment_shader(in SceneData scene_data) {  #ifdef LIGHT_TRANSMITTANCE_USED  			float transmittance_z = transmittance_depth; -			if (directional_lights.data[i].shadow_enabled) { +			if (directional_lights.data[i].shadow_opacity > 0.001) {  				float depth_z = -vertex.z;  				if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { @@ -1677,10 +1780,12 @@ void fragment_shader(in SceneData scene_data) {  			float shadow = 1.0;  #ifndef SHADOWS_DISABLED  			if (i < 4) { -				shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0; +				shadow = float(shadow0 >> (i * 8u) & 0xFFu) / 255.0;  			} else { -				shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0; +				shadow = float(shadow1 >> ((i - 4u) * 8u) & 0xFFu) / 255.0;  			} + +			shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;  #endif  			blur_shadow(shadow); @@ -1721,7 +1826,7 @@ void fragment_shader(in SceneData scene_data) {  		uint item_from;  		uint item_to; -		cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); +		cluster_get_item_range(cluster_omni_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);  #ifdef USE_SUBGROUPS  		item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1739,9 +1844,9 @@ void fragment_shader(in SceneData scene_data) {  			while (merged_mask != 0) {  				uint bit = findMSB(merged_mask); -				merged_mask &= ~(1 << bit); +				merged_mask &= ~(1u << bit);  #ifdef USE_SUBGROUPS -				if (((1 << bit) & mask) == 0) { //do not process if not originally here +				if (((1u << bit) & mask) == 0) { //do not process if not originally here  					continue;  				}  #endif @@ -1785,14 +1890,14 @@ void fragment_shader(in SceneData scene_data) {  	{ //spot lights -		uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size; +		uint cluster_spot_offset = cluster_offset + implementation_data.cluster_type_size;  		uint item_min;  		uint item_max;  		uint item_from;  		uint item_to; -		cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); +		cluster_get_item_range(cluster_spot_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);  #ifdef USE_SUBGROUPS  		item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1810,9 +1915,9 @@ void fragment_shader(in SceneData scene_data) {  			while (merged_mask != 0) {  				uint bit = findMSB(merged_mask); -				merged_mask &= ~(1 << bit); +				merged_mask &= ~(1u << bit);  #ifdef USE_SUBGROUPS -				if (((1 << bit) & mask) == 0) { //do not process if not originally here +				if (((1u << bit) & mask) == 0) { //do not process if not originally here  					continue;  				}  #endif @@ -1882,8 +1987,8 @@ void fragment_shader(in SceneData scene_data) {  #ifdef MODE_RENDER_SDF  	{ -		vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz; -		ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size)); +		vec3 local_pos = (implementation_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz; +		ivec3 grid_pos = implementation_data.sdf_offset + ivec3(local_pos * vec3(implementation_data.sdf_size));  		uint albedo16 = 0x1; //solid flag  		albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11; @@ -1965,7 +2070,7 @@ void fragment_shader(in SceneData scene_data) {  			float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);  			float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);  			//store as 8985 to have 2 extra neighbour bits -			uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25); +			uint light_rgbe = ((uint(sRed) & 0x1FFu) >> 1) | ((uint(sGreen) & 0x1FFu) << 8) | (((uint(sBlue) & 0x1FFu) >> 1) << 17) | ((uint(exps) & 0x1Fu) << 25);  			imageStore(emission_grid, grid_pos, uvec4(light_rgbe));  			imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso)); @@ -1999,8 +2104,8 @@ void fragment_shader(in SceneData scene_data) {  	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances  		uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;  		uint index2 = instances.data[instance_index].gi_offset >> 16; -		voxel_gi_buffer.x = index1 & 0xFF; -		voxel_gi_buffer.y = index2 & 0xFF; +		voxel_gi_buffer.x = index1 & 0xFFu; +		voxel_gi_buffer.y = index2 & 0xFFu;  	} else {  		voxel_gi_buffer.x = 0xFF;  		voxel_gi_buffer.y = 0xFF; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 0c23de96c3..3a45ab0059 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -4,21 +4,23 @@  #define MAX_VOXEL_GI_INSTANCES 8  #define MAX_VIEWS 2 +#ifndef MOLTENVK_USED  #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)  #extension GL_KHR_shader_subgroup_ballot : enable  #extension GL_KHR_shader_subgroup_arithmetic : enable  #define USE_SUBGROUPS -  #endif +#endif // MOLTENVK_USED  #if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)  #extension GL_EXT_multiview : enable  #endif -#include "cluster_data_inc.glsl" -#include "decal_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../decal_data_inc.glsl" +#include "../scene_data_inc.glsl"  #if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)  #ifndef NORMAL_USED @@ -29,8 +31,8 @@  layout(push_constant, std430) uniform DrawCall {  	uint instance_index;  	uint uv_offset; -	uint pad0; -	uint pad1; +	uint multimesh_motion_vectors_current_offset; +	uint multimesh_motion_vectors_previous_offset;  }  draw_call; @@ -38,7 +40,7 @@ draw_call;  /* Set 0: Base Pass (never changes) */ -#include "light_data_inc.glsl" +#include "../light_data_inc.glsl"  #define SAMPLER_NEAREST_CLAMP 0  #define SAMPLER_LINEAR_CLAMP 1 @@ -61,13 +63,14 @@ layout(set = 0, binding = 3) uniform sampler decal_sampler;  layout(set = 0, binding = 4) uniform sampler light_projector_sampler; -#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) -#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) -#define INSTANCE_FLAGS_USE_SDFGI (1 << 7) -#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) -#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) -#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) +#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) +#define INSTANCE_FLAGS_USE_SDFGI (1 << 6) +#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7) +#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8) +#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) +#define INSTANCE_FLAGS_PARTICLES (1 << 11)  #define INSTANCE_FLAGS_MULTIMESH (1 << 12)  #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)  #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) @@ -105,6 +108,8 @@ directional_lights;  struct Lightmap {  	mat3 normal_xform; +	vec3 pad; +	float exposure_normalization;  };  layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { @@ -129,16 +134,18 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {  }  decals; -layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {  	vec4 data[];  } -global_variables; +global_shader_uniforms;  struct SDFVoxelGICascadeData {  	vec3 position;  	float to_probe;  	ivec3 probe_world_offset;  	float to_cell; // 1/bounds * grid_size +	vec3 pad; +	float exposure_normalization;  };  layout(set = 0, binding = 15, std140) uniform SDFGI { @@ -171,62 +178,27 @@ sdfgi;  /* Set 1: Render Pass (changes per render pass) */ -struct SceneData { -	mat4 projection_matrix; -	mat4 inv_projection_matrix; -	mat4 inv_view_matrix; -	mat4 view_matrix; - -	// only used for multiview -	mat4 projection_matrix_view[MAX_VIEWS]; -	mat4 inv_projection_matrix_view[MAX_VIEWS]; -	vec4 eye_offset[MAX_VIEWS]; - -	vec2 viewport_size; -	vec2 screen_pixel_size; +layout(set = 1, binding = 0, std140) uniform SceneDataBlock { +	SceneData data; +	SceneData prev_data; +} +scene_data_block; +struct ImplementationData {  	uint cluster_shift;  	uint cluster_width;  	uint cluster_type_size;  	uint max_cluster_element_count_div_32; -	// Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. -	vec4 directional_penumbra_shadow_kernel[32]; -	vec4 directional_soft_shadow_kernel[32]; -	vec4 penumbra_shadow_kernel[32]; -	vec4 soft_shadow_kernel[32]; - -	vec4 ambient_light_color_energy; - -	float ambient_color_sky_mix; -	bool use_ambient_light; -	bool use_ambient_cubemap; -	bool use_reflection_cubemap; - -	mat3 radiance_inverse_xform; - -	vec2 shadow_atlas_pixel_size; -	vec2 directional_shadow_pixel_size; - -	uint directional_light_count; -	float dual_paraboloid_side; -	float z_far; -	float z_near; -  	uint ss_effects_flags;  	float ssao_light_affect;  	float ssao_ao_affect; -	bool roughness_limiter_enabled; - -	float roughness_limiter_amount; -	float roughness_limiter_limit; -	float opaque_prepass_threshold; -	uint roughness_limiter_pad; +	uint pad1;  	mat4 sdf_to_bounds;  	ivec3 sdf_offset; -	bool material_uv2_mode; +	uint pad2;  	ivec3 sdf_size;  	bool gi_upscale_for_msaa; @@ -235,30 +207,14 @@ struct SceneData {  	float volumetric_fog_inv_length;  	float volumetric_fog_detail_spread;  	uint volumetric_fog_pad; - -	bool fog_enabled; -	float fog_density; -	float fog_height; -	float fog_height_density; - -	vec3 fog_light_color; -	float fog_sun_scatter; - -	float fog_aerial_perspective; - -	float time; -	float reflection_multiplier; // one normally, zero when rendering reflections - -	bool pancake_shadows; -	vec2 taa_jitter; -	uvec2 pad2;  }; -layout(set = 1, binding = 0, std140) uniform SceneDataBlock { -	SceneData data; -	SceneData prev_data; +layout(set = 1, binding = 1, std140) uniform ImplementationDataBlock { +	ImplementationData data;  } -scene_data_block; +implementation_data_block; + +#define implementation_data implementation_data_block.data  struct InstanceData {  	mat4 transform; @@ -270,42 +226,42 @@ struct InstanceData {  	vec4 lightmap_uv_scale;  }; -layout(set = 1, binding = 1, std430) buffer restrict readonly InstanceDataBuffer { +layout(set = 1, binding = 2, std430) buffer restrict readonly InstanceDataBuffer {  	InstanceData data[];  }  instances;  #ifdef USE_RADIANCE_CUBEMAP_ARRAY -layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap; +layout(set = 1, binding = 3) uniform textureCubeArray radiance_cubemap;  #else -layout(set = 1, binding = 2) uniform textureCube radiance_cubemap; +layout(set = 1, binding = 3) uniform textureCube radiance_cubemap;  #endif -layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas; +layout(set = 1, binding = 4) uniform textureCubeArray reflection_atlas; -layout(set = 1, binding = 4) uniform texture2D shadow_atlas; +layout(set = 1, binding = 5) uniform texture2D shadow_atlas; -layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas; +layout(set = 1, binding = 6) uniform texture2D directional_shadow_atlas; -layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; +layout(set = 1, binding = 7) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -layout(set = 1, binding = 7) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; +layout(set = 1, binding = 8) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; -layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer { +layout(set = 1, binding = 9, std430) buffer restrict readonly ClusterBuffer {  	uint data[];  }  cluster_buffer;  #ifdef MODE_RENDER_SDF -layout(r16ui, set = 1, binding = 9) uniform restrict writeonly uimage3D albedo_volume_grid; -layout(r32ui, set = 1, binding = 10) uniform restrict writeonly uimage3D emission_grid; -layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_aniso_grid; -layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid; +layout(r16ui, set = 1, binding = 10) uniform restrict writeonly uimage3D albedo_volume_grid; +layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_grid; +layout(r32ui, set = 1, binding = 12) uniform restrict writeonly uimage3D emission_aniso_grid; +layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid;  //still need to be present for shaders that use it, so remap them to something  #define depth_buffer shadow_atlas @@ -314,21 +270,21 @@ layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid;  #else -layout(set = 1, binding = 9) uniform texture2D depth_buffer; -layout(set = 1, binding = 10) uniform texture2D color_buffer; +layout(set = 1, binding = 10) uniform texture2D depth_buffer; +layout(set = 1, binding = 11) uniform texture2D color_buffer;  #ifdef USE_MULTIVIEW -layout(set = 1, binding = 11) uniform texture2DArray normal_roughness_buffer; -layout(set = 1, binding = 13) uniform texture2DArray ambient_buffer; -layout(set = 1, binding = 14) uniform texture2DArray reflection_buffer; +layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer; +layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer; +layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer;  #else // USE_MULTIVIEW -layout(set = 1, binding = 11) uniform texture2D normal_roughness_buffer; -layout(set = 1, binding = 13) uniform texture2D ambient_buffer; -layout(set = 1, binding = 14) uniform texture2D reflection_buffer; +layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer; +layout(set = 1, binding = 14) uniform texture2D ambient_buffer; +layout(set = 1, binding = 15) uniform texture2D reflection_buffer;  #endif -layout(set = 1, binding = 12) uniform texture2D ao_buffer; -layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture; -layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades; +layout(set = 1, binding = 13) uniform texture2D ao_buffer; +layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture; +layout(set = 1, binding = 17) uniform texture3D sdfgi_occlusion_cascades;  struct VoxelGIData {  	mat4 xform; // 64 - 64 @@ -340,16 +296,19 @@ struct VoxelGIData {  	float normal_bias; // 4 - 88  	bool blend_ambient; // 4 - 92  	uint mipmaps; // 4 - 96 + +	vec3 pad; // 12 - 108 +	float exposure_normalization; // 4 - 112  }; -layout(set = 1, binding = 17, std140) uniform VoxelGIs { +layout(set = 1, binding = 18, std140) uniform VoxelGIs {  	VoxelGIData data[MAX_VOXEL_GI_INSTANCES];  }  voxel_gi_instances; -layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture; +layout(set = 1, binding = 19) uniform texture3D volumetric_fog_texture; -layout(set = 1, binding = 19) uniform texture2D ssil_buffer; +layout(set = 1, binding = 20) uniform texture2D ssil_buffer;  #endif diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub new file mode 100644 index 0000000000..f06a2d86e2 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: +    # find all include files +    gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")] + +    # find all shader code(all glsl files excluding our include files) +    glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + +    # make sure we recompile shaders if include files change +    env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + +    # compile shaders +    for glsl_file in glsl_files: +        env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 26d0de46c2..d50749306e 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib;  //only for pure render depth when normal is not used  #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib;  #endif  #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib;  #endif  #if defined(COLOR_USED) @@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib;  layout(location = 11) in vec4 weight_attrib;  #endif +vec3 oct_to_vec3(vec2 e) { +	vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); +	float t = max(-v.z, 0.0); +	v.xy += t * -sign(v.xy); +	return normalize(v); +} +  /* Varyings */  layout(location = 0) highp out vec3 vertex_interp; @@ -94,7 +101,7 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms  #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) out highp float dp_clip; +layout(location = 9) out highp float dp_clip;  #endif @@ -116,6 +123,33 @@ invariant gl_Position;  #define scene_data scene_data_block.data +#ifdef USE_DOUBLE_PRECISION +// Helper functions for emulating double precision when adding floats. +vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) { +	vec3 s = a + b; +	out_p = b - (s - a); +	return s; +} + +vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) { +	vec3 s = a + b; +	vec3 v = s - a; +	out_p = (a - (s - v)) + (b - v); +	return s; +} + +vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) { +	vec3 s, t, se, te; +	s = two_sum(base_a, base_b, se); +	t = two_sum(prec_a, prec_b, te); +	se += t; +	s = quick_two_sum(s, se, se); +	se += te; +	s = quick_two_sum(s, se, out_precision); +	return s; +} +#endif +  void main() {  	vec4 instance_custom = vec4(0.0);  #if defined(COLOR_USED) @@ -125,6 +159,17 @@ void main() {  	bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH);  	mat4 model_matrix = draw_call.transform; +	mat4 inv_view_matrix = scene_data.inv_view_matrix; +#ifdef USE_DOUBLE_PRECISION +	vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); +	model_matrix[0][3] = 0.0; +	model_matrix[1][3] = 0.0; +	model_matrix[2][3] = 0.0; +	vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]); +	inv_view_matrix[0][3] = 0.0; +	inv_view_matrix[1][3] = 0.0; +	inv_view_matrix[2][3] = 0.0; +#endif  	mat3 model_normal_matrix;  	if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { @@ -133,11 +178,12 @@ void main() {  		model_normal_matrix = mat3(model_matrix);  	} +	mat4 matrix; +	mat4 read_model_matrix = model_matrix; +  	if (is_multimesh) {  		//multimesh, instances are for it -		mat4 matrix; -  #ifdef USE_PARTICLE_TRAILS  		uint trail_size = (draw_call.flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;  		uint stride = 3 + 1 + 1; //particles always uses this format @@ -223,18 +269,27 @@ void main() {  #endif  		//transpose  		matrix = transpose(matrix); -		model_matrix = model_matrix * matrix; + +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED) +		// Normally we can bake the multimesh transform into the model matrix, but when using double precision +		// we avoid baking it in so we can emulate high precision. +		read_model_matrix = model_matrix * matrix; +#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +		model_matrix = read_model_matrix; +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) +#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)  		model_normal_matrix = model_normal_matrix * mat3(matrix);  	}  	vec3 vertex = vertex_attrib;  #ifdef NORMAL_USED -	vec3 normal = normal_attrib * 2.0 - 1.0; +	vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);  #endif  #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -	vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; -	float binormalf = tangent_attrib.a * 2.0 - 1.0; +	vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; +	vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); +	float binormalf = sign(signed_tangent_attrib.y);  	vec3 binormal = normalize(cross(normal, tangent) * binormalf);  #endif @@ -289,7 +344,22 @@ void main() {  // using local coordinates (default)  #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) +#ifdef USE_DOUBLE_PRECISION +	// We separate the basis from the origin because the basis is fine with single point precision. +	// Then we combine the translations from the model matrix and the view matrix using emulated doubles. +	// We add the result to the vertex and ignore the final lost precision. +	vec3 model_origin = model_matrix[3].xyz; +	if (is_multimesh) { +		vertex = mat3(matrix) * vertex; +		model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision); +	} +	vertex = mat3(model_matrix) * vertex; +	vec3 temp_precision; +	vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision); +	vertex = mat3(scene_data.view_matrix) * vertex; +#else  	vertex = (modelview * vec4(vertex, 1.0)).xyz; +#endif  #ifdef NORMAL_USED  	normal = modelview_normal * normal;  #endif @@ -442,7 +512,7 @@ layout(location = 6) mediump in vec3 binormal_interp;  #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) highp in float dp_clip; +layout(location = 9) highp in float dp_clip;  #endif @@ -460,11 +530,12 @@ layout(location = 8) highp in float dp_clip;  //defines to keep compatibility with vertex -#define model_matrix draw_call.transform  #ifdef USE_MULTIVIEW  #define projection_matrix scene_data.projection_matrix_view[ViewIndex] +#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex]  #else  #define projection_matrix scene_data.projection_matrix +#define inv_projection_matrix scene_data.inv_projection_matrix  #endif  #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) @@ -509,7 +580,7 @@ layout(location = 0) out mediump vec4 frag_color;  #endif // RENDER DEPTH -#include "scene_forward_aa_inc.glsl" +#include "../scene_forward_aa_inc.glsl"  #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -518,7 +589,7 @@ layout(location = 0) out mediump vec4 frag_color;  #define SPECULAR_SCHLICK_GGX  #endif -#include "scene_forward_lights_inc.glsl" +#include "../scene_forward_lights_inc.glsl"  #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -675,6 +746,17 @@ void main() {  	vec2 alpha_texture_coordinate = vec2(0.0, 0.0);  #endif // ALPHA_ANTIALIASING_EDGE_USED +	mat4 inv_view_matrix = scene_data.inv_view_matrix; +	mat4 read_model_matrix = draw_call.transform; +#ifdef USE_DOUBLE_PRECISION +	read_model_matrix[0][3] = 0.0; +	read_model_matrix[1][3] = 0.0; +	read_model_matrix[2][3] = 0.0; +	inv_view_matrix[0][3] = 0.0; +	inv_view_matrix[1][3] = 0.0; +	inv_view_matrix[2][3] = 0.0; +#endif +  	{  #CODE : FRAGMENT  	} @@ -697,7 +779,8 @@ void main() {  // alpha hash can be used in unison with alpha antialiasing  #ifdef ALPHA_HASH_USED -	if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { +	vec3 object_pos = (inverse(read_model_matrix) * inv_view_matrix * vec4(vertex, 1.0)).xyz; +	if (alpha < compute_alpha_hash_threshold(object_pos, alpha_hash_scale)) {  		discard;  	}  #endif // ALPHA_HASH_USED @@ -879,6 +962,11 @@ void main() {  	vec3 diffuse_light = vec3(0.0, 0.0, 0.0);  	vec3 ambient_light = vec3(0.0, 0.0, 0.0); +#ifndef MODE_UNSHADED +	// Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI. +	emission *= scene_data.emissive_exposure_normalization; +#endif +  #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)  	if (scene_data.use_reflection_cubemap) { @@ -889,8 +977,10 @@ void main() {  		vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);  		vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));  		vec3 ref_vec = reflect(-view, bent_normal); +		ref_vec = mix(ref_vec, bent_normal, roughness * roughness);  #else  		vec3 ref_vec = reflect(-view, normal); +		ref_vec = mix(ref_vec, normal, roughness * roughness);  #endif  		float horizon = min(1.0 + dot(ref_vec, normal), 1.0);  		ref_vec = scene_data.radiance_inverse_xform * ref_vec; @@ -905,6 +995,8 @@ void main() {  		specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;  #endif //USE_RADIANCE_CUBEMAP_ARRAY +		specular_light *= sc_luminance_multiplier; +		specular_light *= scene_data.IBL_exposure_normalization;  		specular_light *= horizon * horizon;  		specular_light *= scene_data.ambient_light_color_energy.a;  	} @@ -925,7 +1017,8 @@ void main() {  #else  			vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;  #endif //USE_RADIANCE_CUBEMAP_ARRAY - +			cubemap_ambient *= sc_luminance_multiplier; +			cubemap_ambient *= scene_data.IBL_exposure_normalization;  			ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);  		}  	} @@ -940,6 +1033,7 @@ void main() {  		vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map  		float NoV = max(dot(n, view), 0.0001);  		vec3 ref_vec = reflect(-view, n); +		ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);  		// The clear coat layer assumes an IOR of 1.5 (4% reflectance)  		float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV));  		float attenuation = 1.0 - Fc; @@ -982,15 +1076,16 @@ void main() {  		const float c4 = 0.886227;  		const float c5 = 0.247708;  		ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) + -				c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z + -				c4 * lightmap_captures.data[index].sh[0].rgb - -				c5 * lightmap_captures.data[index].sh[6].rgb + -				2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y + -				2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z + -				2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z + -				2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x + -				2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + -				2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); +								 c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z + +								 c4 * lightmap_captures.data[index].sh[0].rgb - +								 c5 * lightmap_captures.data[index].sh[6].rgb + +								 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y + +								 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z + +								 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z + +								 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x + +								 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + +								 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) * +				scene_data.emissive_exposure_normalization;  	} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap  		bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); @@ -999,6 +1094,8 @@ void main() {  		uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;  		uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF); +		uint idx = draw_call.gi_offset >> 20; +  		if (uses_sh) {  			uvw.z *= 4.0; //SH textures use 4 times more data  			vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb; @@ -1006,22 +1103,22 @@ void main() {  			vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;  			vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; -			uint idx = draw_call.gi_offset >> 20;  			vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); +			float exposure_normalization = lightmaps.data[idx].exposure_normalization;  			ambient_light += lm_light_l0 * 0.282095f; -			ambient_light += lm_light_l1n1 * 0.32573 * n.y; -			ambient_light += lm_light_l1_0 * 0.32573 * n.z; -			ambient_light += lm_light_l1p1 * 0.32573 * n.x; +			ambient_light += lm_light_l1n1 * 0.32573 * n.y * exposure_normalization; +			ambient_light += lm_light_l1_0 * 0.32573 * n.z * exposure_normalization; +			ambient_light += lm_light_l1p1 * 0.32573 * n.x * exposure_normalization;  			if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick  				vec3 r = reflect(normalize(-vertex), normal); -				specular_light += lm_light_l1n1 * 0.32573 * r.y; -				specular_light += lm_light_l1_0 * 0.32573 * r.z; -				specular_light += lm_light_l1p1 * 0.32573 * r.x; +				specular_light += lm_light_l1n1 * 0.32573 * r.y * exposure_normalization; +				specular_light += lm_light_l1_0 * 0.32573 * r.z * exposure_normalization; +				specular_light += lm_light_l1p1 * 0.32573 * r.x * exposure_normalization;  			}  		} else { -			ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb; +			ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;  		}  	} @@ -1036,6 +1133,19 @@ void main() {  		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);  		uint reflection_indices = draw_call.reflection_probes.x; + +#ifdef LIGHT_ANISOTROPY_USED +		// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy +		vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; +		vec3 anisotropic_tangent = cross(anisotropic_direction, view); +		vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); +		vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else +		vec3 bent_normal = normal; +#endif +		vec3 ref_vec = normalize(reflect(-view, bent_normal)); +		ref_vec = mix(ref_vec, bent_normal, roughness * roughness); +  		for (uint i = 0; i < 8; i++) {  			uint reflection_index = reflection_indices & 0xFF;  			if (i == 4) { @@ -1047,16 +1157,8 @@ void main() {  			if (reflection_index == 0xFF) {  				break;  			} -#ifdef LIGHT_ANISOTROPY_USED -			// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy -			vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; -			vec3 anisotropic_tangent = cross(anisotropic_direction, view); -			vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); -			vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); -#else -			vec3 bent_normal = normal; -#endif -			reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + +			reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);  		}  		if (reflection_accum.a > 0.0) { @@ -1071,8 +1173,14 @@ void main() {  	} //Reflection probes  	// finalize ambient light here -	ambient_light *= albedo.rgb; -	ambient_light *= ao; +	{ +#if defined(AMBIENT_LIGHT_DISABLED) +		ambient_light = vec3(0.0, 0.0, 0.0); +#else +		ambient_light *= albedo.rgb; +		ambient_light *= ao; +#endif // AMBIENT_LIGHT_DISABLED +	}  	// convert ao to direct light ao  	ao = mix(1.0, ao, ao_light_affect); @@ -1134,7 +1242,7 @@ void main() {  #ifdef USE_SOFT_SHADOWS  			//version with soft shadows, more expensive -			if (directional_lights.data[i].shadow_enabled) { +			if (directional_lights.data[i].shadow_opacity > 0.001) {  				float depth_z = -vertex.z;  				vec4 pssm_coord; @@ -1286,7 +1394,7 @@ void main() {  #else  			// Soft shadow disabled version -			if (directional_lights.data[i].shadow_enabled) { +			if (directional_lights.data[i].shadow_opacity > 0.001) {  				float depth_z = -vertex.z;  				vec4 pssm_coord; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 7413d8730a..631ff0575b 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -5,7 +5,8 @@  #extension GL_EXT_multiview : enable  #endif -#include "decal_data_inc.glsl" +#include "../decal_data_inc.glsl" +#include "../scene_data_inc.glsl"  #if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)  #ifndef NORMAL_USED @@ -32,7 +33,7 @@ draw_call;  /* Set 0: Base Pass (never changes) */ -#include "light_data_inc.glsl" +#include "../light_data_inc.glsl"  #define SAMPLER_NEAREST_CLAMP 0  #define SAMPLER_LINEAR_CLAMP 1 @@ -54,13 +55,14 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;  layout(set = 0, binding = 3) uniform sampler decal_sampler;  layout(set = 0, binding = 4) uniform sampler light_projector_sampler; -#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5) -#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) -#define INSTANCE_FLAGS_USE_SDFGI (1 << 7) -#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) -#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) -#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) -#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11) +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4) +#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5) +#define INSTANCE_FLAGS_USE_SDFGI (1 << 6) +#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7) +#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8) +#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9) +#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10) +#define INSTANCE_FLAGS_PARTICLES (1 << 11)  #define INSTANCE_FLAGS_MULTIMESH (1 << 12)  #define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)  #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) @@ -94,6 +96,8 @@ directional_lights;  struct Lightmap {  	mediump mat3 normal_xform; +	vec3 pad; +	float exposure_normalization;  };  layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps { @@ -118,82 +122,16 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {  }  decals; -layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {  	highp vec4 data[];  } -global_variables; +global_shader_uniforms;  /* Set 1: Render Pass (changes per render pass) */ -struct SceneData { -	highp mat4 projection_matrix; -	highp mat4 inv_projection_matrix; -	highp mat4 inv_view_matrix; -	highp mat4 view_matrix; - -	// only used for multiview -	highp mat4 projection_matrix_view[MAX_VIEWS]; -	highp mat4 inv_projection_matrix_view[MAX_VIEWS]; -	highp vec4 eye_offset[MAX_VIEWS]; - -	highp vec2 viewport_size; -	highp vec2 screen_pixel_size; - -	// Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. -	highp vec4 directional_penumbra_shadow_kernel[32]; -	highp vec4 directional_soft_shadow_kernel[32]; -	highp vec4 penumbra_shadow_kernel[32]; -	highp vec4 soft_shadow_kernel[32]; - -	mediump vec4 ambient_light_color_energy; - -	mediump float ambient_color_sky_mix; -	bool use_ambient_light; -	bool use_ambient_cubemap; -	bool use_reflection_cubemap; - -	mediump mat3 radiance_inverse_xform; - -	highp vec2 shadow_atlas_pixel_size; -	highp vec2 directional_shadow_pixel_size; - -	uint directional_light_count; -	mediump float dual_paraboloid_side; -	highp float z_far; -	highp float z_near; - -	bool ssao_enabled; -	mediump float ssao_light_affect; -	mediump float ssao_ao_affect; -	bool roughness_limiter_enabled; - -	mediump float roughness_limiter_amount; -	mediump float roughness_limiter_limit; -	mediump float opaque_prepass_threshold; -	uint roughness_limiter_pad; - -	bool fog_enabled; -	highp float fog_density; -	highp float fog_height; -	highp float fog_height_density; - -	mediump vec3 fog_light_color; -	mediump float fog_sun_scatter; - -	mediump float fog_aerial_perspective; -	bool material_uv2_mode; - -	highp float time; -	mediump float reflection_multiplier; // one normally, zero when rendering reflections - -	bool pancake_shadows; -	uint pad1; -	uint pad2; -	uint pad3; -}; -  layout(set = 1, binding = 0, std140) uniform SceneDataBlock {  	SceneData data; +	SceneData prev_data;  }  scene_data_block; diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl index 61c8488a05..7488a3f2c7 100644 --- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl @@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible  	mediump float cone_attenuation;  	mediump float cone_angle;  	mediump float specular_amount; -	bool shadow_enabled; +	mediump float shadow_opacity;  	highp vec4 atlas_rect; // rect in the shadow atlas  	highp mat4 shadow_matrix; @@ -25,7 +25,7 @@ struct LightData { //this structure needs to be as packed as possible  	highp float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle  	highp float soft_shadow_scale; // scales the shadow kernel for blurrier shadows  	uint mask; -	mediump float shadow_volumetric_fog_fade; +	mediump float volumetric_fog_energy;  	uint bake_mode;  	highp vec4 projector_rect; //projector rect in srgb decal atlas  }; @@ -44,7 +44,7 @@ struct ReflectionData {  	bool exterior;  	bool box_project;  	uint ambient_mode; -	uint pad; +	float exposure_normalization;  	//0-8 is intensity,8-9 is ambient, mode  	highp 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 @@ -52,7 +52,7 @@ struct ReflectionData {  struct DirectionalLightData {  	mediump vec3 direction; -	mediump float energy; +	highp float energy; // needs to be highp to avoid NaNs being created with high energy values (i.e. when using physical light units and over-exposing the image)  	mediump vec3 color;  	mediump float size;  	mediump float specular; @@ -60,12 +60,12 @@ struct DirectionalLightData {  	highp float softshadow_angle;  	highp float soft_shadow_scale;  	bool blend_splits; -	bool shadow_enabled; +	mediump float shadow_opacity;  	highp float fade_from;  	highp float fade_to;  	uvec2 pad;  	uint bake_mode; -	mediump float shadow_volumetric_fog_fade; +	mediump float volumetric_fog_energy;  	highp vec4 shadow_bias;  	highp vec4 shadow_normal_bias;  	highp vec4 shadow_transmittance_bias; diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index acb62b812e..9f6aa7adc0 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -25,10 +25,10 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;  layout(set = 0, binding = 1) uniform sampler material_samplers[12]; -layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {  	vec4 data[];  } -global_variables; +global_shader_uniforms;  /* Set 1: FRAME AND PARTICLE DATA */ @@ -458,11 +458,11 @@ void main() {  				} break;  				case ATTRACTOR_TYPE_VECTOR_FIELD: { -					vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0; +					vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5;  					if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) {  						continue;  					} -					vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz; +					vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * -2.0 + 1.0;  					dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction  					amount = length(s); @@ -475,7 +475,7 @@ void main() {  		float particle_size = FRAME.particle_size; -#ifdef USE_COLLISON_SCALE +#ifdef USE_COLLISION_SCALE  		particle_size *= dot(vec3(length(PARTICLE.xform[0].xyz), length(PARTICLE.xform[1].xyz), length(PARTICLE.xform[2].xyz)), vec3(0.33333333333)); diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl new file mode 100644 index 0000000000..048257e9ef --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -0,0 +1,69 @@ +// Scene data stores all our 3D rendering globals for a frame such as our matrices +// where this information is independent of the different RD implementations. +// This enables us to use this UBO in our main scene render shaders but also in +// effects that need access to this data. + +struct SceneData { +	highp mat4 projection_matrix; +	highp mat4 inv_projection_matrix; +	highp mat4 inv_view_matrix; +	highp mat4 view_matrix; + +	// only used for multiview +	highp mat4 projection_matrix_view[MAX_VIEWS]; +	highp mat4 inv_projection_matrix_view[MAX_VIEWS]; +	highp vec4 eye_offset[MAX_VIEWS]; + +	highp vec2 viewport_size; +	highp vec2 screen_pixel_size; + +	// Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. +	highp vec4 directional_penumbra_shadow_kernel[32]; +	highp vec4 directional_soft_shadow_kernel[32]; +	highp vec4 penumbra_shadow_kernel[32]; +	highp vec4 soft_shadow_kernel[32]; + +	mediump mat3 radiance_inverse_xform; + +	mediump vec4 ambient_light_color_energy; + +	mediump float ambient_color_sky_mix; +	bool use_ambient_light; +	bool use_ambient_cubemap; +	bool use_reflection_cubemap; + +	highp vec2 shadow_atlas_pixel_size; +	highp vec2 directional_shadow_pixel_size; + +	uint directional_light_count; +	mediump float dual_paraboloid_side; +	highp float z_far; +	highp float z_near; + +	bool roughness_limiter_enabled; +	mediump float roughness_limiter_amount; +	mediump float roughness_limiter_limit; +	mediump float opaque_prepass_threshold; + +	bool fog_enabled; +	highp float fog_density; +	highp float fog_height; +	highp float fog_height_density; + +	mediump vec3 fog_light_color; +	mediump float fog_sun_scatter; + +	mediump float fog_aerial_perspective; +	highp float time; +	mediump float reflection_multiplier; // one normally, zero when rendering reflections +	bool material_uv2_mode; + +	vec2 taa_jitter; +	float emissive_exposure_normalization; +	float IBL_exposure_normalization; + +	bool pancake_shadows; +	uint pad1; +	uint pad2; +	uint pad3; +}; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl index 97c913d489..71510ee06a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl @@ -11,7 +11,8 @@ float hash_3d(vec3 p) {  float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {  	vec3 dx = dFdx(pos); -	vec3 dy = dFdx(pos); +	vec3 dy = dFdy(pos); +  	float delta_max_sqr = max(length(dx), length(dy));  	float pix_scale = 1.0 / (hash_scale * delta_max_sqr); @@ -32,9 +33,9 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {  			1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp))));  	float alpha_hash_threshold = -			(lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z; +			(a_interp < (1.0 - min_lerp)) ? ((a_interp < min_lerp) ? cases.x : cases.y) : cases.z; -	return clamp(alpha_hash_threshold, 0.0, 1.0); +	return clamp(alpha_hash_threshold, 0.00001, 1.0);  }  #endif // ALPHA_HASH_USED diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl index c88bd0a14b..ae5e1b7251 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl @@ -94,7 +94,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3  		light += cone_weights[i] * cone_light.rgb;  	} -	light *= voxel_gi_instances.data[index].dynamic_range; +	light *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;  	out_diff += vec4(light * blend, blend);  	//irradiance @@ -102,7 +102,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3  	if (voxel_gi_instances.data[index].blend_ambient) {  		irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));  	} -	irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range; +	irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;  	//irr_light=vec3(0.0);  	out_spec += vec4(irr_light.rgb * blend, blend); @@ -189,7 +189,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal  		pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;  		diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb; -		diffuse_accum += vec4(diffuse * weight, weight); +		diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);  		if (use_specular) {  			vec3 specular = vec3(0.0); @@ -203,7 +203,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal  				specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0);  			} -			specular_accum += specular * weight; +			specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;  		}  	} diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index c92b29b14a..2fba1351f7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -97,11 +97,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte  		float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance  #if defined(DIFFUSE_LAMBERT_WRAP) -		// energy conserving lambert wrap shader -		diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); +		// Energy conserving lambert wrap shader. +		// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/ +		diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);  #elif defined(DIFFUSE_TOON) -		diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); +		diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);  #elif defined(DIFFUSE_BURLEY) @@ -199,7 +200,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte  #endif // LIGHT_ANISOTROPY_USED  	   // F  		float cLdotH5 = SchlickFresnel(cLdotH); -		vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); +		// Calculate Fresnel using specular occlusion term from Filament: +		// https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion +		float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0); +		vec3 F = f0 + (f90 - f0) * cLdotH5;  		vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -392,7 +396,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {  float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {  #ifndef SHADOWS_DISABLED -	if (omni_lights.data[idx].shadow_enabled) { +	if (omni_lights.data[idx].shadow_opacity > 0.001) {  		// there is a shadowmap  		vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;  		vec4 base_uv_rect = omni_lights.data[idx].atlas_rect; @@ -495,6 +499,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {  				}  				shadow /= float(sc_penumbra_shadow_samples); +				shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);  			} else {  				//no blockers found, so no shadow @@ -513,7 +518,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {  			vec2 pos = shadow_sample.xy / shadow_sample.z;  			float depth = shadow_len - omni_lights.data[idx].shadow_bias;  			depth *= omni_lights.data[idx].inv_radius; -			shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth); +			shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);  		}  		return shadow; @@ -671,7 +676,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v  float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {  #ifndef SHADOWS_DISABLED -	if (spot_lights.data[idx].shadow_enabled) { +	if (spot_lights.data[idx].shadow_opacity > 0.001) {  		vec3 light_rel_vec = spot_lights.data[idx].position - vertex;  		float light_length = length(light_rel_vec);  		vec3 spot_dir = spot_lights.data[idx].direction; @@ -732,6 +737,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {  				}  				shadow /= float(sc_penumbra_shadow_samples); +				shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);  			} else {  				//no blockers found, so no shadow @@ -740,7 +746,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {  		} else {  			//hard shadow  			vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z); -			shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv); +			shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity);  		}  		return shadow; @@ -869,7 +875,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v  			diffuse_light, specular_light);  } -void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { +void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {  	vec3 box_extents = reflections.data[ref_index].box_extents;  	vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz; @@ -877,8 +883,6 @@ void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, flo  		return;  	} -	vec3 ref_vec = normalize(reflect(-view, normal)); -  	vec3 inner_pos = abs(local_pos / box_extents);  	float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));  	//make blend more rounded @@ -906,7 +910,7 @@ void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, flo  		vec4 reflection;  		reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier; - +		reflection.rgb *= reflections.data[ref_index].exposure_normalization;  		if (reflections.data[ref_index].exterior) {  			reflection.rgb = mix(specular_light, reflection.rgb, blend);  		} @@ -929,6 +933,7 @@ void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, flo  			vec4 ambient_out;  			ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb; +			ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;  			ambient_out.a = blend;  			if (reflections.data[ref_index].exterior) {  				ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index a893a66c94..f5b233cca0 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params {  }  params; -vec4 decode_abgr_2_10_10_10(uint base) { -	uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3); -	return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0; +vec2 uint_to_vec2(uint base) { +	uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF); +	return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0;  } -uint encode_abgr_2_10_10_10(vec4 base) { -	uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30); -	return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w; +vec3 oct_to_vec3(vec2 oct) { +	vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y)); +	float t = max(-v.z, 0.0); +	v.xy += t * -sign(v.xy); +	return normalize(v); +} + +vec3 decode_uint_oct_to_norm(uint base) { +	return oct_to_vec3(uint_to_vec2(base)); +} + +vec4 decode_uint_oct_to_tang(uint base) { +	vec2 oct_sign_encoded = uint_to_vec2(base); +	// Binormal sign encoded in y component +	vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0); +	return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y)); +} + +vec2 signNotZero(vec2 v) { +	return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0))); +} + +uint vec2_to_uint(vec2 base) { +	uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16); +	return enc.x | enc.y; +} + +vec2 vec3_to_oct(vec3 e) { +	e /= abs(e.x) + abs(e.y) + abs(e.z); +	vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy); +	return oct * 0.5f + 0.5f; +} + +uint encode_norm_to_uint_oct(vec3 base) { +	return vec2_to_uint(vec3_to_oct(base)); +} + +uint encode_tang_to_uint_oct(vec4 base) { +	vec2 oct = vec3_to_oct(base.xyz); +	// Encode binormal sign in y component +	oct.y = oct.y * 0.5f + 0.5f; +	oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y; +	return vec2_to_uint(oct);  }  void main() { @@ -103,8 +143,8 @@ void main() {  		uint skin_offset = params.skin_stride * index;  		uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); -		uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset -		uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3; +		uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 2; //pre-add xform offset +		uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 2;  		skin_offset += params.skin_weight_offset; @@ -121,6 +161,13 @@ void main() {  		//reverse order because its transposed  		vertex = (vec4(vertex, 0.0, 1.0) * m).xy;  	} + +	uint dst_offset = index * params.vertex_stride; + +	uvec2 uvertex = floatBitsToUint(vertex); +	dst_vertices.data[dst_offset + 0] = uvertex.x; +	dst_vertices.data[dst_offset + 1] = uvertex.y; +  #else  	vec3 vertex;  	vec3 normal; @@ -131,12 +178,12 @@ void main() {  	src_offset += 3;  	if (params.has_normal) { -		normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb; +		normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]);  		src_offset++;  	}  	if (params.has_tangent) { -		tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]); +		tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]);  	}  	if (params.has_blend_shape) { @@ -155,12 +202,12 @@ void main() {  				base_offset += 3;  				if (params.has_normal) { -					blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; +					blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w;  					base_offset++;  				}  				if (params.has_tangent) { -					blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; +					blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w;  				}  				blend_total += w; @@ -234,12 +281,12 @@ void main() {  	dst_offset += 3;  	if (params.has_normal) { -		dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0)); +		dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal);  		dst_offset++;  	}  	if (params.has_tangent) { -		dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent); +		dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent);  	}  #endif  |