Shader opacity based on z


I’m trying to write a shader which fades in and out at 2 different z values.

So step 1 I tried to get it to work with just z passing 0 but the result is the alpha channel of the image is black but the image is displayed.

Fragment shaders:

vec4 color = texture2D(uTexture, vUv);
gl_FragColor = vec4(color);

// Hidden as expected (but is there a command to exit program to prevent gpu use?)
gl_FragColor.a = 0.0;

// Expected 1/2 transparent, but instead alpha channel is black and all is 50% transparent
// gl_FragColor.a = 0.5;

// Expected texture to be displayed on plane with transparency intact,
// but transparent areas of texture are black and the image parts are displayed correctly
// gl_FragColor.a = 1;

// If I use gl_FragColor.a *= pow( gl_FragCoord.z, 50.0 );
// this fades with alpha channel correct but not sure on values of
// gl_FragCoord.z and what value pow() is returning and why
// is it a multiplier, wouldn't that take it far beyond a 0.0 to 1.0 range?

I was going to code something like this:

vec4 color = texture2D(uTexture, vUv);
gl_FragColor = vec4(color);

// hide anything that is over under z:-12
if (gl_FragCoord.z < -12.0){
    gl_FragColor.a = 0.0;
    // Is there some command to prevent render? or exit program? To optimise?

// fade in range
if (gl_FragCoord.z >= -12.0 && gl_FragCoord.z <= -10){
    // code to set opacity from -12.0 to -10.0

// fade out range
if (gl_FragCoord.z >= -1.0 && gl_FragCoor.z <= 0){
    // code to set opacity from -1.0 to 0.0

// hide after 0
if (gl_FragCoord.z > 0.0){
    gl_FragColor.a = 0.0;
    // Is there some command to prevent render? or exit program? To optimise?

I’m not clued up with shaders as you can see, anyone got any tips?


you can check this thread on discord

Its all greyed out.


you have to join the server 1st. but any way, there is a working shader example although the math is off

Yep that’s the last section of my comments in the 1st code sample, it odd that works but setting the alpha value directly from 0.0 to 1.0 breaks the transparency/alpha channel of the texture (png).

I will try injecting numbers into it in the morning and see if I can get actual values for what *= pow(val1,val2) is actually generating. Also that multiplier would mean it’s multiplier incrementing. Might see if I can re-construct it in JS so I can see what values are actually being generated in

gl_FragColor.a *= pow( gl_FragCoord.z, 50.0 );

So I can push the values into the shader for the alpha to work at 2 Z ranges (in and out). And then do it all in the shader itself.

and here is another useful link from the thread: opengl - How do I convert gl_FragCoord to a world space point in a fragment shader? - Stack Overflow

I’ve done a conversion on the original which uses vars bunny and kitty (lol), to z and a (pos, alpha value). No joy.

Will try a re-work of your 2nd links code shortly.

Here’s an attempt using the 2nd example and various others, still no luck. Passing a z of 0.0 should set the alpha to 1.0 and under 0.0 the alpha should be set to 0.5

I have the following code to get the current Z of the pixel? that I wish to evaluate for setting the alpha/opacity

vec4 ndc = vec4(
   (gl_FragCoord.x / screen_width - 0.5) * 2.0,
   (gl_FragCoord.y / screen_height - 0.5) * 2.0,
   (gl_FragCoord.z - 0.5) * 2.0, 1.0

vec4 clip = inverse_view_proj * ndc;
vec3 vertex = (clip / clip.w).xyz;

And this

float z = gl_FragCoord.z / gl_FragCoord.w;
vec3 test = vec3(0.0,0.0,(gl_FragCoord.z / gl_FragCoord.w));

I then tried to evaluate

  • ndc.z
  • clip.z
  • vertex.z
  • test.z


if (var.z >= 0.0) {
    a = 1.0 // set alpha to 1.0
} else {
    a = 0.5 // set alpha to 0.5


if (var.z >= 1.0) {
    a = 1.0 // set alpha to 1.0
} else {
    a = 0.5 // set alpha to 0.5

Results using >= 0.0:

  • ndc.z: a = 1.0 at all times
  • clip.z: a = 1.0 at all times
  • vertex.z: a = 0.5 at all times
  • test.z: a = 1.0 at all times (test.z appears to be around 5.0)

Results using >= 1.0:

  • ndc.z: a = 0.5 at all times
  • clip.z: a = 0.5 at all times
  • vertex.z: a = 0.5 at all times
  • test.z: a = 1.0 at all times

Which leads me to think that the way to get z for all of the above vars ndc, clip, vertex and test is incorrect, also it might suggest that z is not being adjusted when the mesh is being moved via mesh.position.z

This code is working when tested manually setting a

gl_FragColor = vec4( vec3( 1.0 ), a );

By playing with the if statement value, I found that test.z is around 5.0 and I can see a transition there but it never changes so can’t be used.

Anyone know the code to get the updating z of that pixel? point? vertex? on each run of the shader program? Is is possible or do I need to update a var in the shader in the render/animation loop for each plane I have?

or am I on the wrong mindset?


there are two ways to supply params:

  • attributes (these are unique per vertex)
  • uniforms (these are per draw call, uniform across all the vertices)

you can check three.js examples to see how to use both

I need more information on shaders, I need to buy a book on shaders or something before I can work this out…

I’ve posted it as a job on this forum: