Guide on creating a repeating displacement map in three.js

When working with a three.js rendering, I have a small texture that I need to repeat multiple times. This texture includes various maps such as the map itself, a displacement map, a normal map, an ambient occlusion map, and a specular map. Everything looks fine when the pattern is repeated only once in both the x and y directions, showing the expected displacements.

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

However, if I increase the repeat values to more than 1, all the maps seem to scale correctly except for the displacement map. It doesn't repeat as expected and remains the same as the previous image.

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

Here is a code snippet that demonstrates how these maps are applied to a plane:

///////////////////////////////////////////////
// create a textured plane for testing

xRep = 1;
yRep = 1;

var loader = new THREE.TextureLoader();
var tex = loader.load('images/img.png');
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.repeat.set(xRep, yRep);

var nloader = new THREE.TextureLoader();
var ntex = loader.load('images/img-normal.png');
ntex.wrapS = ntex.wrapT = THREE.RepeatWrapping;
ntex.repeat.set(xRep, yRep);

var aloader = new THREE.TextureLoader();
var atex = aloader.load('images/img-ao.png');
atex.wrapS = atex.wrapT = THREE.RepeatWrapping;
atex.repeat.set(xRep, yRep);

var dloader = new THREE.TextureLoader();
var dtex = dloader.load('images/img-v003-disp.png');
dtex.wrapS = dtex.wrapT = THREE.RepeatWrapping;
dtex.repeat.set(xRep, yRep);

var sloader = new THREE.TextureLoader();
var stex = sloader.load('images/img-v003-spec.png');
stex.wrapS = stex.wrapT = THREE.RepeatWrapping;
stex.repeat.set(xRep, yRep);

var faceMaterial = new THREE.MeshPhongMaterial({
  color: 0xa0a0a0,
  shininess: 30,
  //map               : tex,  
  //bumpMap           : tex,
  //bumpScale         : 1,
  displacementMap: dtex,
  displacementScale: 10,
  normalMap: ntex,
  //normalScale       : (1,1),
  aoMap: atex,
  //aoMapIntensity    : 1,
  specularMap: stex
    //_last: 0
});

face = new THREE.Mesh(new THREE.PlaneGeometry(50, 50, 256, 256),
  faceMaterial);
face.position.z = 50;
face.receiveShadow = true;
face.castShadow = true;

scene.add(face);

Is there a way to modify this code snippet so that the displacement map repeats just like the other maps?

Note: The issue with the displacement map not repeating properly may be related to the discussion in issue #7826 on GitHub.

Answer №1

Want your displacement map to repeat, but it doesn't work as expected in the current version of three.js.

To make it repeat 3 times, adjust the UVs of your geometry accordingly.

To achieve this using PlaneBufferGeometry, you can follow these steps:

var uvs = geometry.attributes.uv.array;

for ( var i = 0; i < uvs.length; i ++ ) uvs[ i ] *= 3;

If you need to adjust other textures, remember to scale their repeat values like this:

texture.repeat.set( 1 / 3, 1 / 3 );

If you are modifying the buffer geometry UVs after rendering once, ensure to update them with:

mesh.geometry.attributes.uv.needsUpdate = true;

Don't forget to check out this helpful post.

Updated for three.js r.79

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

Tips for sending the ampersand character (&) as a parameter in an AngularJS resource

I have an angular resource declared in the following manner: angular.module('xpto', ['ngResource']) .factory('XPTO', function ($resource, $location) { var XPTO = $resource($location.protocol() + '://' + $locatio ...

Limits on zooming with THREE.js Orbit controls

I've encountered an interesting limit while using Orbit controls. The zooming functionality is tied to the radius of the spherical coordinates of the camera in relation to the orbiting axis. Here's how it functions: Whenever the user scrolls, t ...

Is it possible for an object to be null even when its type is object

There's an issue that I can't seem to replicate. Personally, I'm not experiencing any errors but bugsnag reports that some users are encountering them. Take a look at snippet line 6 for more information. let lang = this.$store.state.lang ...

Trouble updating Kendo DropDown in Internet Explorer

Having an issue with updating a Kendo DropDownList through a javascript function. It works fine in FireFox and Chrome, but not in Internet Explorer. @(Html.Kendo().DropDownList() .Name("myDDL") .HtmlAttributes(new { style = "width: 320px" }) . ...

What is the process for adjusting the position following the modification of a table value in React?

In my React UI, I have set up two text fields for entering values. After saving the values, they are displayed in a table below (designed with antd). When I click on a record in the table to edit it, I want the data from that record to populate the text f ...

Customized Values in AngularJS Slider

My slider currently has values ranging from 1 to 10, but I want to change them to 1 Lakh, 2 Lakhs, 3 Lakhs, 5 Lakhs, 10 Lakhs, and more than 10 Lakhs. How can I adjust the value set to display this text instead? I have incorporated rg-slider into my code ...

JS issue: Having trouble accessing the array values despite the array being present

I am working on an ajax call where I save the success data in an array. However, when I try to access that data outside of the ajax function and use console to log my array, it appears as expected. Here is a glimpse at what I see on the screen: https://i ...

An unexpected { token error was encountered by Jest while running a React application

I am facing a persistent issue that I just can't seem to resolve. Despite trying numerous solutions found online, nothing seems to fix it. Below are the configurations: package.json { "scripts": { "test": "jest --no-cache", ...

Is there a way to incorporate the 'window' into middleware when using Express?

I am using middleware to retrieve data from a cookie with the help of vue-cookies. try { if (window.$cookies.get('region')) { res.setHeader('Set-Cookie', [ `region=${window.$cookies.get('region')};pat ...

The Vue property or method is unrecognized when utilizing the non-minified version

When I attempted to display the name 'John' using an inline template in a simple Vue example, I encountered the following error message: [Vue warn]: Property or method "name" is not defined on the instance but referenced during render. ...

How can you create a table cell that is only partially editable while still allowing inline JavaScript functions to work?

Just a few days back, I posted a question similar to this one and received an incredibly helpful response. However, my attempt at creating a table calculator has hit a snag. Each table row in a particular column already has an assigned `id` to transform t ...

Tips for transferring information between two distinct ports within a single application

I have been utilizing the expressjs library for my project. It functions as a server on localhost:8000 and I am displaying static pages through it. However, my application operates on localhost:4200. Despite attempting to share the same cookie or localSt ...

Strategies for resolving a mix of different data types within a single parameter

Here, I am setting up the options params to accept a value that can either be a single string or another object like options?: string[] | IServiceDetail[] | IServiceAccordion[]; However, when attempting to map these objects, an error is encountered: Prope ...

The value on the input of a custom Vue component does not update as expected when using v

I'm currently working on a custom component called customCombobox. It functions similarly to a regular v-combobox, but with an added feature - after the user presses the tab key, it automatically selects the first option available. Everything in my i ...

What is the method for providing external parameters to a JOI extension?

Perhaps JOI may not be the ideal tool for this particular task, but I am interested in utilizing it if feasible. Essentially, I have a scenario where a user is sending a request to an API to store specific metric data. Certain metrics are restricted based ...

Load information from a JavaScript object when the user clicks dynamically

My challenge involves utilizing a JavaScript object that contains video information such as title and source URL. Within my HTML, I have image placeholders and the goal is to trigger a modal pop-up (using Twitter Bootstrap modal) of the specific video when ...

What is the best way to trigger the download of an image file created by PHP to a user's computer?

My PHP code (upload.php) allows users to upload an image from index.html, resize it, add a watermark, and display it on the same page. Users can download the watermarked image by using the 'Save image as...' option. The resized image is saved in ...

JavaScript Popup Box Failing to Trigger

Snippet of Code: <form method="post" id="cp_ind_form"> // several input fields here... <input type="submit" name="update_submit" value="Update" /> <input type="submit" name="delete_submit" value="Delete" onclick="deleteConfi ...

Having trouble with Vue.js not returning HTML elements from methods properly?

I have been attempting to retrieve html elements from a method, and I thought of using v-html for this purpose (not sure if there is a better approach). However, I seem to have encountered an issue with backtick templates and string interpolation. An error ...

The Socket.io application is facing deployment issues on the Heroku platform

I have developed a simple chat server using nodejs, socket.io, and express, and now I am attempting to deploy it on Heroku using my Git repository. However, when I access the Herokuapp website for my application (), the display is not as expected: https:/ ...