Varying `v_uv` has static-use in the frag shader, but is undeclared in the vert shader

I am trying to add a postProcess step to a shader to pass uniforms such as iTime to the fragment shader. The shader works fine until I add the following call to PostProcess:

        const postEffect = new BABYLON.PostProcess("post process for customEffect",
            "customEffect",
            ["iTime", "iResolution"],
            [], 1, camera);

At which point it errors with Varying `v_uv` has static-use in the frag shader, but is undeclared in the vert shader. The vertexShader code is:

    attribute vec2 uv;
    attribute vec3 position; 

    uniform mat4 worldViewProjection;

    varying vec2 v_uv;

    void main() {
        v_uv = uv;
        gl_Position = worldViewProjection * vec4(position, 1.0);
    }

And the fragmentShader code is:

    precision highp float;

    uniform float iTime;
    uniform vec2 iResolution;

    varying vec2 v_uv;

    void main(void) {
        gl_FragColor = vec4(v_uv, 0.0, 1.0);
    }

Playground: https://playground.babylonjs.com/#VG25E8#11 (set conditional on line 33 to true to trigger error and check logs to see error)

Alternatively I can add the postProcess step if I replace the reference to v_uv with literal floats e.g. gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);


I tried searching the playgrounds for a similar error but I think I 500’d the snippets server :grimacing:

I also tried looking at page in the docs on Putting Shader Code Into Babylon.js and on Custom postprocesses | Use Post Processes for a solution or working example but couldn’t see one?

Thanks!

* edit * fixed playground, had old shader cache locally but wasn’t correct name in playground.

The post process class is using a default vertex fragment which is using a uv variable named vUV, not v_uv. So you must use this name in your shader:

Note that you can use your own vertex shader with a post process by giving a value to the 11th parameter, but your existing vertex shader won’t work because the post process class is drawing a full screen 2D quad and the “position” attribute reflects that (it directly passes vertices for a triangle in the NDC coordinate system). The default vertex shader used by the post process class is:

attribute vec2 position;

uniform vec2 scale;

varying vec2 vUV;

const vec2 madd = vec2(0.5, 0.5);

void main(void) {
	vUV = (position * madd + madd) * scale;
	gl_Position = vec4(position, 0.0, 1.0);
}
3 Likes

A quick follow up for those looking for vUV in the documentation. It’s under the section “Introduction To Shaders → Running Shader Code” which shows vUV being set by the vertex shader and passed to the fragment shader.

And this playground shows an example of a custom shader applied to a custom mesh (no postprocess step required) https://playground.babylonjs.com/#VG25E8#19

Thanks to @Evgeni_Popov for pointing out the postProcess interacts with the whole screen so that my previous approach was not going to work. And to this page for showing me how to set uniforms for a material’s custom shader: Passing Uniforms to your custom Babylon.js shader. Where's my u_resolution? - Big Tex Hog Tech Blog and I now see that the material.setFloat("abc", 1.0) is documented towards the bottom of this page: Shader Material | Babylon.js Documentation

PostProcessing step is blurry but solving that’s for another time / another question.

Video from version #17 of the playground where the custom mesh was a simple plane (and no postprocessing was applied):

2 Likes