What is the best way to adjust the size of a 3D Cube in WebGL GLSL without affecting its center point?

I have a scaling attribute that I am applying to various instances of an instanced buffered geometry in Three.js. The shader code appears as follows:

attribute float scale;

uniform vec3 uMeshPosition;

void main() {
  vec3 pos = position;
  pos.x *= (uMeshPosition.x - pows.x) * scale + uMeshPosition.x;
  pos.z *= (uMeshPosition.z - pos.z) * scale + uMeshPosition.z;
  pos.y *= (uMeshPosition.y - pos.y) * scale + uMeshPosition.y;

  gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}

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

Z represents the height in this case!!!

I want the scaled cubes to maintain their original center as indicated by the wireframe cube above.

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

Is it possible to apply scaling on all three axes without computing and applying the scale on the CPU?

Updates:

The method I use to create the Geometry, typically with multiple cubes, but for this instance, it will be just one:

 const createInstancedGeometry = (instanceCount, sizeX = 1, sizeY = 1, sizeZ = 1) => {
  const geometry = new InstancedBufferGeometry()
  geometry.maxInstancedCount = instanceCount

  const shape = new BoxBufferGeometry(0.1 * sizeX, 0.1 * sizeY, 0.1 * sizeZ)
  shape.translate(0, 0.4, 0)

  const data = shape.attributes

  geometry.addAttribute('position', new BufferAttribute(new Float32Array(data.position.array), 3))
  geometry.addAttribute('uv', new BufferAttribute(new Float32Array(data.uv.array), 2))
  geometry.addAttribute('normal', new BufferAttribute(new Float32Array(data.normal.array), 3))
  geometry.setIndex(new BufferAttribute(new Uint16Array(shape.index.array), 1))
  shape.dispose()

  createInstancedAtrributes(geometry, instanceCount)

  return geometry
}

This is how I set up the shader, although I'm not yet utilizing colors.

const createShader = () => {
  const uniforms = {
    // uMap: { type: 't', value: null },
    uColor1: { type: 'c', value: new Color(0x961800) }, // red
    uColor2: { type: 'c', value: new Color(0x4b5828) }, // yellow
    uMeshPosition: { type: 'vec3', value: new Vector3(0, 0, 0) },
  }

  const shader = new ShaderMaterial({
    uniforms,
    vertexShader,
    fragmentShader,
    blending: AdditiveBlending,
    transparent: true,
    depthWrite: false,
  })

  return shader
}

The constructor for my Particle Fire is structured like this:

constructor({ sizeX = 1, sizeY = 1, sizeZ = 1 } = {}) {
    const instanceCount = 1
    const geometry = createInstancedGeometry(instanceCount, sizeX, sizeY, sizeZ)
    const material = createShader()

    const mesh = new Mesh(geometry, material)
    mesh.frustumCulled = false

    this.geometry = geometry
    this.material = material
    this.mesh = mesh

    mesh.up = new Vector3(0, 0, 1)
    mesh.position.set(2, 2, 1)
    mesh.rotateX(Math.PI / 2)

    this.instanceCount = instanceCount

    const lineGeo = new EdgesGeometry(geometry) // or WireframeGeometry
    const mat = new LineBasicMaterial({ color: 0xffffff, linewidth: 2 })
    const wireframe = new LineSegments(lineGeo, mat)
    this.mesh.add(wireframe)
  }

And the update function looks like this:

update() {
    const { instanceCount } = this
    const { scale, progress, randoms } = this.geometry.attributes
    const { uMeshPosition } = this.material.uniforms
    uMeshPosition.value = this.mesh.position

    for (let i = 0; i < instanceCount; i += 1) {
      let value = progress.array[i]
      value += 0.025

      if (value > 1) {
        value -= 1
        scale.setX(i, randomValueBetween(0.3, 2, 3))
        // randoms.setX(i, randomValueBetween(0, 1, 3))
      }

      // progress.setX(i, value)
    }


    scale.needsUpdate = true
    // randoms.needsUpdate = true
    // progress.needsUpdate = true
  }

To add the object to the scene, I do the following:

const pFire = new ParticleFire()
scene.add(pFire.mesh)

To update it within a render loop:

pFire.update({ deltaTime })

renderer.render(scene, cameraController.camera)

requestAnimationFrame(animate)

cameraController.camera refers to a basic camera controller added to the scene as a child to a 'character' that moves around the scene.

configuredCamera = new PerspectiveCamera(
    75, window.innerWidth / window.innerHeight, 0.1, 5000,
  )

Answer №1

The function called translate found in the documentation for THREE.Geometry is responsible for moving each vertex of a mesh. This results in the mesh itself being shifted from its original center point at (0, 0, 0).

It is important to note that you should adjust the geometry's position instead using position. You can refer to THREE.Object3D for more information.

This means that you need to remove the line shape.translate(0, 0.4, 0) and handle the positioning entirely through geometry.position. By doing so, the mesh will maintain its original placement without any displacement, with positioning handled by the modelViewMatrix alone. This adjustment will make the GLS shader code function correctly:

gl_Position = projectionMatrix * modelViewMatrix * vec4(pos * scale, 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

What is the best way to confirm if the elements in an array are in consecutive order?

Is there a way to determine if an array's members are consecutive? For instance, the array [1,3,4,5,6] is not considered consecutive because it is missing the number 2 in the sequence. Which JavaScript array methods can be used to check for this type ...

Postpone reloading automatically if a division is in view

I endeavored to develop a small project aimed at monitoring flights passing over my vicinity. Utilizing the flight-radar24 API python package, I managed to extract the necessary data. Subsequently, I designed a systemd service to execute my python script ...

jQuery: Repeated Triggering of Button Click Event

At my website, I am facing an issue with multiple buttons being loaded twice via ajax from the same file. The problem arises when the event associated with a button fires twice if that same button is loaded twice. However, it functions correctly if only o ...

Using useCallback with an arrow function as a prop argument

I'm having trouble understanding the code snippet below <Signup onClick={() => {}} /> Upon inspecting the Signup component, I noticed the implementation of useCallback as follows const Signup = ({onClick}) => { const handleClick = us ...

Exploring the search functionality within Meteor JS

As a newcomer to databases and search functionality, I am exploring how to implement a search feature in my Meteor app. After browsing through atmosphere, I found these 4 options: Mattodem easy search Search Source Elastic search package on Atmosphere (h ...

The hamburger menu for mobile devices is not functioning properly on the website's mobile version, however it operates correctly when the screen is resized

Currently, I am facing an issue with the hamburger menu not responding on my mobile device. Oddly enough, it does work when I resize my browser window to mimic a mobile size. There seems to be a glitch happening, but I'm struggling to pinpoint the exa ...

Performing an AJAX call using the PUT method to update information in the

I am facing difficulties when trying to call my REST api from JavaScript, as I keep receiving either a Bad Request or an Unsupported Media Type error depending on my testing... Here is my Servlet code: /** * Update an existing frame * * @ ...

html displaying dynamic data in a table

As a beginner in coding, I am attempting to create a dynamic table. The first column is working fine with each new cell being added to the top. However, when I try to add columns, they fill from top to bottom instead of mirroring the first column. I want m ...

Updating field based on dropdown value in CakePHP 3.6.11

I have the following tables: customers[id, name, surname, phone, text, balance, created] service_types[id, title, price, length, is_subscription, created] customer_service_types[id, customer_id, service_type_id, price, created] Within the add.ctp file o ...

ReactJs: How useEffect is invoked before onClick function in NextJS

I am facing an issue with a button in my Next project. Here is the code for the button: <Button minWidth={'140px'} onClick={() => exec(scope)} >Save</Button> When this button is clicked, it triggers the following function: c ...

Retrieving information from Prismic API using React Hooks

I'm having trouble querying data from the Prismic headless CMS API using React Hooks. Even though I know the data is being passed down correctly, the prismic API is returning null when I try to access it with React Hooks. Here is my current component ...

JS - What is causing my JavaScript src to not work properly?

Here is a snippet of my code: <form name="calculator"> <input type="button" name="latest" value="You are not using the latest version."> <script src="http://www.alvinneo.com/bulbuleatsfood.js"> if(latest-version==="1.0.4.2"){ document.ca ...

"Enhance Your Communication: Utilize setTimeout in Ajax

Hey there, I could really use some help with the setTimeout function in my code. No matter what I try, it just doesn't seem to work. I'm currently working on a chat system where I need to send and receive messages (testing by opening 2 browser ...

Instructions on opening a modal and changing the source of the iframe within the modal

I currently have a modal within my application that is triggered by Bootstrap: <div class="modal full-page fade" tabindex="-1" role="dialog" id="fullpageModal"> <div class="full-page-content"> <button type="button" class="close" d ...

Attempting to render an image onto a canvas and apply Caman.js for image editing purposes

Currently, I have a code snippet that allows me to draw an image onto a canvas. Here is the code: var imageLoader = document.getElementById('imageLoader'); imageLoader.addEventListener('change', handleImage, false); var ...

(NodeJS + Socket IO Issue) NodeJS is sending duplicate data when the page is refreshed, causing an improper response

Each time I refresh a page, NodeJS seems to be repetitively writing data on the socket. Interestingly, the number of writes increases with each page refresh but then stabilizes at three after several refreshes. I urge you to inspect the console output whi ...

The communication hub in a Vue.js application

I'm currently developing a Vue single-page project and I have implemented an empty Vue instance as a central event bus. However, I've encountered an issue when trying to fire an event. eventbus.js import vue from 'Vue' export default ...

What is the reason behind the occurrence of an error when attempting to iterate through an array of objects within my react.js component?

Here is an example of some code: class Stepper extends Component { state ={ quiz_data: [ patient_data: [ {name: "A", age: "1"}, {name: "B", age: & ...

Reposition div when clicked

I have encountered a challenge where I am unable to perform a small task. My goal is to have the position of "div1" change upon clicking on "div2", taking into account that "div2" is nested inside "div1". Additionally, when clicking on "div2" again, "div1" ...

Why React Native's array.map function fails to calculate the sum of a state

I am currently developing a COVID-19 data app for a school project, and I am struggling to sum the total number of tests and positive results from an API. Below is the snippet of code that I am using: function GetDataApi() { if(data !== null) { const ...