Shapes in Three.js with multiple colors

As a newcomer to Three.js and webGL programming, I have successfully created a cone and a cylinder in my scene using the script provided below:

var scene;
var camera;
var renderer;

var createACone = function() {
    // Cone creation code here
}

var createACylinder = function(radiusTop, radiusBottom, height, x, y, z, opacity=0.5, z_rotate = 0, transparent=true, thetaStart=0, thetaLength=2*Math.PI) {
     // Cylinder creation code here
}

var createLight = function () {
    // Light creation code here
};

var init = function(){
    // Scene initialization code here
}

window.onload = this.init;

I am now looking to divide the cone and cylinder horizontally into two colors based on their height. I want the lower base to halfway point of the cylinder to be red, and the rest to be blue. Similarly, I want the cone's vertex to midpoint to be red, with the rest being blue. I have explored the material and geometry sources but haven't found a solution. Splitting each geometry into two manually is not ideal, as I desire a dynamic color ratio. Is there a better method within Three.js to achieve this effect?

Thank you in advance for your assistance.

Answer №1

Here is an example of how you can implement a dual-color effect using UV coordinates within a ShaderMaterial:

body {
  overflow: hidden;
  margin: 0;
}
<script type="module">
console.clear();
import * as THREE from "https://threejs.org/build/three.module.js";
import {OrbitControls} from "https://threejs.org/examples/jsm/controls/OrbitControls.js";
import {BufferGeometryUtils} from "https://threejs.org/examples/jsm/utils/BufferGeometryUtils.js";
import {GUI} from "https://threejs.org/examples/jsm/libs/dat.gui.module.js";

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, -5, 8);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

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

let gCyl = new THREE.CylinderGeometry(5, 5, 1, 32, 1, true);
let gCon = new THREE.ConeGeometry(5, 1, 32, 1, true);
for(let i = 0; i < gCon.attributes.uv.count; i++){
  gCon.attributes.uv.setY(i, 1 - gCon.attributes.uv.getY(i));
}
gCon.rotateX(Math.PI);
gCon.translate(0, -1, 0);
let g = BufferGeometryUtils.mergeBufferGeometries([gCyl, gCon]);

let m = new THREE.ShaderMaterial({
  uniforms: {
    color1: {value: new THREE.Color("red")},
    color2: {value: new THREE.Color("blue")},
    colorRatio: {value: 0.5}
  },
  vertexShader:`
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }
`,
  fragmentShader: `
    uniform vec3 color1;
    uniform vec3 color2;
    uniform float colorRatio;
    varying vec2 vUv;
    void main() {
      vec3 col = mix(color1, color2, step(colorRatio, vUv.y)); 
      gl_FragColor = vec4( col, 1.0);
    }
  `
});

let o = new THREE.Mesh(g, m);
scene.add(o);

let gui = new GUI();
gui.add(m.uniforms.colorRatio, "value", 0., 1.).name("colorRatio");

renderer.setAnimationLoop( _ => {
  renderer.render(scene, camera);
});
</script>

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

What are the best practices for utilizing *ngIf?

In my Angular project, I am facing a challenge with using *ngIf. My app.component.html file handles both the login page and the dashboard. I want to hide the dashboard until the user logs in. To achieve this, I decided to use *ngIf. Here is how I implement ...

The MeshBasicMaterial is producing the wrong color when given input

I've encountered an issue where the shade of the material in my scene is different from what I intended, even though there are no other lights or factors influencing it. Initially, I used meshBasicMaterial thinking that lights were causing the proble ...

Resolving issues with CSS placement and resizing

I have been considering developing a UI toolkit that offers an intuitive and powerful way of setting the position and size of elements/widgets. Here are some examples of how it could be used (although they are not currently implemented): ui("Panel").size( ...

Place the button inside the form following another block element

Here is the HTML code I am working with: <div class="actions"> <input id="submit-car" name="commit" type="submit" value="Добавить объявление"> </div> and here is a fiddle example: http://jsfiddle.net/348U4/ In ...

Tips for defining the operational scope of orbit controls in three.js

I've been working on creating an orientation cube in threeJS and have set up 2 scenes with different viewports, cameras, and controls. Check out the fiddle here var controls = new THREE.OrbitControls( view.camera, container.domElement ); In the fid ...

Erasing a comment creates empty spaces

I've encountered an issue with my idea whiteboard where removing comments leaves unwanted blank spaces between ideas. For example, if I have the following comments: But when I delete something: Is there a way to ensure that no gaps are left between ...

Traversing through JSON main sections, checking for operation and subsequently retrieving data

I have a json structure below: { users: [ { action: 'add', payload: [Array] } ], categories: [ { action: 'add', payload: [Array] } ], products: [ { action: 'add', payload: [Array] } ] } Can you suggest a method using .m ...

prevent parent jQuery functions from interfering with child function execution

I am facing an issue with conflicting jQuery functions between parent and child elements. The child function is a bootstrap function, while the parent is a custom function. The main objective is to limit the height of the parent div (refer to the code belo ...

Creating registration and login forms using an express server

Currently, I'm in the process of creating a basic website on my localhost that incorporates a signup form along with other essential HTML elements. The setup for the signup procedure went smoothly as planned. When a user completes the form and submits ...

Tips for inserting a page break after every item in a loop in Visualforce when generating a PDF document

I need help with rendering a VF page as PDF. The VF page iterates over a list of account records using the repeat tag. I want to apply a page break for each element in the repeat tag. The code below is working, but it has an issue - it shows an empty PDF p ...

Syntax for retrieving response with jQuery AJAX

Currently, I am in the process of working on an AJAX request that triggers a URL when a specific button is clicked. The fundamental aspects are running smoothly, ensuring that the GET request is activated towards the URL upon button click. I have also cros ...

Utilize the HTTP path to designate the currently active tab

Here is a sample code snippet for vertical tabs in React using the Material-UI library: import * as React from 'react'; import Tabs from '@mui/material/Tabs'; import Tab from '@mui/material/Tab'; import Typography from '@ ...

Console log displays varied outputs for identical arrays

Having an array in a static form and one that is filled using the ajax post function, I initially planned to replace the static array with the dynamic one. However, upon closer inspection, it seems that the two arrays are not matching. Array 1 (static) ...

Adjusting the height of the search icon through the Jquery toggle action to create animated effects

While trying to create a search field with the click function (animate), I noticed an issue similar to what is seen in this example: . Whenever the search icon is clicked, it moves up and down unexpectedly, and I am uncertain as to why this behavior is occ ...

Switch your attention to the following input text using AngularJS

In my controller, I have an object variable called `myObject` with 3 input text fields in the user interface. I am looking for a way to automatically shift the focus to the next input field once the current one reaches its maximum length. var myObject = ...

Error message: Uncaught TypeError - Unable to retrieve data using POST method in react with node and express servers

I am currently working on creating a Login / Register form using react for the client-side and node / express / (mongo) for the backend. The backend functionality is working smoothly as expected, with successful storage of credentials in the database upon ...

What is the best way to conceal elements that do not have any subsequent elements with a specific class?

Here is the HTML code I have, and I am looking to use jQuery to hide all lsHeader elements that do not have any subsequent elements with the class 'contact'. <div id="B" class="lsHeader">B</div> <div id="contact_1" class="contac ...

What distinguishes the sequence of events when delivering a result versus providing a promise in the .then method?

I've been diving into the world of Promises and I have a question about an example I found on MDN Web Docs which I modified. The original code was a bit surprising, but after some thought, I believe I understood why it behaved that way. The specific ...

JavaScript code failing to return array contents

As I navigate through the realms of NodeJS application development handling .nessus result files, I encounter an intriguing behavior quandary when generating an array of numbers. The primary goal is to create an array [1234,1223,1222] from a "results" file ...

how can you add an object to an array in react native without altering the properties of the array

In my attempt to contract an array for use in 'react-native-searchable-dropdown', I have encountered an issue while trying to push objects into the array. Here is the code snippet that I am struggling with: let clone=[]; obj={{id:8,name:'Yyf ...