[SOLVED] Standard material shader

How do I make pc.StandardMaterial to use a supplied shader? For example, the following will work fine wtih the base pc.Material:

var shader = new pc.Shader(device, shaderDefinition);
var material = new pc.Material();
material.shader = shader;

It will use the vertex and fragment shaders I feed it. However, I want to use pc.StandardMaterial, instead of its base class, so I can use the hardware instancing.

Unfortunately, it doesn’t work if I use the following:

var shader = new pc.Shader(device, shaderDefinition);
var material = new pc.StandardMaterial();
material.shader = shader;
material.update();

It doesn’t use the shader I give it. Instead, it uses a default one. What would be the correct way?

Hi @LeXXik,

I think with the pc.StandardMaterial you can only override parts of the shader (chunks), adding custom shader code of your own.

The complete shader is getting generated automatically here, on material.update(), depending on the enabled/used material slots and settings:

1 Like

Hi, @Leonidas!

Thank you for the answer! I was hoping I could use the inherited .shader property. I don’t mind using the chunks, but if I am correct, the shader definition is also auto generated with the chunks. As such, I cannot map custom attributes to semantics. I can only use the existing ones, like vertex_position, etc. Unless there is some way to update the shader definition?

You could definitely monkey patch the pc.StandardMaterial class for that or create a new material program for that, though I am fairly certain there may be a more elegant way.

Not sure who to invoke @yaustar for this, maybe @mvaligursky? Hope I am ringing the right bells :innocent:

1 Like

@ray would be your best bet for this week.

@mvaligursky has recently worked with vertex attributes so would know more (he is on holiday this week) - but I did come across a good example project showing how to use custom shaders and shader chunks (both vertex and fragment) with the Standard material: https://playcanvas.com/project/489836/overview/toon-shader-with-skinning

4 Likes

Thank you, @ray! This is a good example, indeed. I guess I can rely on uniforms, instead of attributes then.

I will add a simple excerpt here for reference and mark this as solved. @mvaligursky, enjoy your holiday! and feel free to comment after you are back, if you have anything to add.

// ------- startVS chunk -----------
uniform float u_PointSize;

void main(void) {
    gl_PointSize = u_PointSize;
    gl_Position = getPosition();
// ------- startVS chunk -----------



// script js, mesh generation is omited for brevity
var material = new pc.StandardMaterial();
var startVS = this.startVS.resource;  // startVS chunk
material.chunks.startVS = startVS;
material.update();

var meshInstance = new pc.MeshInstance(node, mesh, material);
meshInstance.setParameter('u_PointSize', 2);

var model = new pc.Model();
model.graph = node;
model.meshInstances = [ meshInstance ];
1 Like

Hi @LeXXik - I’m not entirely sure what’s your goal here exactly, it seems you want to maybe pass some additional per instance parameters (like color for example) to shader to render meshes using instancing?

If yes, this should work. See this instancing example source code:
http://playcanvas.github.io/#graphics/hardware-instancing.html

It creates additional VertexBuffer, which stores per instance data. VertexFormat it uses in that example allows storing 4 x float4 (so a matrix), but you can create custom format to provide additional data such as color. Then you’d need to use custom shader chunks to use the data, similar way the current instancing matrix is used.

2 Likes