A comprehensive guide on effectively utilizing a lookup table in a shader using three.js

I have developed a basic three.js project that involves using a height map. Below is the specific code snippet responsible for creating the shader material:

function loadHeightMap() {
    // setting up a mock lookup table
    var lut = [];
    for ( var n=0; n<256; n++ ) {
       lut.push(new THREE.Vector3(0.5, 0.4, 0.3));
    }

    var loader = new THREE.TextureLoader();
    var zScale = 10;

    var mapLoc = "https://s22.postimg.org/8n93ehmep/Terrain128.png";
    loader.load(mapLoc, function ( texture ) {
    // using "this." to create a global object
    this.customUniforms = {
        zTexture:   { type: "t", value: texture },
        zScale:     { type: "f", value: zScale },
        zLut:       { type: "v3v", value: lut }
    };

    var customMaterial = new THREE.ShaderMaterial({
        uniforms: customUniforms,
        vertexShader:   document.getElementById( 'vertexShader'   ).textContent,
        fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
        side: THREE.DoubleSide
    });

    var planeGeo = new THREE.PlaneGeometry( 20, 20, 129, 129 );
    var plane = new THREE.Mesh( planeGeo, customMaterial );
    plane.rotation.x = -Math.PI / 2;
    plane.position.y = 0;

    scene.add(plane);
});
}

Here are the shader scripts used:

<script id="vertexShader" type="x-shader/x-vertex">
    uniform sampler2D   zTexture;
    uniform float       zScale;
    uniform vec3        zLut[ 256 ];

    varying float vAmount;

    void main() {
      vec4 heightData = texture2D( zTexture, uv );

      vAmount = heightData.r; 

      // adjusting the position based on the normal
      vec3 newPosition = position + normal * zScale * vAmount;

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

<script id="fragmentShader" type="x-shader/x-vertex">
    uniform vec3        zLut[ 256 ];

 varying float vAmount;

 void main() {
     int index = int(vAmount) * 255;
       vec3 vColor = vec3(vAmount, vAmount, vAmount);
       //gl_FragColor = vec4(zLut[index], 1.0);
       gl_FragColor = vec4(vColor, 1.0);
  }

The shaders and the height map functionality are operational. However, I am encountering challenges when attempting to pass the lookup table (zLut). The provided code functions correctly if the lookup table isn't utilized. You can view a functional example here. Additionally, I have created a fiddle here, but it fails due to CORS issues.

I would appreciate any suggestions or insights on this matter.

Answer №1

Resolved the issue successfully by implementing a solution in the vertex shader. By fetching the lookup color in the vertex shader, I was able to index into an array using a non-const value. This color was then passed to the fragmentShader as a varying. Here are the updated shaders:

<script id="vertexShader" type="x-shader/x-vertex">
        uniform sampler2D   vTexture;
        uniform float       vScale;
        uniform vec3        vLut[ 256 ];

        varying vec3        vColor;

        void main() {

            vec4 heightData = texture2D( vTexture, uv );

            // assuming map is grayscale it doesn't matter if you use r, g, or b.
            float vAmount = heightData.r;

            // fetch the color from the lookup table so it gets passed to the fragshader
            int index = int(heightData.r * 255.0);
            vColor = vLut[index];

            // move the position along the normal
            vec3 newPosition = position + normal * vScale * vAmount;

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

    <script id="fragmentShader" type="x-shader/x-vertex">

        varying vec3  vColor;

        void main() {

            gl_FragColor = vec4(vColor, 1.0);
        }
    </script>

Currently, the issue I am facing is that the colors appear flat when rendered. Although I attempted to force an update on the vertices in the animate function without success, I am still investigating the error. However, the main question at hand has been resolved (to the best of my knowledge).

You can view the outcome here

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 bend a Polyline in react-google-maps?

Just dipping my toes into React and experimenting with the react-google-maps package. I'm on a mission to curve a Polyline connecting two locations. I've reviewed the documentation and I'm attempting to integrate the curve polyline function ...

What is the reason for not storing information from MySQL?

Looking to extract data from a website using this JavaScript code. var i = 0 var oldValue = -1 var interval = setInterval(get, 3000); function get(){ var x= $($('.table-body')[1]).find('.h-col-1') if(i!=5){ if(oldValue != x){ old ...

After converting my HTML elements to JSX in Next.js, I am experiencing issues with my CSS files not being applied

Hey there, I'm currently working on a website using Next.js. I've converted the HTML elements of a page to JSX elements but for some reason, the CSS of the template isn't showing up. I've double-checked all the paths and even updated th ...

Does the first Ajax call always finish first in the order of Ajax calls?

In my code, I have an ajax call that triggers another ajax call based on its return value. The URL parameter of the second call is modified by the output of the first one. These two calls are interrelated as the first call feeds the URL parameter for the s ...

Transitioning from using lerna to adopting pnpm

We are in the process of transitioning our project from Lerna to PNPM and we currently have a script that we run. Here are the commands: "postinstall": "npm run bootstrap" "bootstrap": "lerna bootstrap --hoist", &quo ...

text/x-handlebars always missing in action

I'm currently working on my first app and I'm facing an issue with displaying handlebars scripts in the browser. Below is the HTML code: <!doctype html> <html> <head> <title>Random Presents</title> ...

Issue with JQuery time picker functionality not functioning properly upon repeat usage

I am facing an issue with a modal dialog that contains a form loaded via ajax. The form includes a time field populated using the jquery timepicker. Everything works perfectly when I open the dialog for the first time. However, if I try to load the dialog ...

Vue 2.0: Exploring the Power of Directive Parameter Attributes

It has come to my attention that directive param attributes have been phased out in Vue.js 2.0. As a result, I am unable to use syntax like v-model="msg" number within an input tag. Are there alternative methods to achieve the same outcomes without relyi ...

Autocomplete feature integrated within search bar

I'm currently experimenting with merging MUI autocomplete and MUI searchbar to create a Searchbar that provides suggestions. I have attempted the following: https://codesandbox.io/s/material-demo-forked-cthpv import React from "react"; impo ...

When a Javascript function marked as async is executed, it will return an object

Async function is returning [object Promise] instead of the desired real value. Interestingly, I can see the value in the console log. It seems like this behavior is expected from the function, but I'm unsure how to fix my code. This code snippet is ...

"Utilizing AJAX in JavaScript to render HTML content and inserting it into an HTML element with a specific id

I ran into an issue while trying to display HTML content in a Bootstrap modal using AJAX. The class seems to be malfunctioning and I'm unable to pinpoint the source of the error. Here's the code snippet: var all_gaugeKritis5 = ""; all_gaugeKrit ...

Tips for selecting an <select> option value based on an URL parameter automatically

I have a 2-step form where I am successfully passing the first name in the URL from step 1 to step 2, but I am struggling to do the same for a select field. Here's an example of what I have: In the URL: ?firstname=Bob Form Field: <input type= ...

My bootstrap collapse navbar isn't functioning properly. Despite pressing the icon on a smaller screen, the menu fails to open. Can anyone provide a solution to this issue?

The hamburger menu is not working properly. I am facing an issue where the navigation does not appear when I press on the hamburger icon on a small screen. Can someone please guide me on how to resolve this problem? :/ <nav class="navbar bg-d ...

What is the best way to assign JSON data to a Class variable within Angular?

In my code, I have a class called Projects export class Projects { project_id: number; project_name: string; category_id: number; project_type: string; start_date: Date; completion_date: Date; working_status: string; project_info: string; area: string; add ...

Tips for attaching functions to a fresh SVG element with jQuery?

My jQuery code creates an <svg> element and appends it to a <div>. When I try to access the appended <svg> using each() after the append() function, the event handler doesn't work. However, if I create the <svg> element before ...

The "read more" button seems to be malfunctioning

I've been working on integrating a gallery of images into my posts. My goal is to display 4 images initially, followed by a "load more" button that, when clicked, will reveal another set of 4 images, and so on. I have already created the HTML, CSS, an ...

Check the value of a single bit in JavaScript: Is the bit on (1) or off (0)?

Is there a way in JavaScript to determine if a single Bit is On (1) or Off (0)? function isBitOn(number, index) { // ... ? } // Example: let num = 13; // 1101 isBitOn(num, 0); // true 1 isBitOn(num, 1); // false 0 isBitOn(num, 2); // true 1 isBit ...

Guide to dynamically adding a class in VueJS based on a certain condition

I'm in the process of transitioning a project to Vue, and I'm curious about how I can dynamically assign classes to specific elements based on database values rendered with Vue. Previously, I had this code set up without Vue: $(document).ready(f ...

Alert: '[Vue warning]: Directive "in testing" could not be resolved.'

Currently, I am running unit tests within a Vue 2.0 application using PhantomJS, Karma, Mocha and Chai. Although the tests are passing successfully, I am encountering a warning message with each test indicating an issue like this: ERROR: '[Vue warn ...

What is the process for importing extensions and files in Visual Studio Code?

Nodejs development utilizing (--experimental-modules) Current visual studio code intelligence import example: import config from "./config"; However, it should be imported as: import config from "./config.js"; An error is encountered without the . ...