Adding transparency to shader toy shader

Against all odds, I’ve managed to port a shader toy shader of a star into three.js. It is a thing of spectacular beauty. You will find the shader toy shader here. I’ve cut it down to make it a bit more light weight, and I’m rendering it to a plane geometry and it all works super fine; using Object3D.lookAt I’m able to get it to always face the camera. There’s just this one issue, though… It’s not transparent, as you can see in the attached image.

I would like the orange glow that covers the plane geometry to be transparent so that you would just see the sphere of the sun and then the corona and the rest would be the background and whatever is in the field of view. It seems so simple but after a lot of wrangling I haven’t been able to get it to work… So help, please :angel:?

P.S. Thanks to the people behind https://threejsfundamentals.org/ for the article on converting shader toy shaders to three.js; couldn’t have done it without you guys!!!

See the command fragColor.a = 1.0; on line 94? You’re going to have to figure out how to fade that alpha value out to 0 once you’re outside the star. You could do a simple distance calculation to the center, but you can probably use some of the flare calculations to your advantage.

Then don’t forget to add material.transparent = true to your ShaderMaterial in JavaScript.

4 Likes

That did it!!!

Thank you very much!

Now I’m going to make the color of the star dependent on a temperature uniform… :sun_with_face:

Hola!

This is a long shot, but I’ll give it a try anyway. I would love to know how you enabled transparency in the end?

I ported one simple shader from ShaderToy, and now I want to do the exact same thing regarding transparency.

I could say that I get how all of this works, but lacking the skills to figure out the calculations for being outside of the star etc.

This is the ShaderToy example I am using and here is the code to port it to threejs :

Vertex

  varying vec2 vUv;
    void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }

Fragment

varying vec2 vUv;
uniform vec3 iResolution;
uniform float iTime;

float cheap_star(vec2 uv, float anim)
{
    uv = abs(uv);
    vec2 pos = min(uv.xy/uv.yx, anim);
    float p = (2.0 - pos.x - pos.y);
    return (2.0+p*(p*p-1.5)) / (uv.x+uv.y);      
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = ( fragCoord - .5*iResolution.xy ) / iResolution.y;
    uv *= 2.0 * ( cos(iTime * 2.0) -2.5);
    
    // anim between 0.9 - 1.1
    float anim = sin(iTime * 12.0) * 0.1 + 1.0;    

    fragColor = vec4(cheap_star(uv,anim) * vec3(0.35,0.2,0.15), 1.0);
}

  void main(){
        mainImage(gl_FragColor, vUv * iResolution.xy);
    }

Shader Material

class ShaderToyMaterial extends ShaderMaterial {
  constructor(){
    super({
        transparent: true,
        side: THREE.DoubleSide,
        uniforms: {
            iTime: { value: 0 },
            iResolution: { value: new THREE.Vector2(1200, 675) }
          },
          vertexShader,
          fragmentShader
    })
  }
}

Init / anim

const planeGeometry = new THREE.PlaneGeometry(12, 6.75)
const shaderToyMaterial = new ShaderToyMaterial()
shaderToyMaterial.uniforms.iResolution.value.set(1200, 675)
engine.animate = (delta, total) => {
// render loop anim
shaderToyMaterial.uniforms.iTime.value = performance.now() / 1000
}