admin管理员组

文章数量:1384613

I'm trying to build a shader that will perform some post processing based on some entities that exist in the world space...

I went through some theory and tried to apply the knowledge I gathered but there are a lot of unknowns there for me and being relatively new to Godot (Godot 4), despite trying hard, I cannot pin down what I'm doing wrong and am having hard time visualizing where exactly things go haywire...

I tried to take a few steps back so that at least I would know I have the basics right and I'm also running into some issues...

so, here I am - this is the shader where I'm trying to produce a debug pattern that would suggest that I'm on the correct course but it's still wrong though somewhat on the right track, I guess...

shader_type canvas_item;

uniform mat4 camera_projection;
uniform mat4 camera_transform;

void fragment() {    
    vec4 clip_pos = vec4(UV.x * 2.0 - 1.0, 0.0, -(UV.y * 2.0 - 1.0), 1.0);
    vec4 view_pos = inverse(camera_projection) * clip_pos;
    view_pos /= view_pos.w;
    
    vec4 world_pos = inverse(camera_transform) * view_pos;
    
    COLOR = vec4(abs(fract(world_pos.xyz * 0.1)), 1.0);
}

and this is the gdscript piece that supplies the parameters to the shader


    var camera_projection = main_camera.get_camera_projection()
    material.set_shader_parameter("camera_projection", camera_projection)
    var camera_transform = main_camera.global_transform
    material.set_shader_parameter("camera_transform", camera_transform)

generally, my understanding is that clip_pos should use XY coordinates but when I do it that way, it looks even less sensible...

what I'm aiming to do is to have the XY screen coords mapped to world's XZ coords ... so I'm assuming that if I got this right, I would expect the displayed grid to align with the world coordinates and the rotations, translations and zoom to be reflected in the pattern the same way as it is on a "real" object there. but as it is, they're very much off...

EDIT: got it working (so I thought I'd share the correct solution):

shader_type canvas_item;

uniform mat4 camera_projection;
uniform mat4 camera_transform;
uniform float ground_height = 0.0;

void fragment() {
    vec4 clip_pos = vec4(UV * 2.0 - 1.0, 0.0, 1.0);
    clip_pos.y *= -1.0; // !!! Y-up/Y-down conversion
    vec4 view_pos = inverse(camera_projection) * clip_pos;
    view_pos /= view_pos.w;

    vec4 world_pos = camera_transform * view_pos; // !!! not inversed

    vec3 ray_origin = camera_transform[3].xyz;

    vec3 ray_dir = normalize(world_pos.xyz - ray_origin);

    float t = (ground_height - ray_origin.y) / ray_dir.y;
    vec3 intersection = ray_origin + t * ray_dir;

    vec3 color = fract(intersection);
    COLOR = vec4(color.r, 0.0, color.b, 1.0);
}

本文标签: graphicsmapping screen space to world space in a Godot shaderStack Overflow