Skip to content

Allow double precision modelview #106951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 24, 2025

Conversation

celyk
Copy link
Contributor

@celyk celyk commented May 30, 2025

@celyk celyk requested a review from a team as a code owner May 30, 2025 05:00
@Calinou Calinou added bug topic:rendering topic:3d cherrypick:4.4 Considered for cherry-picking into a future 4.4.x release labels May 30, 2025
@Calinou Calinou added this to the 4.5 milestone May 30, 2025
@cridenour
Copy link
Contributor

Thank you @celyk for this fantastic work.

I've tested the MRPs and this affects the following:

Closes #104654
Closes #101139
Closes #76388
Closes #89061
Closes #73383
Supersedes #89165

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change loses the precision benefits of using the split operators. With this the transforms are just using single precision.

The most important part of the double precision approach is to separate the translation of the vertex position into two additions (1 add the vertex position to the modelview translation, 2 add in the error term.

This PR completely removes that operation and combines everything ahead of time. Which means that when transforming the vertex we lose the extra precision and effectively do a single precision transformation.

What this appears to improve is the addition of the multimesh instance translation with the normal instance transform

@fire fire requested a review from a team May 30, 2025 21:13
@celyk
Copy link
Contributor Author

celyk commented May 31, 2025

the transforms are just using single precision

Yes, but the transformation from model to view space does not need double. The translation component of the transformation is small enough because it's centred around the camera.

when transforming the vertex we lose the extra precision and effectively do a single precision transformation

This is what you do anyway? The vertex never goes into double_add_vec3(), and the translation uses regular addition.

This PR completely removes that operation and combines everything ahead of time

But I was careful not to alter calls to double_add_vec3(). Notice that each of those calls should give the same output as before, thus respecting the error term.

Whether the final translation is applied through an addition or a translation matrix, what difference does it make? Either way it becomes a single precision addition by the end.

@fire fire changed the title Double precision modelview Allow double precision modelview May 31, 2025
@celyk
Copy link
Contributor Author

celyk commented Jun 1, 2025

Tested using Calinou's Large World Coordinates demo

image

@fire
Copy link
Member

fire commented Jun 1, 2025

@celyk can you post the MRP as the issue report too. It'll help. Like off and on.

@celyk
Copy link
Contributor Author

celyk commented Jun 2, 2025

Sorry fire I'm not sure what you mean. The MRP (the official demo project) is provided, you want me to put this at the top?

@fire
Copy link
Member

fire commented Jun 2, 2025

Let me try message you.

I wanted to double check that the https://github.com/godotengine/godot/files/13539578/INV_VIEW_MATRIX.bug.Game.Project.zip MRP would be fixed in the situation where the camera is far away from the origin due to concerns from @clayjohn

@celyk
Copy link
Contributor Author

celyk commented Jun 2, 2025

No that will not be fixed, because my PR only applies to MODELVIEW_MATRIX. But I'm thinking of making a proposal for how the other transforms can be addressed

@celyk
Copy link
Contributor Author

celyk commented Jun 2, 2025

To elaborate on my idea of a helper function, here's some example code (untested)

// Multiplies a double mat4 with a double vec3
mat4 double_mul_mat4_vec3(mat4 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) {
	// Assume that M * vec4(p,1) == M[3].xyz + mat3(M) * p
	base_b = mat3(base_a) * base_b;
	base_b = double_add_vec3(base_a[3].xyz, prec_a, base_b, prec_b, out_precision);
	return base_b;
}

// Multiplies a double mat4 with a double mat4
mat4 double_mul_mat4(mat4 base_a, vec3 prec_a, mat4 base_b, vec3 prec_b, out vec3 out_precision) {
	// Only the translation part supports double precision at the moment.

	// Single precision transform just to fill the mat3 basis. Ignore the last column
	mat4 T = base_a * base_b;

	// Transform the origin of base_b, and pass out the error term
	T[3].xyz = double_mul_mat4_vec3(base_a, prec_a, base_b[3].xyz, prec_b, out_precision);

	return T;
}
#endif

If I'm correct this should allow arbitrary concatenation of transforms, and this PR would reduce to:

#ifdef USE_DOUBLE_PRECISION
	vec3 temp_precision;
	mat4 modelview = double_mul_mat4(scene_data.view_matrix, view_precision, model_matrix, model_precision, temp_precision);
#else
	mat4 modelview = scene_data.view_matrix * model_matrix;
#endif

@celyk
Copy link
Contributor Author

celyk commented Jun 2, 2025

Hmmm, double_mul_mat4_vec3() looks wrong for transforming base_b with single precision. The reason this is ok in the PR is we know the vector is already small relative to the camera.

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your clarification. On second thought this does seem safe.

I was forgetting that the original adds the model transform and camera transforms together with high precision but adds the result of that to the vertex position with single precision. So indeed, this does do the final operation in single precision, but that doesn't change from how it was before.

@clayjohn
Copy link
Member

The final step before merging is to rebase and then squash all the commits together so that the whole PR only contains 1 big commit with all your changes. We like to merge one commit at a time to keep the git history clean and navigable.

If you don't know how to do that, we have a helpful tutorial in the official documentation https://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html#the-interactive-rebase

@celyk celyk force-pushed the double-precision-modelview branch from 92726da to 7f9b8da Compare June 24, 2025 05:39
@clayjohn
Copy link
Member

Looks great! I've queued this up for Beta 2 :)

@Repiteo Repiteo merged commit e59215a into godotengine:master Jun 24, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Jun 24, 2025

Thanks! Congratulations on your first merged contribution! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment