Adding shadows to a ShaderMaterial in three.js: A step-by-step guide

My current challenge involves using a customized shader to incorporate gradient colors onto a model. However, I have noticed that the shader lacks clarity when it comes to displaying shadows with well-defined edges (as shown in the first image). It seems to have an unintended "glowing" effect.

I aim to achieve the same level of edge clarity seen in the second image with my custom shader. How can I make this happen?

THREE.ShaderMaterial:

https://i.sstatic.net/7yswp.png

THREE.MeshStandardMaterial:

https://i.sstatic.net/vWb6z.png

The custom shader featuring a gradient:

const mat: THREE.Material = new THREE.ShaderMaterial({
uniforms: {
    color1: {
        value: new THREE.Color("#01e2f6")
    },
    color2: {
        value: new THREE.Color("#FF6969")
    },
    color3: {
        value: new THREE.Color("#FFF9DE")
    },
    bMin: {
        value: this.mesh.geometry.boundingBox.min
    },
    bMax: {
        value: this.mesh.geometry.boundingBox.max
    }
},
vertexShader: `
    uniform vec3 bMin;
    uniform vec3 bMax;

    varying vec2 vUv;

    void main() {
    vUv.y = (position.y - bMin.y) / (bMax.y - bMin.y);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }
    `,
fragmentShader: `
    uniform vec3 color1;
    uniform vec3 color2;
    uniform vec3 color3;

    varying vec2 vUv;

    void main() {              
    gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);
    gl_FragColor = mix(gl_FragColor, vec4(mix(color2, color3, vUv.y), 1.0), vUv.y);
    }
    `
});

this.mesh.material = mat;

Answer №1

Here's a solution utilizing MeshStandardMaterial and .onBeforeCompile:

body{
  overflow: hidden;
  margin: 0;
}
<script async src="https://ga.jspm.io/npm:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="81e4f2aceceee5f4ede4acf2e9e8ecf2c1b0afb7afb2">[email protected]</a>/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="790d110b1c1c394957484c48574a">[email protected]</a>/build/three.module.js",
      "three/addons/": "https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fa8e92889f9fbacad4cbcfcbd4c9">[email protected]</a>/examples/jsm/"
    }
  }
</script>
<script type="module">
// Code omitted due to character limit
</script>

PS The gear design can be found here: https://codepen.io/prisoner849/pen/zYaZPPw

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 is the best way to display countries using paths on a 3D globe in React Native?

I'm currently working on developing an interactive world map in React Native. The challenge I am facing involves incorporating country information paths from a file called countriesData.json into my project. While I have successfully generated a 3D gl ...

What could be causing the if/else block in my Redux Toolkit reducer to malfunction?

I'm currently working on a shopping cart feature where I need to increase the quantity of an item if it's already in the cart. If the same item with different sizes is added, they should be displayed separately. I've successfully implemented ...

Prevent the function from being repeatedly triggered as the user continues to scroll

I am facing an issue with my app where new content is fetched from the API using the infinity scroll method when the user reaches near the bottom of the screen. However, if the user scrolls too fast or continuously scrolls to the bottom while new content i ...

When using React with Firebase, remember to specify the "to" property when using setState to avoid errors

Struggling to figure out what's going wrong after hours of trying. I'm new to React and would really appreciate your help. Initially, my state was an array of accommodations which I mapped over successfully. However, once I connected Firebase wit ...

Encountering an issue with Meteor and node-celery: "Unable to access property 'slice' of null"

Check out the Github repository for reproducing this issue Run localhost:3000 to replicate the problem. In my setup with Meteor 1.4.4.1, I am utilizing the node-celery npm packages on the server side. Upon Meteor initialization, the client automatically i ...

"Enhance Your Phonegap Android App with Pinch Zoom Capability

I am currently working on an Android Application with the help of jQuery Mobile and Phonegap. My goal is to implement pinch zoom functionality on the App pages. I have come across several suggestions that involve using the following line, but unfortunatel ...

Even when it appears to be chaotic, the TypeScript array of numbers always manages to find its way back to being sorted

I recently developed a function that aims to verify if an array of numbers is sorted: const checkIfSorted = (numbers: number[]) => { return numbers === numbers.sort((a, b) => a - b); }; checkIfSorted([4, 2, 8, 7, 3, 10, 1, 5, 9, 6]); // This cur ...

Suggestions for placing a script under the scripts menu in Illustrator CS5.1

My script for Adobe Illustrator CS5.1 is not showing up in the scripts menu despite trying to place it in various directories such as: C:\Program Files\Adobe\Adobe Illustrator CS5.1\Presets\en_GB\Scripts\ C:\Progra ...

searching backwards using regular expressions

I have successfully extracted <%? imagepath;%> using the following regex from a string. <%(\?|.|\s)*%> <img src="http://abc/xyz/<%? imagepath;%>.gif"> <img not_src="http://abc/xyz/<%? imagepath;%>.gif"> <i ...

"Troubleshooting Issue: Why Props in mapStateToProps Aren't Updating After Running an Action in Redux

Adding some context, I utilize Redux to manage updates in a shopping cart list. Essentially, I retrieve the list, add an item to it, and then update the entire list. However, after executing an action, my cartList does not seem to update. Despite consulti ...

Looking for a Javascript tool to select provinces graphically?

Looking for a graphic province selector similar to the one found on this website: . If anyone is aware of something like this, especially in the form of a jQuery plugin, that would be fantastic. Thank you. ...

Storing and Retrieving Cookies for User Authentication in a Flutter Application

I am currently working on developing a platform where, upon logging in, a token is created and stored in the cookie. While I have successfully implemented a route that stores the cookie using Node.js (verified in Postman), I encounter issues when attemptin ...

High resolution 2D canvas text using a high-fidelity Three.js model

Initially, I've really been enjoying working with three.js. However, I'm in need of a little assistance with something I am trying to achieve. I have a high poly model in Maya that I exported to JavaScript and loaded via THREE.JSONLoader(). So fa ...

How to Utilize Vue and Checkboxes for Filtering a List?

My current challenge involves filtering a list of posts based on userId using checkboxes. The data is being retrieved from: https://jsonplaceholder.typicode.com/posts. I aim to include checkboxes that, when selected, will filter the list by userId. Here is ...

What is the best way to capture a screenshot using selenium in conjunction with synchronous JavaScript?

Currently, I am developing an automated test using javaScript and leveraging a node library called webdriver-sync. This library simplifies writing selenium tests by eliminating the need for callbacks and promises, and it utilizes the java Webdriver API. Su ...

Organize information in a React table following a predetermined sequence, not based on alphabetical order

As a beginner with React, I'm looking to sort my data by the column "Status" in a specific order (B, A, C) and vice versa, not alphabetically. The data structure looks like this: export interface Delivery { id: number; name: string; amount: num ...

Is it possible to first match a named route and then a dynamic route in Express.js?

app.get('/post/create', create_post); app.get('/post/:slug', view_post); When trying to access /post/create, I expected the view_post function not to run. However, it still matches because "create" can be considered the value for :slug ...

The importance of managing both synchronous and asynchronous processes in Javascript

As I delved into the intricacies of Javascript's asynchronous behavior within its single-threaded environment, I stumbled upon a comment that caught my attention regarding the following code snippet: request(..., function (error, response, body) ...

Using the Google Identity Services JavaScript SDK in conjunction with Vue and TypeScript: A comprehensive guide

I am currently working on authorizing Google APIs using the new Google Identity Services JavaScript SDK in my Vue / Quasar / TypeScript application. Following the guidelines provided here, I have included the Google 3P Authorization JavaScript Library in ...

How to assign attributes to all child elements in Angular?

I have a unique component in Angular that I utilize throughout my app. It's a button component which I use by calling <app-delete-btn></app-delete-btn> wherever needed. I tried to set the tabindex="1" attribute for my component ...