Generate a GridGeometry of size 16x16 that is responsive to the viewport dimensions using Three.js

The question is quite simple, I am looking for help to create a specific Three.js and WebGL project.

Although I have a basic understanding of creating a Cube in Three.js and WebGL, I am struggling with a more complex task.

I am currently using this pen as a reference point while learning: https://codepen.io/jackrugile/pen/vOEKzw as it demonstrates the functionality I am aiming for without being dependent on screen size.

var tick = 0,
  smallestDimension = Math.min(window.innerWidth, window.innerHeight),
  viewportWidth = smallestDimension,
  viewportHeight = smallestDimension,
  worldWidth = 100,
  worldHeight = 100,
  rows = 30,
  cols = 30,
  tileWidth = worldWidth / cols,
  tileHeight = worldHeight / rows,
  FOV = 90,
  scene = new THREE.Scene(),
  camera = new THREE.PerspectiveCamera(
    FOV,
    viewportWidth / viewportHeight,
    0.1,
    1000
  ),
  renderer = new THREE.WebGLRenderer({
    antialias: true
  }),
  plane = new THREE.Mesh(
    new THREE.PlaneBufferGeometry(worldWidth, worldHeight, 1),
    new THREE.MeshPhongMaterial({
      color: 0x222222
    })
  ),
  cubes = new THREE.Object3D(),
  spotLight = new THREE.SpotLight(0xffffff),
  ambientLight = new THREE.AmbientLight(0x666666);

renderer.setSize(viewportWidth, viewportHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;

scene.add(plane);
scene.add(cubes);
scene.add(spotLight);
scene.add(ambientLight);

for (var x = 0; x < cols; x++) {
  for (var y = 0; y < rows; y++) {
    var width = tileWidth,
      height = tileHeight,
      dx = (cols / 2 - x),
      dy = (rows / 2 - y),
      depth = 1 + (20 - Math.sqrt(dx * dx + dy * dy)) / 4,
      xBase = -worldWidth / 2 + x * tileWidth + tileWidth / 2,
      yBase = -worldHeight / 2 + y * tileHeight + tileHeight / 2,
      zBase = depth / 2,
      cube = new THREE.Mesh(
        new THREE.BoxGeometry(width, height, depth),
        new THREE.MeshPhongMaterial({
          color: 'rgb(' + ~~((y / rows) * 255) + ', ' + ~~((x / cols) * 255) + ', 255)',
          shininess: 50
        })
      );
    cube.position.set(
      xBase,
      yBase,
      zBase
    );
    cube.castShadow = true;
    cube.receiveShadow = true;
    cube.zBase = zBase;
    cube.zScaleTarget = 1;
    cubes.add(cube);
  }
}

plane.position.set(0, 0, 0);
plane.castShadow = false;
plane.receiveShadow = true;

camera.position.set(0, 0, 100);

spotLight.position.set(0, 0, 100);
spotLight.castShadow = true;
spotLight.shadowCameraNear = 0.1;
spotLight.shadowMapWidth = 2048;
spotLight.shadowMapHeight = 2048;
spotLight.shadowDarkness = 0.1;

function step() {
  spotLight.position.x = Math.sin(tick / 100) * (worldWidth / 2);
  spotLight.position.y = Math.cos(tick / 100) * (worldHeight / 2);

  cubes.traverse(function(cube) {
    if (cube instanceof THREE.Mesh) {
      if (Math.abs(cube.scale.z - cube.zScaleTarget) > 0.001) {
        cube.scale.z += (cube.zScaleTarget - cube.scale.z) * 0.05;
      } else {
        cube.zScaleTarget = 1 + Math.random() * 10;
      }
      cube.position.z = cube.geometry.parameters.depth / 2 * cube.scale.z;
    }
  });

  tick++;
}

function render() {
  renderer.render(scene, camera);
}

function loop() {
  requestAnimationFrame(loop);
  step();
  render();
}

loop();

document.body.appendChild(renderer.domElement);
body {
  background: #000;
  overflow: hidden;
}

canvas {
  bottom: 0;
  display: block;
  left: 0;
  margin: auto;
  position: absolute;
  right: 0;
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

worldWidth = 100,
worldHeight = 100,
rows = 30,
cols = 30,
tileWidth = worldWidth / cols,
tileHeight = worldHeight / rows,

It appears that these values are used to determine the size of the tiles later utilized in the loop:

...
var width = tileWidth,
    height = tileHeight,
    dx = ( cols / 2 - x ),
    dy = ( rows / 2 - y ),
    depth = 1 + ( 20 - Math.sqrt( dx * dx + dy * dy ) ) / 4,
    xBase = -worldWidth / 2 + x * tileWidth + tileWidth / 2,
    yBase = -worldHeight / 2 + y * tileHeight + tileHeight / 2,
...

How can I draw these tiles across the entire viewport similar to this image: https://i.sstatic.net/fxYhV.jpg

Thank you!

Answer №1

Instead of using Math.min, consider replacing it with the following in line 2:

smallestDimension = Math.max( window.innerWidth, window.innerHeight )
. This will dynamically adjust to your screen size. Feel free to modify rows = 10 and col = 10 as needed.

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

Using THREE.js: Object3D Dimension Shrinkage

Is there a way to disable sizeAttenuation for an Object3D in THREE.js? I'm working on rendering a trajectory at a massive scale using arrow helpers to show the motion direction. I want the arrow heads to maintain their orientation without changing si ...

Durable Container for input and select fields

I need a solution for creating persistent placeholders in input and select boxes. For instance, <input type="text" placeholder="Enter First Name:" /> When the user focuses on the input box and enters their name, let's say "John", I want the pl ...

Vue.js Class-based Decorator not Transmitting Event from Child to Parent Component

I'm fairly new to working with Vue.js and I've encountered an issue with the child to parent emit functionality. Essentially, I have a Box component that contains a Search component. In the Search component, I attempted the following: @Watch("se ...

Adding a mesh to a group object in Threejs while the scene is running does not display the mesh

While working on a ThreeJS scene, I encountered an issue when trying to add a mesh using an onclick event. The mesh appears as expected when added to the scene object directly. However, when attempting to add it to an existing group within the scene, the b ...

Is it possible to develop custom decorators for the express router?

Seeking to streamline and enhance the readability of my code, I decided to develop a basic decorator for express router. My starting point: itemRouter .get('/:item_id', async (req, res, next) => { try { const id = pars ...

Categorize a collection of objects based on shared characteristics

I am in need of the count for the current week only. Specifically, I want to calculate monthly totals with a breakdown per week. Currently, I can retrieve the weekly count for each month. Now, my goal is to display only the existing weeks. For example, if ...

Is it better to define a function within useEffect or externally?

What is the reason behind defining the fetchData function inside the useEffect instead of outside? Link: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-faunadb/lib/useFetch.js import { useState, useEffect } from 'react' exp ...

Tips for integrating both client-side and server-side validation techniques in your web application

After conducting some research, I have come across information indicating that it is feasible to implement both client-side and server-side validation simultaneously. However, my focus is not solely on learning JavaScript; I am also interested in utilizi ...

Is there a way to retrieve JSON data from a different domain and incorporate it into my own website?

I am attempting to utilize JSON data from "" and display the data on my website. My goal is to extract the JSON field name "Stats" and retrieve the sub-field name '\"v\"'. You can refer to the documentation provided by purpleair here: h ...

"Utilize JavaScript (Observer) to pick out an SVG element based on its class

I am working on dynamically displaying an SVG item as it enters the viewport using an observer. The animation associated with the SVG item should only play when it becomes visible in the view window. Initially, I have set the display property to none, and ...

Looking to duplicate the elements with the click of a button?

I am in need of assistance with my registration form. My goal is to move the elements contained within the <fieldset> tags to the end of a row when the user clicks the + button. The result you see initially has been recreated. Thank you for your s ...

Modifying `msg.sender` in Solidity and Ether.js

I have a Smart Contract written in Solidity. Within this contract, there is a function called makeMarketItem. function makeMarketItem( address nftContract, uint256 tokenId, uint256 price ) public payable nonReentrant { IERC721(nftContract). ...

The information retrieved from the open weather map API is difficult to interpret

Currently experimenting with the Open Weather Map API. Two specific calls are being examined, one for London and another for Hermanus in South Africa. Noticing differences in the data returned from each call. Below are the two API calls: Data returned fo ...

A directional light in three.js does not adjust based on the size of the object it is illuminating

As I have a DirectionalLight nested within an Object3D, I've noticed that when I adjust the scale of the object, the light's behavior doesn't match my expectations. It seems to cast shadows at varying depths instead of sticking to the scaled ...

Determining the precise mouse location within child elements regardless of zoom level, scrolling, or dimension changes

My goal is to accurately determine mouse coordinates within the page elements. To see the code in action, please visit: http://jsfiddle.net/t8w9k6gu/ $('#p1, #p2, #p3').on('click mousemove touchmove', function(ev){ var target = ...

A guide on eliminating repetitions from an array of objects by utilizing the spread operator

I am working with an object array that has a unique key called "id": var test = [ {id: 1, PlaceRef: "*00011", Component: "BATH", SubLocCode: "BAT", BarCode: ""}, {id: 2, PlaceRef: "*00022", Component: "BAXI10R", SubLocCode: "KIT", BarCode:""}, {id: ...

Creating a Unique Navigation Bar Design in Bootstrap 4 with Custom Styling for Active

I have successfully added a navigation bar to my page, but I am currently facing issues with the active state. I want the navigation item to be underlined when it is active (when I am on that page) or when it is hovered over, and I also want brackets added ...

How can I turn off credential suggestions in a React JS application?

Is there a way to disable managed credential suggestion on a React JS web page using a browser? I have tried using the autoComplete=off attribute and setting editable mode with an onFocus event, but the password suggestions are still appearing. Any help wo ...

A pair of iterations of the same design

It may sound strange, but I find myself in a situation where I need to have two versions of the same model in my Node.js application. Let me try to explain. I am required to create two different account types, one for job seekers and one for employers. Th ...

After closing, the position of the qtip2 is being altered

I've successfully integrated the qtip2 with fullcalendar jQuery plugin, which are both amazing tools. However, I'm encountering an issue with the positioning of the qtip. Here's the code snippet I'm using: $(window).load(function() { ...