[SOLVED] Fresnel shader not working for opacity

I have a basic fresnel shader setup, which I am using successfully on the emissive channel of materials, but I can’t get it to work on the opacity of a material.

Here is an example scene: https://playcanvas.com/editor/scene/1094535

The look of the sphere on the left shows what I want the opacity to be doing - essentially becoming transparent as the normals face away from the camera view direction.

I’m able to set a constant opacity using something simple like this:

void getOpacity() {
    dAlpha = 0.5;

So I’m definitely using the right chunk, but I feel like there must be some reason the opacity channel is not able to use the fresnel calculation.

Anyone have any ideas?

I recommend to install spector js (as chrome plugin), capture the scene and inspect it.

I see that on the sphere, the alpha blending it set up correctly, but something is not right with the chunk. I see the shaders has this chunk it in:

void getOpacity() {
    dAlpha = 1.0;
    #ifdef MAPFLOAT
        dAlpha *= material_opacity;
    #ifdef MAPTEXTURE
        dAlpha *= texture2D(texture_opacityMap, UV).CH;
    #ifdef MAPVERTEX
        dAlpha *= clamp(vVertexColor.VC, 0.0, 1.0);
1 Like

Interesting, I wouldn’t have thought I would need to replicate all those conditionals (if that’s what you’re saying) because it seems like all getOpacity needs to do is alter the dAlpha value. Indeed, the simple version I posted totally works, just setting a constant value to dAlpha. So I’m still not sure why trying to set the value in a more complicated way would be any different…
I’ll try out Spector as you suggest though, when I get a chance, thanks!

OK, I figured it out. The way it was behaving would only really make sense if somehow the view direction and normal weren’t set up correctly, and sure enough, the main function in the PS shader has these lines:


So the opacity is calculated before the view direction and normal. So here is my working code, which unfortunately means I need to calculate the normal and view again, but it works.

void getOpacity() {
    vec3 view = normalize(view_position - vPositionW);
    vec3 normal = normalize(dVertexNormalW);
    float fresnel =  dot(normal, view);
    dAlpha = mix(0.0, 1.0, pow(clamp(fresnel, 0.0, 1.0), 8.0));

(Not sure how to mark this as solved…?)