New Tutorial: Custom Shaders

I’ve just added a new tutorial on how to write Custom Shaders for materials. Including a cool little dissolve effect.

Take a look:


I love you for this one, but it seems a little over my head…

1 Like

Shader programming can be a little funky, but once you understand the basics it’s not that hard to achieve what you want.

Start small with a little special effect material like the burn/dissolve shader above, then move on to bigger stuff.

This covers the real basics of shaders and the terminology: It’s designed for three.js but the concepts are the same as PlayCanvas.

I read the article still clueless…this concept is making me want to quit learning how to program and give up indie game design like I keep getting the impression that a lot of this stuff is supposed to be simple and Im just blow away by the ideas behind it so maybe its time to give up the dream…

I think its mainly because I dont get any time to sit and study any of these concepts anymore… its hard being a single dad working two jobs, and I still dont have enough money to feed myself, so Im thinking its time to stop trying to make games.

You mustn’t get disheartened by there being stuff you don’t understand. Especially stuff like shaders. I’ve been working the games industry for nearly 15 years and this is the first time I’ve ever written shader.

There are so many different areas of game development that it’s impossible to know it all. Which is why engines and tools like PlayCanvas exist! :smile: This stuff is only going to get easier and you will soon find you don’t need to understand complex shaders in order to get great effects.

When you’re doing this stuff in your free time the important thing is to work on the bits you enjoy.


that is great advice! I was going to say, Im starting to hate game development… but in reality there are parts of it i really do enjoy, the textures and shaders are not one of them though…

nor are particle systems… o_O

var shaderDefinition = {
    attributes: {
        aPosition: pc.gfx.SEMANTIC_POSITION,
        aUv0: pc.gfx.SEMANTIC_TEXCOORD0
    vshader: [
        "attribute vec3 aPosition;",
        "attribute vec2 aUv0;",
        "uniform mat4 matrix_model;",
        "uniform mat4 matrix_viewProjection;",
        "varying vec2 vUv0;",
        "void main(void)",
        "    vUv0 = aUv0;",
        "    gl_Position = matrix_viewProjection * matrix_model * vec4(aPosition, 1.0);",
    fshader: [
        "precision " + gd.precision + " float;",
        "varying vec2 vUv0;",
        "uniform sampler2D uDiffuseMap;",
        "uniform sampler2D uHeightMap;",
        "uniform float uTime;",
        "void main(void)",
        "    float height = texture2D(uHeightMap, vUv0).r;",
        "    vec4 color = texture2D(uDiffuseMap, vUv0);",
        "    if (height < uTime) {",
        "      discard;",
        "    }",
        "    if (height < (uTime+0.04)) {",
        "      color = vec4(0, 0.2, 1, 1.0);",
        "    }",
        "    gl_FragColor = color;",

can you put notes on this section please I understand the nomenclature now from reading the article but still some of the stuff reads as gibberish.

I’ve updated the tutorial with comments in the code.

Hope that helps.

1 Like

yes sir, you just connected the dots and Im sure that’s going to help a lot of us comprehend what was happening there.

Hope you don’t mind if I resurrect this old thread.

The tutorial says the following about uniform variables…
“The value of this variable must be passed into the shader from the main application”

So what is setting the uniform variables “matrix_model” and “matrix_viewProjection”? Are these automatically set by the platform? If so, are there any other automatically set variables that might be useful?

1 Like

That’s right, those uniforms are set in the forward renderer.

These are the other uniforms defined in pc.scene.ForwardRenderer in scene_forwardrenderer.js

    this.projId = scope.resolve('matrix_projection');
    this.viewId = scope.resolve('matrix_view');
    this.viewId3 = scope.resolve('matrix_view3');
    this.viewInvId = scope.resolve('matrix_viewInverse');
    this.viewProjId = scope.resolve('matrix_viewProjection');
    this.viewPosId = scope.resolve('view_position');
    this.nearClipId = scope.resolve('camera_near');
    this.farClipId = scope.resolve('camera_far');
    this.lightRadiusId = scope.resolve('light_radius');

    this.fogColorId = scope.resolve('fog_color');
    this.fogStartId = scope.resolve('fog_start');
    this.fogEndId = scope.resolve('fog_end');
    this.fogDensityId = scope.resolve('fog_density');

    this.modelMatrixId = scope.resolve('matrix_model');
    this.normalMatrixId = scope.resolve('matrix_normal');
    this.poseMatrixId = scope.resolve('matrix_pose[0]');
    this.boneTextureId = scope.resolve('texture_poseMap');
    this.boneTextureSizeId = scope.resolve('texture_poseMapSize');

    this.alphaTestId = scope.resolve('alpha_ref');
    this.shadowEnableId = scope.resolve('shadow_enable');
1 Like

Thanks very much! I’m trying to figure out how I might implement this shader in playcanvas. I’m not sure how to deal with the cubemap part. Any hints would be appreciated!

We’re about to launch a whole bunch of updates to our current shader system. Hopefully it will be released next week. This will include support for cubemap assets so you can created them in the editor from uploaded textures.

I wouldn’t normally recommend looking at this because it’s part of what we’re going to be replacing next week, but the staticcubemap_component.js has some code which creates a cubemap texture. pc.gfx.Texture is what you need to look at.

A post was split to a new topic: Does PlayCanvas support multiple materials on one mesh?

I am have written my own custom shader with the help of above tutorial but getting few errors. Please see - Getting Errors in my custom shader
Help me out of this please.