Shader transform differences in double-precision builds

Godot Version

4.2.1 - 4.3

Question

I have been trying to understand something about how Godot’s rendering/shaders work and I have kinda hit a dead end…

So, here is my test shader:

shader_type spatial;
render_mode unshaded, skip_vertex_transform;

uniform sampler2D bg_texture : source_color, hint_screen_texture;
uniform sampler2D depth_texture : source_color, hint_depth_texture;

void vertex()
{
	POSITION = vec4(VERTEX, 1.0);
}

void fragment()
{
	float depth = texture(depth_texture, SCREEN_UV).x;
	vec3 nrm_dev_coord = vec3(SCREEN_UV * 2.0 - 1.0, depth);
	vec4 vs_pos = INV_PROJECTION_MATRIX * vec4(nrm_dev_coord, 1.0);
	//vs_pos.xyz *= -1.0;
	vec3 ws_pos = (INV_VIEW_MATRIX * vec4(vs_pos.xyz / vs_pos.w, 1.0)).xyz;

	float fade = 1.0 - clamp(length(ws_pos) / 4.0, 0.0, 1.0);

	ALBEDO = texture(bg_texture, SCREEN_UV).rgb * fade;
}

This is just a post-processing effect using a full-screen quad (as seen in Advanced post-processing — Godot Engine (stable) documentation in English , with some modifications)

All it does is calculate the world position of the fragment and then fade it to black based on how far away it is from the world origin. Here’s what that looks like:

The thing is… when I run this exact same code in a double-precision float build instead of single-precision, it doesn’t work. It just displays a black screen.

That’s where this line comes in: //vs_pos.xyz *= -1.0; In double-precision builds, it has to be uncommented, I guess negating the view space coordinates. And then it works again.

So my question is: Huh?

I just don’t understand what’s going on, here. There’s not much documentation on the differences that 64-bit floats have in the engine internals, but from looking through the source I can see some things are being done to INV_VIEW_MATRIX before and after it’s transferred into the shader, but matrix stuff in general is very hard for me to get my head around, so I don’t know what that code is really doing.

I would very much appreciate some help understanding this, or what I could do differently to not have to worry about this, as the main project I’m working on very much needs 64 bit floats to work properly, and I don’t want to be caught unaware of subtle differences like this.

1 Like

Hi bud, i have encountered a similar issue when using this lovely volumetric cloud shader in double precision mode.

The shader is great and supports 4.3, but i noticed when i recompiled godot with double precision the world position derived from INV_VIEW_MATRIX[3].xyz was inverted, and i also found that inverting it back via INV_VIEW_MATRIX[3].xyz * -1.0 solved the issue.

I looked at the godot engine code i’m not sure what the problem is exactly, but i know that the engine is using some workarounds to send double precision floating point values into the shader code. I noticed that the camera transform is inverted in the pipeline, but only when REAL_T_IS_DOUBLE is defined. See servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp

#ifdef REAL_T_IS_DOUBLE
	RendererRD::MaterialStorage::split_double(-cam_transform.origin.x, &ubo.inv_view_matrix[12], &ubo.inv_view_matrix[3]);
	RendererRD::MaterialStorage::split_double(-cam_transform.origin.y, &ubo.inv_view_matrix[13], &ubo.inv_view_matrix[7]);
	RendererRD::MaterialStorage::split_double(-cam_transform.origin.z, &ubo.inv_view_matrix[14], &ubo.inv_view_matrix[11]);
#endif

and further down

#ifdef REAL_T_IS_DOUBLE
		RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.x, &prev_ubo.inv_view_matrix[12], &prev_ubo.inv_view_matrix[3]);
		RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.y, &prev_ubo.inv_view_matrix[13], &prev_ubo.inv_view_matrix[7]);
		RendererRD::MaterialStorage::split_double(-prev_cam_transform.origin.z, &prev_ubo.inv_view_matrix[14], &prev_ubo.inv_view_matrix[11]);
#endif

These blocks of code invert the cam_transform origin. Not sure why, but they need to stay this way in order for the editor to function normally. Editing the negative sign away borks the editor.

Edit: Found a relevant issue

Edit:

This commit fixes the issue

1 Like