Open alekseym88 opened 1 year ago
Can you reproduce this in 3.5.1?
I think the issue here is actually with the INV_PROJECTION_MATRIX
. If you for ALBEDO = clip_uv - clip_pos;
then the UVs offset as expected. Additionally, VIEW_MATRIX
and PROJECTION_MATRIX
are both used when rendering any object. If either one of them was broken objects would not render correctly. INV_PROJECTION_MATRIX
however, is only exposed to users, so problems with it only appear in custom shaders
Edit: Okay I can confirm something is off in INV_PROJECTION_MATRIX
Taking a value from world space into view space and back leaves the value unchanged. But taking something from view space into clip space and back changes the value.
Edit: And after further testing, the issue is only present for orthogonal cameras, perspective cameras work fine. This explains why this hasn't been caught earlier.
@clayjohn yes, confirm this. As a temporary solution can use inverse(PROJECTION_MATRIX) instead INV_PROJECTION_MATRIX, and result looks fine:
I was just implementing full screen quad and lost 2h of debugging due to this.
Definitely INV_PROJECTION_MATRIX
is broken under orthogonal camera (it's fine under projection camera).
With the inverse(PROJECTION_MATRIX)
it's fine.
Code:
shader_type spatial;
render_mode unshaded;
uniform vec4 color : source_color = vec4(0.0);
void vertex()
{
POSITION = vec4(VERTEX, 1);
}
void fragment()
{
ALBEDO = color.rgb;
ALPHA = 0.9;
// depth is encoded on first channel and is <0; 1>
float depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;
// transform depth from <0; 1> value to corresponding point in projection space <-1,-1,0; 1,1,1>*
// * note that projection space in Vulkan is different than in OpenGL
vec3 normalized_device_coordinates = vec3(SCREEN_UV * 2.0 - 1.0, depth);
// move depth point from projection space to world space
// * note that INV_PROJECTION_MATRIX is broken atm. so, let's use inverse(PROJECTION_MATRIX)
vec4 world_position =
INV_VIEW_MATRIX * inverse(PROJECTION_MATRIX) * vec4(normalized_device_coordinates, 1.0);
world_position.xyz /= world_position.w;
CC @cybereality
I just lost some time debugging as well, but thankfully I found this by googling problems with orthogonal cameras instead of binary searching my shader code to find the issue (Which is quite hard to do since the only debug output you can make are colors).
I feel like INV_PROJECTION_MATRIX
being broken without explanation is a pretty major issue, orthogonal cameras are just broken for any water shaders that use it for depth. Or really, any shader that uses linear depth for any purpose not just water.
At the minimum can we get a more descriptive error? ("Do not use INV_PROJECTION_MATRIX with orthogonal cameras; use inverse(PROJECTION_MATRIX) instead"). But maybe that's harder to code than just fixing the issue, I'm not sure. For now, this bug without any warning / documentation is a bit rough.
Godot version
4.0.dev (84c404f6bc) and same for 4.0b4
System information
MacOS Monterey 12.0.1 Intel Iris Graphics 550 1536 MB
Issue description
When I'm trying to use VIEW_MATRIX transform to change world pos to view pos, it seems get not so correct data. Probably it's due to wrong scaling in .w part of matrix. I'm using orthogonal camera, but it will be the same for perspective
Steps to reproduce
void fragment() {
}
shader_type spatial; render_mode unshaded;
void fragment() {
}