Shader pixel coordinates in 3d space

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By roflcopterDorrie

I am attempting to take a 2D shader and convert it to a spatial shader (using Godot 3.1).

For example, I am trying to use the second shader of The Book of Shaders: uniforms.

It is fairly straight forward and works fine in a canvas_item shader type

From:

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution;
    gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}

To:

shader_type canvas_item;
void fragment() {
    vec2 st = FRAGCOORD.xy/ (1.0/SCREEN_PIXEL_SIZE);
    COLOR.rgb = vec3(st.x, st.y, 0.0);
}

However, I can’t seem to do this same technique for a spatial shader because SCREEN_PIXEL doesn’t exist for spatial shaders.

What is the alternative to get the 0.0 to 1.0 version using FRAGCOORD for a spatial shader?

I have tried everything I can think of from Spatial shaders — Godot Engine (3.1) documentation in English with no luck.

I would have thought VIEWPORT_SIZE would be the spatial equivalent, but no luck, it turns out yellow all the way through.

shader_type spatial;
void fragment()
{
    vec2 st = FRAGCOORD.xy / VIEWPORT_SIZE;
    ALBEDO = vec3(st.x, st.y, 0.0);
}

Does anyone have ideas where I am going wrong?

In 3d, you normally apply shaders to surfaces. Surfaces are mapped to textures and often to shaders via UV coordinates (Vector2). Those are similar to screen coordinates amd typically go from 0 to 1. So a square face which should show the whole texture is mapped to UV 0,0 in one corner and 1,1 in the other corner. UVs are defined for each vertex ajd are available interpolated in the fragment shader. You typically map UVs to 3D objects in the 3D editor (i.e. Blender).

wombatstampede | 2019-03-23 20:20

:bust_in_silhouette: Reply From: wombatstampede

Here’s an example for a spatial shader:

shader_type spatial;

void fragment() {
    ALBEDO = vec3(UV.x, UV.y, 0.0);
}

Create a MeshInstance, select a CubeMesh and apply this shader as ShaderMaterial.

It will look similar to the shader in 2D but limited to the faces of the Cube.
You’ll have better control over the UV though when you i.e. edit the UVs of the mesh in a 3D editor.

There are many other possibilities though. Depending on how you want the shader to behave in your 3D world. You could as well use VERTEX.x, VERTEX.z when you want to use the (local) x/z coordinates as shader parameters instead of the UV. (You might have it to scale it down though.)

:bust_in_silhouette: Reply From: SIsilicon

Have you seen a variable called SCREEN_UV in the Godot docs? I’m pretty sure there’s what you’re looking for.

shader_type spatial;

void fragment() {
    ALBEDO = vec3(SCREEN_UV, 0.0);
}