Issue with adjusting the column width in the three.js shader

My challenge involves dividing a shader into 6 columns and 3 rows, each with dimensions of 100vw by 100vh. The goal is to have the rows evenly proportioned by height. However, the width of the shader segments should vary in proportions of 17.65vw, 16.25vw, 16.32vw, 16.32vw, 16.25vw, and 17.15vw from left to right. Currently, all segments have the same width, preventing me from achieving the desired result.

I received the initial code from a web designer, which was built using React. Since I needed it in JavaScript, I rewrote the code but encountered an issue where the shader segments were only square-shaped and couldn't be adjusted for different shapes and sizes. Despite researching three.js and reviewing the provided code, I haven't been able to make it work as intended. Here is my code:

const canvas = document.getElementById('canvas');
    const renderer = new THREE.WebGLRenderer({ canvas });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    const scene = new THREE.Scene();

    const camera = new THREE.OrthographicCamera(
        window.innerWidth / -2, window.innerWidth / 2,
        window.innerHeight / 2, window.innerHeight / -2,
        0.1, 1000
    );
    camera.position.z = 1;

    window.addEventListener('resize', () => {
        const width = window.innerWidth;
        const height = window.innerHeight;
        renderer.setSize(width, height);
        camera.left = width / -2;
        camera.right = width / 2;
        camera.top = height / 2;
        camera.bottom = height / -2;
        camera.updateProjectionMatrix();
    });

    const vertexShader = `
        varying vec2 vUv;
        void main() {
            vUv = uv;
            vec4 modelPosition = modelMatrix * vec4(position, 1.0);
            vec4 viewPosition = viewMatrix * modelPosition;
            vec4 projectionPosition = projectionMatrix * viewPosition;
            gl_Position = projectionPosition;
        }
    `;

    const fragmentShader = `
        uniform float time;
        uniform vec2 resolution;
        uniform vec2 pointer;
        varying vec2 vUv;

        // Fragment shader logic goes here

    `;

    const uniforms = {
        time: { value: 0 },
        resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
        pointer: { value: new THREE.Vector2(0, 0) }
    };

    // Shader material setup

    const geometry = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
    const plane = new THREE.Mesh(geometry, material);
    scene.add(plane);

    const clock = new THREE.Clock();
    function animate() {
        uniforms.time.value += clock.getDelta();
        renderer.render(scene, camera);
        requestAnimationFrame(animate);
    }

    animate();
#canvas {
  display: block; 
  position: absolute; 
  top: 0; 
  left: 0; 
  width: 100vw; 
  height: 100vh;
}
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

I am seeking assistance in making the shader's column (segments') width adjustable and distinct from each other. Can you please help me find a solution?

Answer №1

expanding the number of segments in PlaneGeometry is possible.

const widthSegments = 6
const heightSegments = 3

const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)

By adjusting geometry.attributes.position, you can alter the behavior to achieve this result: https://i.sstatic.net/fluTlO6t.png To accomplish this, use the following function:

function adjustPlaneGeomPosAttr(planeGeometry, widthSegments, heightSegments) {
    function validate(value, valueCheck) {
        if ( !(value instanceof Array) || (value instanceof Array && value?.length != valueCheck)) {
            if (value instanceof Number) {
                return new Array(value).fill(1)
            } else {
                return new Array(valueCheck).fill(1)
            }
        } else {
            return value
        }
    }

    widthSegments   = validate(widthSegments , planeGeometry.parameters.widthSegments )
    heightSegments  = validate(heightSegments, planeGeometry.parameters.heightSegments)

    const widthPos   = widthSegments .reduce((ac,a,i)=>{ac[i+1]=ac[i]+a; return ac}, new Array(widthSegments .length+1).fill(0)).map((a,_,A)=>a/A.at(-1))
    const heightPos  = heightSegments.reduce((ac,a,i)=>{ac[i+1]=ac[i]+a; return ac}, new Array(heightSegments.length+1).fill(0)).map((a,_,A)=>a/A.at(-1))

    const pos = planeGeometry.attributes.position.array
    let i = 0;
    for (yPos of heightPos) {
        y = (yPos-0.5)*planeGeometry.parameters.height

        for (xPos of widthPos) {        
            x = (xPos-0.5)*planeGeometry.parameters.width

            pos[i++] = x
            pos[i++] = -y
            pos[i++] = 0
        }
    }
}

planeGeometry represents the THREE.PlaneGeometry you wish to modify
widthSegments should be an Array with a length equal to the widthSegments of PlaneGeometry (if you don't want to change widthSegments, just set it to null)
heightSegments should be an Array with a length equal to the heightSegments of PlaneGeometry (if you don't want to change heightSegments, simply set it to null or omit specifying a value)

To demonstrate how to apply this function, here's an example:

const geometry = new THREE.PlaneGeometry(width, height, 6, 3);
adjustPlaneGeomPosAttr(geometry, [1,2,3,4,5,6], [1,2,3])

In this scenario:
widthSegments = [1,2,3,4,5,6], indicating relative widths for each segment (the overall width remains unchanged)
heightSegments = [1,2,3], denoting relative heights for each segment (the total height stays constant)
As a result, you will see: https://i.sstatic.net/6ER1YdBM.png For your specific situation, assign widthSegments as

[17.65, 16.25, 16.32, 16.32, 16.25, 17.15]

Complete code section:

function modifyPlaneGeomPosAttr(planeGeometry, widthSegments, heightSegments) {
    // Function code here...
}

// Additional code snippet...
#css styles go here...
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <canvas id="canvas"></canvas>
    <input type="range" min=0 max=1 step=0.001 value=0.385>

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 return statement seems to be coming up blank

Why is the return statement not producing any output or errors? I've tested it on Chrome, Firefox, and repl.it. Here's the code snippet in question: //Function that returns the product of two numbers function multiply(num1, num2){ ret ...

What is the importance of updating project dependencies regularly?

After coming across the tags on GitHub repositories, it dawned on me that some of my own projects have outdated dependencies. Surprisingly, my code still functions properly without updating them. What are the compelling arguments for regularly updating ...

Ensuring the absence of non-UTF8 characters in JavaScript

Seeking advice on creating a function in Javascript to determine if a string contains only UTF8 characters. The goal is to return true if the string has no non-UTF8 characters, and false if it does. No character replacement is needed, just a validation c ...

Resposiveness of force-directed graph is lost

const container = document.getElementById("container"); const svgElement = d3.select(container).append("svg") // Get the width and height computed by CSS. let width = container.clientWidth; let height = container.clientHeight; const colorScale = d3.scale ...

What is the best way to add a dynamic parameter to the URL?

Here is an example of my URL: https://my-website.com/api/players?countryId=1&clubId=2&playerName=abc The parameter values can vary. This is the code snippet I use: getDataPlayer(payload) { let params if(payload.countryId && payl ...

Sorting a function with two parameters in descending order is possible even when dealing with an empty array and no initial value for reduction

My npm test is not passing the third out of six tests. I have attempted to sort it using the following code snippet: sumAll.sort(function(min,max)) { return max - min; } However, this approach did not work. I also tried incorporating conditionals in t ...

Is the element loaded but not appearing on screen?

I am facing an issue when using ajax to send data to a PHP server and displaying it in the view. Even though the data loads successfully (checked in console), it does not display in the view. Can someone please help me resolve this? Here is my code : Vie ...

Combining Python Arrays with JavaScript Indexing in Django's Template Language

Hey there, I have a question that's been bugging me for a while. While working on rendering a view in Django, the python side of my code looks something like this: ... marray = [1, 2, 3, 4, 5] ... return render(request, "template.html", {"marray": ma ...

How come every time I click on a different lightbox link, it always shows the same content

I'm currently facing an issue where different contents are supposed to be displayed in different lightbox links, but instead, when I click on any link, only the last content appears in all other lightboxes. It seems like there is some overlapping happ ...

Can information be securely transmitted using Ajax?

Currently, I am in the process of developing an application in HTML and JavaScript that heavily relies on ajax connections, with the use of the jQuery.ajax() method to simplify the process. I have been pondering the best practices for making secure calls ...

Do discrepancies exist between ' and " symbols?

Similar Question: When to Use Double or Single Quotes in JavaScript Difference between single quotes and double quotes in Javascript I scoured this site and did some internet sleuthing (in that order...) trying to find the answer to this burning q ...

"After clicking the button for the second time, the jQuery on-click function begins functioning properly

(Snippet: http://jsfiddle.net/qdP3j/) Looking at this HTML structure: <div id="addContactList"></div> There's an AJAX call that updates its content like so: <div id="<%= data[i].id %>"> <img src="<%= picture %&g ...

Utilizing Ajax and JQuery to invoke a PHP function with parameters

Seeking to implement a record deletion feature using JQuery/Ajax in order to avoid the need for page reload every time a delete action is performed. I have a Movie.php file which acts as a model object for Movie and contains a function called delete_movie ...

Is there a way to retrieve all IDs within an array of objects using a foreach loop and merge the data associated with each ID?

I am currently working on a TypeScript API where I have merged all the data from this API with some additional data obtained from another API function. I have provided a snippet of my code which adds data to the first index of an array. M ...

Steps for displaying a loading gif animation prior to retrieving text content using JavaScript

Before fetching the PHP result, I want a loading GIF image to display within the div section. <!DOCTYPE html> <html> <head> <title> CTR Calculator Tool | Free Click Through Rate Online Calculator </title> & ...

Is it possible to create personalized BBCode?

I currently manage my own forum where users can edit, delete, and report posts and replies. However, I am now looking to add new features such as BBCode. Specifically, I want to implement a [QUOTE][/QUOTE] feature that allows users to easily quote other po ...

Trigger a PHP function with an image's OnClick event

In my PHP class, there is a method called delete. I am trying to call this method when clicking on an image, but the following line of code does not work: echo "<img src='icon/del.gif' onClick='.delete()'/>" I also attempted us ...

Import reactjs modules without the need for Browserify, Webpack, or Babel

I am attempting to set up a TypeScript HTML application in Visual Studio. My goal is to incorporate reactjs v0.14.7 without relying on tools like Browserify. But, how can I utilize the react-dom module in this scenario? Let's set aside TypeScript fo ...

Simple Method to Retrieve one document from Firebase v9 in a React Application

Is it possible to retrieve a document from Firebasev9 using a slug instead of an id with the useDocument Hook? useDocument Hook import { useEffect, useState } from "react" // firebase import import { doc, onSnapshot } from "firebase/firesto ...

Providing static content within the generated code structure by Yeoman for the Angular Fullstack framework

I'm sticking to the code structure generated by Yeoman for an Angular fullstack application. The issue I'm facing is how to include a script called core.js in a file named app.html. <script src="core.js"></script> I can't fi ...