• Godot HelpShaders
  • [Solution in comments!] Billboard texture shader warping at edges of screen

I'm trying to display a texture at the center of a mesh but the scaling isn't quite right: Can someone explain what I'm doing wrong? I've tried everything I can think of, including several transform combinations. Below you may find a zip containing the visual shader. Thanks!

notice that the AABB(bounding box drawn by godot editor) is distorting the same way.

@Megalomaniak said: notice that the AABB(bounding box drawn by godot editor) is distorting the same way.

Same as the mesh, yes, but not the texture.. Here's another GIF that demonstrates what the shader should be doing:

Ah, I thought the texture scaling was intentional. Still, I suspect it the result of that cross product, which may be redundant anyways. I'm guessing you are trying to follow some generic openGL/glsl tutorial and you aren't accounting for the fact that some of the things done there godot already does for you.

@Megalomaniak said: Ah, I thought the texture scaling was intentional. Still, I suspect it the result of that cross product, which may be redundant anyways. I'm guessing you are trying to follow some generic openGL/glsl tutorial and you aren't accounting for the fact that some of the things done there godot already does for you.

No other visual shader node combinations that I had tested came as close to being correct as that one did. Removing the cross product yields this effect: Do you have any suggestions or resources I may follow with regards to this scenario?

I'll take a closer look at this when I'm at my workstation.

Billboards in the spatial shader are experiencing the same too.

anyways, returning to my original diagnosis:

Viewport fov 15:

Viewport fov 70(default, and zoomed in to compensate):

edit: Looking at the op again, you could try to use normalize vectorfunc instead of the divide?

Eh, honestly this is just giving me a headache now.

To the best that I can tell you are perceiving it as a texture mapping issue where as the mesh is still affected by the fov/lens distortion, in the screenshot screencapture in your opening post if you pay attention the sphere is getting stretched horizontally while because of your shader the texture is scaled uniformly along both axis thus the top and bottom get cut off.

@Megalomaniak said: Eh, honestly this is just giving me a headache now.

To the best that I can tell you are perceiving it as a texture mapping issue where as the mesh is still affected by the fov/lens distortion, in the screenshot screencapture in your opening post if you pay attention the sphere is getting stretched horizontally while because of your shader the texture is scaled uniformly along both axis thus the top and bottom get cut off.

OK, then perhaps the issue stems from the use of the view input / cross product. I'm still attempting fixes.

Yes, that is likely, the coordinates and how warped they are is pretty evident in that image too, it is that view space that you'd likely want to correct, but not just for the one shader material but probably for your whole scene render, hence my original link in my first reply.

Simple solution might be to just render your scene to a viewport(rendertarget) and apply a counter warp to it.

Once you have successfully corrected that you might find it much easier to achieve your actual goal here which I'm guessing is to get a billboard shader that tracks the camera outputs center more closely?

One fair point on that note, should you try to utilize that in XR or any form of stereoscopy it will be problematic: each eye would have it's own dedicated camera/view and be offset from the other.

Not that any sort of billboard would work well in that situation, tbf.

Maybe if you use the camera's view direction instead of the default VIEW variable. I don't know. I'm just brainstorming here. It can just be a constant vec3(0, -1, 0), which is the camera vector in view space.

@Megalomaniak That would work, although I'm not favorable of affecting the whole scene. If there's no other solutions, I'm just going to give up and use a script for a similar result.

Well, you can try to modify the view vector but I doubt it is going to give you perfectly satisfying results. If you did both though..?

5 months later

SOLVED! Discovered a solution by mere chance:

mat4 makeRotationDir(vec3 direction, vec3 up)
{
    vec3 xaxis = normalize(cross(up, direction));
    vec3 yaxis = normalize(cross(direction, xaxis));
    mat4 mat;
    mat[0].x = xaxis.x;
    mat[0].y = yaxis.x;
    mat[0].z = direction.x;
    mat[1].x = xaxis.y;
    mat[1].y = yaxis.y;
    mat[1].z = direction.y;
    mat[2].x = xaxis.z;
    mat[2].y = yaxis.z;
    mat[2].z = direction.z;
    return mat;
}

...

vec3 direction = (CAMERA_MATRIX * vec4(VERTEX, 0.0)).xyz;
vec3 up = (CAMERA_MATRIX * vec4(0.0, 1.0, 0.0, 0.0)).xyz;
vec3 view = (makeRotationDir(direction, up) * CAMERA_MATRIX * vec4(NORMAL, 0.0)).xyz;
vec2 uv = 0.5 - view.xy * vec2(0.5);
vec4 color = texture(matcap_texture, uv);
2 years later