[SOLVED] Extending a shader

I have a fairly simple shader that I’ve written, but I want it to have all the lighting/specular, etc

The shader I’ve written takes a mask with using the Red and Blue channels to replace the red with another texture and the blue with 1 colour and the rest is a 2nd colour, which is done like:

void main(void)
{
    vec4 maskTex = texture2D(mask, TexCoordOut);
    
    vec4 faceImageTex = texture2D(faceImage, TexCoordOut);
    vec4 ballColor = vec4(ballcolour_r, ballcolour_g, ballcolour_b, 1);
    vec4 lineColor = vec4(linecolour_r, linecolour_g, linecolour_b, 1);
    
    gl_FragColor = (mix( mix( mix( ballColor, faceImageTex, maskTex.r), lineColor, maskTex.g), lineColor, maskTex.b));
}

While the shader does the colour replace that I want, its obviously unlit/no specular on it. Is it possible to extend the existing physical shader to add this in?

thanks

Yes, it’s possible. You can replace the diffuse map shader chunk.

Create a shader asset with code like:

uniform sampler2D mask;
uniform sampler2D faceImage;
uniform vec4 ballcolour_r;
uniform vec4 ballcolour_g;
uniform vec4 ballcolour_b;
uniform vec4 lineColor;

void getAlbedo(inout psInternalData data) {
    vec4 maskTex = texture2D(mask, $UV);
    
    vec4 faceImageTex = texture2D(faceImage, $UV);
    vec4 ballColor = vec4(ballcolour_r, ballcolour_g, ballcolour_b, 1);
    vec4 lineColor = vec4(linecolour_r, linecolour_g, linecolour_b, 1);
    
    data.albedo = (mix( mix( mix( ballColor, faceImageTex, maskTex.r), lineColor, maskTex.g), lineColor, maskTex.b)).rgb;
}

Use standard physical material with a diffuse map and then patch it via script:

material.chunks.diffuseTexPS = app.assets.find("name of your shader asset").resource;
material.update();
1 Like

Thank you for the quick reply, I’ve just tried what you said and its not throwing any errors, but it doesn’t show my texture on the ball, just the standard white physical shader.

uniform sampler2D faceImage;
uniform sampler2D mask;

uniform float linecolour_r;
uniform float linecolour_g;
uniform float linecolour_b;

uniform float ballcolour_r;
uniform float ballcolour_g;
uniform float ballcolour_b;

void getAlbedo(inout psInternalData data)
{
    vec4 maskTex = texture2D(mask, $UV);
    
    vec4 faceImageTex = texture2D(faceImage, $UV);
    vec4 ballColor = vec4(ballcolour_r, ballcolour_g, ballcolour_b, 1);
    vec4 lineColor = vec4(linecolour_r, linecolour_g, linecolour_b, 1);
    
    data.albedo = (mix( mix( mix( ballColor, faceImageTex, maskTex.r), lineColor, maskTex.g), lineColor, maskTex.b)).rgb;
}

and in my script, I configure it like so:

pc.script.attribute("fs", "asset", null, {displayName: "Mask Shader", type: "shader", max:1});
pc.script.attribute("mask", "asset", null, {displayName: 'Mask', type: 'texture', max: 1});
pc.script.attribute("face", "asset", null, {displayName: 'Face', type: 'texture', max: 1});
pc.script.attribute("linecolor", "rgba", null, {displayName: 'Line Colour', type: 'rgba', max: 1});
pc.script.attribute("ballcolor", "rgba", null, {displayName: 'Ball Colour', type: 'rgba', max: 1});
...
    initialize: function () {
       var model = this.entity.model.model;
       var maskTexture = app.assets.get(this.mask).resource;
       var faceTexture = app.assets.get(this.face).resource;     
       var fragmentShader = app.assets.get(this.fs).resource;
            
       model.meshInstances[0].material.chunks.diffuseTexPS = fragmentShader
             
       model.meshInstances[0].material.setParameter("mask", maskTexture);
       model.meshInstances[0].material.setParameter("faceImage", faceTexture);
       model.meshInstances[0].material.setParameter("ballcolour_r", this.ballcolor.r);
       model.meshInstances[0].material.setParameter("ballcolour_g", this.ballcolor.g);
       model.meshInstances[0].material.setParameter("ballcolour_b", this.ballcolor.b);

       model.meshInstances[0].material.setParameter("linecolour_r", this.linecolor.r);
       model.meshInstances[0].material.setParameter("linecolour_g", this.linecolor.g);
       model.meshInstances[0].material.setParameter("linecolour_b", this.linecolor.b);
       model.meshInstances[0].material.update();               
 }
1 Like

Ah, my fault - I hadn’t set a texture for diffuse, doh!

Wonderful, thats working now. Thank you again

Heads up for anyone visiting this thread in 2020, it looks like some things have changed since:

material.chunks.diffuseTexPS is now material.chunks.diffusePS

void getAlbedo(inout psInternalData data) { is now: void getAlbedo() {

instead of using the data.albedo param, the dAlbedo global should be used, for example:
void getAlbedo() { dAlbedo = new albedo value; }

2 Likes