Three.js: Apply a single color to a mesh shaderMaterial until a specific point is reached

I am struggling to grasp the concept of Three.js shaders. My goal is to apply a color to a mesh, but only up to a specific point. Here is my progress so far.

  • I want the green color to "stop" at 50% of the mesh height
  • For the remaining part of the mesh (above 50%), I am open to either filling it with another color or leaving it unfilled (both options would work)

Shader code:

    const _VS = `

        uniform vec3 bboxMin;
        uniform vec3 bboxMax;

        varying vec2 vUv;

        void main() {
            vUv.x = (position.x - bboxMin.x) / (bboxMax.x - bboxMin.x);
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `;

    const _FS = `

        uniform vec3 incompleteColor;
        uniform vec3 completenessColor;

        varying vec2 vUv;

        void main() {

            gl_FragColor = vec4(mix(incompleteColor, completenessColor, vUv.x), 1.0);
        }
    `;

Javascript code:

            let geometries = element.geometry.clone(); // Inherits geometries from parent element

            let wall = new THREE.Mesh(
                geometries,
                new THREE.ShaderMaterial({
                    uniforms: {
                        incompleteColor: {
                            value: new THREE.Color('red')
                        },
                        completenessColor: {
                            value: new THREE.Color('green')
                        },
                        bboxMin: {
                            value: element.geometry.boundingBox.min
                        },
                        bboxMax: {
                            value: element.geometry.boundingBox.max
                        }
                    },
                    vertexShader: _VS,
                    fragmentShader: _FS,
                })
            );

            wall.castShadow = true;
            wall.position.setFromMatrixPosition(element.matrixWorld);
            wall.rotation.setFromRotationMatrix(element.matrixWorld, 'XYZ');

            scene.add(wall);

This image demonstrates what I am aiming for:

LEFT: The current result with the provided code (Three.js scene)

RIGHT: The desired outcome

https://i.sstatic.net/2w0lh.png

I have spent hours researching this problem, but I haven't found a suitable example to guide me in the right direction.

Answer №1

To achieve the desired effect, you must incorporate the GLSL function step(). For more information on how to implement this function, you can check out this resource.

void main() {
    // Begin by creating a definitive step at the 0.5 threshold of UV
    float transition = step(0.5, vUv.x);
    
   // Next, apply this specific step in your mix operation
    gl_FragColor = vec4(mix(startColor, endColor, transition), 1.0);
}

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

Is it possible to replicate a stale closure similar to React's useEffect hook without the use of the useEffect hook?

I have a good understanding of closures, but I am struggling to grasp how a stale closure can be created in React's useEffect without providing an exhaustive dependencies array. In order to explore this concept further, I am attempting to replicate a ...

Looking for a way to trigger a function on JSTree's refresh event

I have searched through many posts here but cannot find what I am looking for. The version of JSTree that I am using is 3.3.3. My goal is to select a node after a create_node event triggers an AJAX request. Subsequently, JSTree fires the rename_node eve ...

Unexpected Outcome Arises When Applying Lodash's Debounce Function to Axios API Call

I keep encountering an issue with my app where it updates every time text is typed. I've implemented debounce on an axios request to queue them up until the timer runs out, then they all go at once. But I want to limit the requests to one per 10-secon ...

Form a hierarchical data structure using a combination of three arrays

Here are three sets of data: let firstData = [ {key: value1}, {key: value2}, {key:value3} ] let secondData = [ {key: value1}, {key: value2}, {key:value3}, {key: value4} ] //same structure, different values let thirdData = [ [1,1,1,1], [1,1,1,1], [1,1,1,1] ...

Take charge of the TrackballControls

Is there a way to limit the rotation of the TrackballControl (r53) to only the upper hemisphere? Alternatively, how can one restrict it to just a single axis? The question about this restriction has come up several times, but I haven't been able to fi ...

Ways to both retrieve a variable and clear it simultaneously

In my validator library, there are functions that sanitize and validate strings. These validator functions add error messages to an array called "errors" for each invalid input they encounter. After completing validation on all inputs, I collect the error ...

Tips for implementing a 2-second delay in Ajax success function

I am experiencing fast responses when fetching data in each loop, but I need to introduce a delay. I have tried using setTimeout and delay methods without success. I believe there might be a different approach that I should consider, but I am unsure how ...

Adding an indentation to the initial line of each paragraph within a text area

Is there a way to apply indentation to each paragraph within a text area as the user types? I tried using the code below: <textarea rows="1" style="height:1em; text-indent:-50px; padding-left:50px;" cols="25" html="true" id="text">Lorem Ipsum Lorem ...

Disappearing Data Mystery in ngFor Array

In my Angular 6 component, I have created a form for adding new users using an HTML table: user-add.component.html [...] <tbody> <tr *ngFor="let value of data.pos; let i = index"> <td><input matInput [(ngModel)]="value.us ...

Tips for real-time content updates on a server-side rendered express application

My social media app, built using Express, Pug, and JavaScript for server-side rendering, is fully functional. However, whenever I comment on a post, I need to manually reload the page to see the new comment displayed. I'm exploring ways to dynamicall ...

What's the best way to propagate a browser event through a custom event?

http://jsfiddle.net/m2dqd236/ document.addEventListener('click', function (event) { $(document).trigger('click-anywhere', $.event.fix(event)); }, true); $(document).on('click-anywhere', function (event, e) { console.lo ...

Unit Testing Angular: Mastering Unit Testing for the .map() Function

I am in need of testing a service method, but I am unsure about how to achieve complete coverage for the code that gets executed as a result of calling another injected service method. The Service Method to be tested: @Injectable() export class BomRevisi ...

Form Validation in JavaScript Continues to Submit Form Even When 'False' is Detected

Here is the issue at hand - I am restricted to using older browsers (IE8 and FF8) by corporate policy. Despite my research indicating otherwise, it seems like this might be the root cause of my troubles. My current setup includes PHP 5.5.12 on Apache 2.4. ...

How can I connect HTML and JavaScript to get the clicker functioning?

While the HTML and javascript work flawlessly on jsfiddle where I initially created this project, I'm encountering a problem with Google Drive's hosting. The HTML displays correctly but there is no interaction happening with the javascript. Belo ...

Antialiasing Dilemma in Webgl/Three.js

When creating a rectangle with shadows and transparency, I encountered antialiasing issues when the dimensions were small (<30px) or when applying a 2D rotation at any angle. The quality of the geometry deteriorated significantly in these cases. Here i ...

Issue with displaying ng-repeat data in AngularJS tbody

I am experiencing an issue with using ng-repeat inside a tbody element. Here is the code snippet that is causing trouble: <tbody> <tr ng-repeat="group in groups"> <td>{{ group.name }}</td> </tr> </tbody> Wh ...

Blank white screen in Three.js following the rendering of numerous objects

I have a situation where I am loading over 4350 3D objects from JSON files in my game. for (var y in game.fields) { for (var x in game.fields[y]) { switch (game.fields[y][x]) { case 'm': ...

Exploring the functionalities of stores and props within the Vue onMounted lifecycle method

As a newcomer to the Vue Composition API, I've run into some issues with functions like defineProps not being available. My current predicament involves receiving props from a parent component and wanting to store them in the "Pinia" storage after a s ...

Validating Arrays of Input Elements using JQuery

I have a task to validate an array of input text elements (mileage). Here is an example of what I need to accomplish: <tbody> <c:forEach items="${list}" var="item"> <tr> <!--some other columns---> ...

The issue of Angular curly braces malfunctioning in some simple code examples reversed my

<head> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"> </script> </head> <body style="padding: 20px 20pc;"> <div ng-app="app"> ...