Transparency texture display incorrectly

issue
i create a mesh with transparency texture over the ground. but when i move the mesh , the transparent part of the texture changed to background color of the scene in some where. how to solve this problem? am i missing some configuration here?
code of render:
this.renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
logarithmicDepthBuffer: true,
});
code of texture:
let material = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
color: 0xFFFFFF,
map: new THREE.TextureLoader().load(_background),
transparent: true,
opacity: 1,
});

Hi!
The less you use transparency, the less headache you get :thinking:
As an option, use uv coordinates of intersection to draw a circle right on a plane
Example: Edit fiddle - JSFiddle - Code Playground
Picture:

2 Likes

you are right. but i still want to know how this happen. it’s really weird. i got this issue in other situation as well. that’s why i have to figgure it out.

As I’ve started to look a little deeper into shaders, this topic has come to mind.

Using @prisoner849’ s solution, I created a partially transparent plane and a mouse-movable circle as THREE.ShaderMaterial.

ShaderExamples_07

UPDATE: Optimized the code a bit. There were unnecessary lines about uniforms. If necessary please copy it again.

2021-11-29 15.25.32

Since I’m not very familiar with shaders yet, I don’t know if one can use THREE.ShaderMaterial to solve the original problem in the post.



<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/transparency-texture-display-incorrectly/29793/2 -->
<head>
  <title> ShaderExamples_07 </title>
  <meta charset="utf-8" />
  <style>
    body {
        overflow:hidden;
        margin: 0;
    }
  </style>
</head>

<body> </body>

<script type="module">

// @author hofk ( based on https://jsfiddle.net/prisoner849/5c9n3zsd/ @author prisoner849 )
 
import * as THREE from '../jsm/three.module.135.js';
import {OrbitControls} from '../jsm/OrbitControls.135.js';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 65, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set( -5, 1, 5 );

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xfefefe );
document.body.appendChild( renderer.domElement );

const controls = new OrbitControls( camera, renderer.domElement );

const circleGeometry = new THREE.CircleBufferGeometry( 4, 64 );
const circleMesh = new THREE.Mesh( circleGeometry, new THREE.MeshBasicMaterial( { color: 0xff0000 } ) );
circleMesh.position.z = -4.0;
scene.add( circleMesh );

const planeWidth =  5;
const planeHeight = 4;
  
const shaderMaterial = new THREE.ShaderMaterial( {

    uniforms: { 
            v_Uv: { value: new THREE.Vector2( ) },
            planeMouseUv: { value: new THREE.Vector2( ) },
            planeAspect: { value: new THREE.Vector2( planeWidth, planeHeight ) }
    },
    vertexShader: vertexShader( ), 
    fragmentShader: fragmentShader( ),
    side: THREE.DoubleSide,
    transparent: true,
    
} );

const planeGeometry = new THREE.PlaneBufferGeometry( planeWidth, planeHeight );
const planeMesh = new THREE.Mesh( planeGeometry, shaderMaterial );

scene.add( planeMesh );

let mouse = new THREE.Vector2( );
let raycaster = new THREE.Raycaster( );
let intersects = [];

window.addEventListener( "pointermove",  onPointerMove );  
window.addEventListener( "resize", onWindowResize);

animate( );

function animate( ) {

    requestAnimationFrame( animate );   
    renderer.render( scene, camera );

}

function onPointerMove( ) { 
    
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    
    raycaster.setFromCamera( mouse, camera );
    intersects = raycaster.intersectObject( planeMesh );
     
    if( intersects.length > 0 ) shaderMaterial.uniforms.planeMouseUv.value.copy( intersects[0].uv );
    
}

function onWindowResize( ) {

  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix( );
  renderer.setSize( innerWidth, innerHeight );

}

function vertexShader ( ) { //   return `    `;   a multiline template literal
    
    return `
        varying vec2 v_Uv;
        uniform vec2 planeMouseUv;
        uniform vec2 planeAspect;
        
        void main( )    {

                v_Uv = uv;
                vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
                gl_Position = projectionMatrix * mvPosition;
            
        } 
    `;
    
}

function fragmentShader( ) { //   return `    `;   a multiline template literal 
    
    return `       
        varying vec2 v_Uv;
        uniform vec2 planeMouseUv;
        uniform vec2 planeAspect;
        
        void main( ) {
            
            // borders
            float left = smoothstep( 0.00, 0.05, v_Uv.x );
            float right = 1.0 - step( 0.98, v_Uv.x );
            float top = 1.0 - step( 0.66, v_Uv.y );
            float bottom = smoothstep( 0.00,0.05, v_Uv.y );    
            
            vec3 color = vec3( left * right * top * bottom );
            
            // moving circle
            vec2 aspect = vec2( planeAspect.x / planeAspect.y, 1.0 );
            vec2 pUv = v_Uv * aspect;
            vec2 mUv = planeMouseUv * aspect;
            
            float dist = distance( pUv, mUv ) * planeAspect.y; // plane's height is the base
            float radius = 0.07;
            float thickness = 0.02;
            
            float circ =  step( radius, dist ) - step( radius + thickness, dist );
            
            color = color * vec3( v_Uv.x, v_Uv.x, v_Uv.y );
            
            gl_FragColor = vec4( color, sqrt( v_Uv.y ) );
             
            gl_FragColor.rgb = mix( gl_FragColor.rgb, vec3( 0.2, 1.0, 0.4 ), circ );
            
        }
    `;
}

</script>
</html>