World coordinate in fragment shader

Hello everyone!

I wonder is there a simple way to get a world coordinate into a fragment shader? Well, I think I could get the entity’s world transform matrix and pass it into the shader as uniform value. But is there anything simpler?

I am able to get a local pixel coordinate via attribute vec3 aPosition;, so maybe you have something built-in for world (global) position, that takes into account model’s world transform (position, rotation, scale) and could output pixel’s world coordinate (so cube center on the picture below is [0, 1.25, 0] instead of [0, 0, 0] that I am getting from aPosition)?

Thanks!

P.S. I am completely new to GLSL and shaders :slight_smile:

Hi @Igor,

If you are working with shader chunks what you are looking for is dPositionW.

1 Like

Thank you for the answer @Leonidas!

Another noob question: how to access dPositionW from my custom frag (or vert) shader? I see it’s returned in getWorldPosition(), but trying to call it I get an error:
image

image

So I don’t think you need to do anything at all, just use the dPositionW variable wherever is required.

Example diffuse color that changes based on the pixel distance from world ZERO:

    float distance = distance(vPositionW, vec3(0.0));
    dAlbedo *= 1.0 - clamp(distance/ 10.0, 0.0, 1.0);

Edit: sorry I’ve just seen you use a custom shader, in that case that would be different, you need to calculate that value yourself in the vertex shader and pass it as varying to the pixel shader.

Here is a stackoverflow on how to do that in GLSL:

Hey, I attempt the same thing and followed the stackoverflow thread. From what I can discern there is by default a built in variable in OpenGL called “gl_Vertex” which (if I understand correctly) can be used to multiply with the “matrix_model” variable to acquire the world positions of the fragments.

However, when I use the gl_Vertex variable name in my custom vertex shader, I get the error message:
“‘gl_Vertex’: undeclared identifier”

Is the value of gl_Vertex accessible through another variable name in Playcanvas? i.e. the
Vertex’s world-space coordinate.

Hi @Astra,

If you are using a pixel shader chunk, the world position of the pixel is available like this:

// vec3
vPositionW

So, I think I figured it out.

‘gl_Vertex’ is what would correspond to ‘vec4(aPosition, 1.0)’ where aPosition is an attribute variable passed from a javascript with the value ‘pc.gfx.SEMANTIC_POSITION’

In other words to write a custom GLSL shader in Playcanvas where you can access the fragments world position in the fragment shader, your Vertex shader should look something like this:

attribute vec3 aPosition;
attribute vec2 aUv0;

uniform mat4 matrix_model;
uniform mat4 matrix_viewProjection;

varying vec2 vUv0;
varying vec4 worldPos;

void main(void)
{
    vUv0 = aUv0;

    worldPos = matrix_model * vec4(aPosition, 1.0);
    gl_Position = matrix_viewProjection * worldPos;
}

Where ‘worldPos’ is a Vec4 representing the world coordinates, and can be used in the fragment shader like this for instance:

varying vec2 vUv0;
varying vec4 worldPos;

void main(void)

{
    gl_FragColor = worldPos;
}

In the Javascript the shader declaration would then look something like this:

// Create the shader definition 
    // dynamically set the precision depending on device.
    var gd = this.app.graphicsDevice;
    var fragmentShader = "precision " + gd.precision + " float;\n";
    fragmentShader = fragmentShader + this.fs.resource;
    
    var vertexShader = this.vs.resource;

    // A shader definition used to create a new shader.
    var shaderDefinition = {
        attributes: {           
            aPosition: pc.gfx.SEMANTIC_POSITION,
            aUv0: pc.SEMANTIC_TEXCOORD0,
        },
        vshader: vertexShader,
        fshader: fragmentShader
    };
    
    // Create the shader from the definition
    this.shader = new pc.Shader(gd, shaderDefinition);
1 Like

k, thx!
was looking for custom shader solution, but will keep that in mind for other projects :slight_smile:

1 Like

Thanks for sharing your full solution with the varying!