Creating custom transparency effects in Three JS using ShaderMaterial

When drawing two geometries next to each other and having them rotate, a common issue arises. The first drawn geometry obstructs the second one where transparency should be applied uniformly. Both objects should exhibit the same level of transparency regardless of their drawing order. To address this, blending is enabled while depth testing is disabled. Here are images displaying the problem:

Both geometries consist of point clouds using THREE.ShaderMaterial with the following setup:

var shaderMaterial = new THREE.ShaderMaterial({
                uniforms: uniforms,
                attributes: attributes,
                vertexShader: document.getElementById('vertexshader').textContent,
                fragmentShader: document.getElementById('fragmentshader').textContent,
                blending: THREE.NormalBlending,
                depthTest: false,
                transparent: true
            });

where

// attributes
attributes = {
                size: { type: 'f', value: null },
                alpha: { type: 'f', value: [] },
                customColor: { type: 'c', value: null }
            };

 // uniforms
uniforms = {
             color: { type: "c", value: new THREE.Color(0x00ff00) },
             texture: { type: "t", value: THREE.ImageUtils.loadTexture("../textures/sprites/circle.png") }
            };

and

<script type="x-shader/x-vertex" id="vertexshader">
        attribute float alpha;
        attribute float size;
        attribute vec3 customColor;        
        varying float vAlpha;
        varying vec3 vColor;
        void main() {
        vAlpha = alpha;
        vColor = customColor;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_PointSize =  size * ( 120.0 / length( mvPosition.xyz ));
        gl_Position = projectionMatrix * mvPosition;
        }
    </script>
<script type="x-shader/x-fragment" id="fragmentshader">
        uniform vec3 color;
        uniform sampler2D texture;
        varying float vAlpha;
        varying vec3 vColor;
        void main() {
        gl_FragColor = vec4( vColor, vAlpha );
        gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
        }
    </script>

Answer №1

Below is a sample code that demonstrates the use of 2 textures, but can also be adjusted to work with just one:

<script id="fragmentShaderLoader" type="x-shader/x-fragment">
        uniform float percentage;

        uniform sampler2D tex1;
        uniform sampler2D tex2;

        varying vec2 uvCoord;

        void main() {
            gl_FragColor = texture2D(tex1, uvCoord);
            vec4 texture2Data = texture2D(tex2, uvCoord);
            
            if (texture2Data.a - percentage < 0.0) {
                gl_FragColor.a = 0.0;
                // Alternatively, you may use 'discard;' instead of making it transparent
            }
        }

</script>

<script id="vertexShaderLoader" type="x-shader/x-vertex">
    varying vec2 uvCoord;

    void main()
    {
        uvCoord = uv;

        vec4 modelViewPos = modelViewMatrix * vec4(position, 1.0);
        gl_Position = projectionMatrix * modelViewPos;
    }
</script>

Initialization steps:

uniformParams = {
        percentage: { type: "f", value: 1.0 },
        tex1: { type: "t", value: (new THREE.TextureLoader()).load("images/sample1.png") },
        tex2: { type: "t", value: (new THREE.TextureLoader()).load("images/sample2.png") } 
    };

materialObj = new THREE.ShaderMaterial({
        uniforms: uniformParams,
        vertexShader: document.getElementById('vertexShaderLoader').textContent,
        fragmentShader: document.getElementById('fragmentShaderLoader').textContent
});

materialObj.transparent = true;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The returned data from a Apollo Client useMutation call is consistently undefined

Currently, I have a code snippet that executes a mutation to update a post to "published." The mutation functions correctly and updates the data as intended. However, I am facing an issue where the data property remains undefined in the useMutation hook. S ...

VeeValidate fails to validate input fields in a form that is constantly changing

My goal is to create dynamic forms with validations using veeValidate in Vue.js. I am attempting to achieve this by storing an array of objects within the component's data. For instance: data(){ return{ inputs: [ { id: 1, lab ...

How to highlight all the text within a 'pre code block' when double-clicked using JavaScript

Is there a way to make code blocks on my blog automatically selected when double-clicked without using jQuery? Here is the code I have so far: I apologize if this is a silly question, I am still learning! <script type="text/javascript" src="https://c ...

Encountering a "dependency resolution error" while deploying a React application with Parcel on Heroku

I've developed a compact application and I'm in the process of deploying it to Heroku. However, I keep encountering an error stating: '@emotion/is-prop-valid' dependency cannot be resolved. It's worth mentioning that this project d ...

I am seeking to incorporate several Three.js animations into my HTML document, but I am experiencing issues with them

As a professional graphic designer, I am facing an issue with Three.js https://i.sstatic.net/6ZsWa.jpg I have tried several solutions, but none seem to work effectively. In my attempt, I duplicated the imported model and changed its name. Despite trying ...

Transferring photos from iPhoto to iPhone results in loss of PNG transparency

I'm developing an iPhone app that requires images with transparency from the user. I thought I could sync my photos using iPhoto, then use the image picker to import them into the app. Unfortunately, when I tried this, the transparency was lost. I am ...

Comparing elements between two arrays in AngularJS

I am working with two arrays, the first one looks like this: $scope.blinkedBoxes=[3,4,1,2,..] There will be a maximum of 8 elements in this array, each element being a number from 1 to 4. The second array is as follows: $scope.clickedImages=[2,4,3,1,.. ...

Contrasting outcomes when tackling a problem in node.js versus python

After tackling a challenging leetCode problem, I successfully came up with the following solution: Given d dice, each with f faces numbered from 1 to f, determine the number of possible ways (modulo 10^9 + 7) to roll the dice so the sum of the face up nu ...

Creating a primary php file in Apache without the use of SQL or any database: is it possible?

Forgive me if this comes across as rude, but I'm struggling to grasp the concept of apache, PHP, and servers in general. To help myself understand better, I want to create a very basic website that assigns an ephemeral ID to each user (not a session). ...

Using JavaScript to Transmit URL

Imagine I have a URL similar to this: http://localhost:8000/intranet/users/view?user_id=8823 All I aim to achieve is to extract the value from the URL using JavaScript, specifically the user_id (which is 8823 in this instance), and transmit it through an ...

Store user input as cookies and showcase it to the user upon their return visit

I'm looking for some assistance in saving user input to cookies and displaying it to the user. The goal is to have the text entered in the input field change into a div and be displayed to the user every time they revisit the page. Currently, I only ...

Tips for showcasing an uploaded image with ajax

I am looking to upload an image and display it without having to reload the page. I believe this can be achieved using Ajax form submission. However, I have tried some code but the Ajax form submit function does not seem to be working for me. Can someone p ...

Rotating a rectangular parallelepiped in THREE.js based on the "normal" vectors of two specific faces

Imagine a rectangular parallelepiped in a 3D space positioned on the axis origin with a specific orientation. The largest face, depicted in green, is on the XY plane, while the smallest face, shown in blue, is parallel to the YZ plane. If we have two orth ...

Searching for the index of a nested array in jQuery using JSON

I am currently working on developing an image uploader using Codeigniter3 along with jQuery and Ajax. Problem: I am facing difficulty in understanding how to locate the index of the array received from the ajax response shown below. Here is the data retu ...

What is the reason for not displaying the various li elements on my webpage?

Here is the code snippet export default function DisplaySearchResults({ results }) { var arr = Object.entries(results) console.log(arr) return ( <div> Here are the search results : <ol> {arr.map((va ...

struggle to locate / Node.js Error

I followed the tutorial located at and implemented the following code. // Module dependencies. var application_root = __dirname, express = require( 'express' ), //Web framework path = require( 'path' ), //Utilities for dealing with fi ...

Using Node.js to retrieve child processes associated with a daemon and terminate them

I am attempting to create a node application that allows me to send the command kill -9 to all child processes of a single daemon. Just to clarify, there is one daemon running on our server. Upon startup, it initiates a process for communicating with clie ...

What could be causing the form body to return null in a PUT request?

What could be causing the form data to not be stored in req.body? EJS/HTML <form onsubmit="EditJob()" class="editForm"> <div class="form-group-edit"> <label for="position">Position</label> <input type="pos ...

Storing an Excel file with JavaScript: A comprehensive guide

I've been struggling to save an Excel file using Javascript, but I'm facing compatibility issues with different browsers. I initially tried using BASE64 along with data URL, which worked well in Chrome and Firefox but failed in IE and Safari. ne ...

What is the best way to maintain the toggleClass event state once an ajax call has been made?

If I have the HTML code below <div class="row"> <div class="link grey"> <a href="#">Link</a> </div> </div> <div class="row"> <div class="link"> <a href="#">Link</a> </div> & ...