Kyle Richardson
Kyle Richardson

Reputation: 5645

Changing the opacity of a THREE.Mirror()

I'm pretty new to Three.js, and 3D in general, so please bear with me!

I'm trying to make a THREE.Mirror and change its opacity. I would think this would work, but unfortunately it does not, nor does any other solution I've tried thus far.

// inside init, render has no been called

// create a THREE.Mirror and add it to the provided THREE.Scene
function createMirror( props ) {
    let { name, width, height, options, scene } = props;

    this[ name ] = new THREE.Mirror( width, height, options );
    scene.add( this[ name ] );
}

// create 3js mirror and add to scene
createMirror.call( this, {
    name: "Mirror_1",
    width: 1.75,
    height: 1.75,
    options: {
        clipBias: 0.01,
        textureWidth: this.width,
        textureHeight: this.height,
        color: 0xefefef
    },
    scene: this.Main_Scene
} );
this.Mirror_1.rotation.x = -Math.PI / 2;
this.Mirror_1.material.opacity = 0.1;
this.Mirror_1.material.transparent = true;

// render is called inside an ObjectLoader after objects are loaded, here is 
// the render function

renderScene() {
    requestAnimationFrame( this.renderScene );

    this.P_Camera_1.lookAt( this.Main_Scene.position );
    this.controls.update();
    this.WebGL_Renderer_1.setViewport(0, 0, this.width, this.height);
    this.WebGL_Renderer_1.render( this.Main_Scene, this.P_Camera_1 );
}

Everything else works fine. Objects are loaded, scene renders beautifully, mirror looks great... just can't change it's opacity. Any help would be greatly appreciate. If this is not enough context, please let me know and I can provide more.

P.S. This is inside a React application. render() { ... } is a method on the component controlling the scene.

EDIT: I edited the fragmentShader portion of the Mirror.js provided in the examples\js portion of npm install three and written by @author Slayvin / http://slayvin.net.

var mirrorShader = {

    uniforms: {
        ...
    },

    vertexShader: [
        ...
    ].join( '\n' ),

    fragmentShader: [
        'uniform vec3 mirrorColor;',
        'uniform sampler2D mirrorSampler;',
        'varying vec4 mirrorCoord;',

        'float blendOverlay(float base, float blend) {',
        '   return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );',
        '}',

        'void main() {',
        '   vec4 color = texture2DProj(mirrorSampler, mirrorCoord);',


        // Changed the vec4(r, g, b, alpha) alpha from 1.0 to 0.25
        // No change in rendered THREE.Mirror


        '   color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b), 0.25);',
        '   gl_FragColor = color;',
        '}'
    ].join( '\n' )
}

I'm obviously missing something though!

Upvotes: 0

Views: 880

Answers (2)

misha11
misha11

Reputation: 1

add another geometry over mirror and set transparency for it

var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshLambertMaterial ( { opacity : 0.98 , transparent: true } ) );

Upvotes: 0

Kyle Richardson
Kyle Richardson

Reputation: 5645

For anyone wondering how to affect the opacity of a THREE.Mirror(), you need to do two things:

  1. Your_Mirror.material.transparent = true; Make sure this is done before the scene is rendered, or before the mirror is added to the scene and the fragmentShader has applied it's magic.

  2. Change the alpha in the fragmentShader used by the Your_Mirror.material.fragmentShader

Here is a solution I am using to change the opacity of a mirror dynamically.

const fragmentShaderBeforeAlpha = `
    uniform vec3 mirrorColor;
    uniform sampler2D mirrorSampler;
    varying vec4 mirrorCoord;

    float blendOverlay(float base, float blend) {
        return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
    }

    void main() {
        vec4 color = texture2DProj(mirrorSampler, mirrorCoord);
        color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b),
`;

const fragmentShaderAfterAlpha = `
    );
        gl_FragColor = color;
    }
`;

export default function fragmentShader( alpha ) {
    return fragmentShaderBeforeAlpha + alpha + fragmentShaderAfterAlpha;

}

Upvotes: 1

Related Questions