Having difficulties in properly connecting faces while UV mapping a cube in Three.js

After successfully applying an image texture to a cube through UV mapping for a photo-sphere viewer, I noticed that thin straight lines are visible where the faces of the cube join.

Interestingly, this issue does not occur when splitting texture tiles via Canvas and using MultiMaterial on the cube.

The comparison image below demonstrates the results obtained from these two different methods of texturing (click for larger view):

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

You can view a live example at CodePen.io

The original image used as the texture can be accessed here

Shown here is the code snippet responsible for the UV mapping process:

function mapCubeUV(geometry, cubeH) {
  
  // function logic
  
}

// More code snippets follow...

Upon inspecting the values generated by the UV mapping function, it appears that everything is in order. The produced UV values correctly correspond with the dimensions of the image. Here's a sample dump:

Face VerticeA   VerticeB   VerticeC 
 0: (    0,1), (    0,0), (0.125,1)
 1: (    0,0), (0.125,0), (0.125,1)
 2: (0.125,1), (0.125,0), ( 0.25,1)
 3: (0.125,0), ( 0.25,0), ( 0.25,1)
 4: ( 0.25,1), ( 0.25,0), (0.375,1)
 5: ( 0.25,0), (0.375,0), (0.375,1)
 6: (0.375,1), (0.375,0), (  0.5,1)
 7: (0.375,0), (  0.5,0), (  0.5,1)
 8: (  0.5,1), (  0.5,0), (0.625,1)
 9: (  0.5,0), (0.625,0), (0.625,1)
10: (0.625,1), (0.625,0), ( 0.75,1)
11: (0.625,0), ( 0.75,0), ( 0.75,1)

Is there an error in my implementation or is there a known issue with Three.js causing this problem?

P.S. This test was based on an example from the Three.js website

P.P.S

A similar question addressing seams on cube edges when using a texture atlas can be found HERE (albeit not related to manual UV map calculations)

Answer №1

After spending some time on the issue and getting a good night's rest, I made an interesting discovery. The problem stems from pixels of adjacent tiles leaking through at the face edges. However, this leakage doesn't occur when the image is divided into smaller independent sections (e.g., via canvas) as the adjacent tile pixels are not copied over.

A solution to this problem involves rearranging the tiles in the source image so that they align with the neighboring tiles when applied to the cube. This way, if any pixels shine through at the edge, they will be the correct ones.

In the case presented, the order of the tiles was initially West-East-Top-Bottom-South-North. The correct order should be East-South-West-North + Top + Bottom.

Nevertheless, there is still an issue with tiles at the sequence's edges where their edges are adjacent to the wrong tiles: * North - its right edge should connect with East * Top - its left edge should align with East, and the right edge with West * Bottom - the left edge connects to West, and the right edge to East

To address this, we need to introduce some space between North, Top, and Bottom. Subsequently, we can copy a narrow vertical strip from the edges of the East & West tiles and paste them next to the edges of North, Top & Bottom. This action will prevent incorrect pixels from shining through.

The link below displays the original image and the intended end-result with added strips marked by blue letters:

https://i.sstatic.net/G1oeT.jpg

Two additional considerations include:

  • Ensuring the image dimensions are powers of two (width and height) to avoid WebGLRenderer complaints
  • Positioning the Top and Bottom tiles' X coordinates such that in UV coordinates they form rational numbers with few decimal places, ensuring the start pixel calculated by WebGL is a whole number (e.g., 4.5*1024 for Top and 6*1024 for Bottom)

A live demonstration showcasing this solution by comparing the two approaches is available at CodePen.io

Due to the tile reordering, adjustments were necessary for the UV mapping function:

function mapCubeUV_v2(geometry, cubeH) {

  // converting all vertices into polar coordinates
  geometry.faceVertexUvs[0] = []; // This clears out any UV mapping that may have already existed on the object

  // walking through all the faces defined by the object
  // ... we need to define a UV map for each of them
  geometry.faces.forEach(function(face) {
  
    ...

  });

  geometry.uvsNeedUpdate = true;

  return(geometry);
}

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

Ways to prevent an array from being reset

My issue involves the clothes and orders tables, along with an array based on Clothes and Orders models. Whenever I add a clothes element into the Orders array and specifically update the amount and price of the selected item, it also updates the Clothes a ...

Create a roster of numbers that are multiples using a systematic approach

Is the following code a functional way to return multiples of 5? function Mul(start,array,Arr) { Arr[start]=array[start]*5; if(start>array.length-2){ return Arr; } return Mul(start+1,array,Arr); } var numbers =[1,2,3,4,5,6 ...

I'm struggling to understand how to interpret this. The v-tab function seems to be generating a button with various properties, but I'm unsure which specific property is related to

The V-tab below generates the button known as the right one on the v-app-bar: https://i.stack.imgur.com/DzNmq.png <v-tab :to="'/demo'" active-class="text--primary" class=&quo ...

Attach the Bootstrap-Vue modal to the application's template

I am implementing a custom modal using bootstrap-vue modal in my project on codesandbox. This is the template structure: <template> <b-button variant="link" class="btn-remove" @click="removeItemFromOrder(index)"> Remove item </b-bu ...

Using a static function within a library's state function in NextJS is throwing an error: "not a function"

Inside a library, there's a special class known as MyClass. This class contains a static method named setData. The contents of the MyClass.js file are shown below: class MyClass { static DATA = ''; static setData(data) { MyClass ...

Choose an element from within a variable that holds HTML code

I have a specific div element that I need to select and transfer to a new HTML file in order to convert it into a PDF. The issue I'm facing is related to using AJAX in my code, which includes various tabs as part of a management system. Just to prov ...

iPhone height is not correct

One issue I faced was when trying to view a webpage in landscape mode on iPhones (specifically testing on model SE, but it appears that many people are experiencing the same problem with other iPhone models). I have created a simple example below, consist ...

Developing a side panel for navigation

My goal is to create a sidebar that shifts to the right from the left side and makes space on the page when the hamburger menu is pressed. I have made progress in achieving this, but I am encountering difficulties with the animation. const btnToggleSide ...

Discovering the presence of line breaks

I have searched extensively on Google, but I am struggling to find a definitive answer. My goal is to create an email simulation where users can input text into a textarea and save it to the database. They should then be able to return to the page later a ...

Setting up web pack with flag-icon-css integration

I have successfully set up a webpack project using https://github.com/teroauralinna/webpack-guide. Now, I am looking to integrate https://github.com/lipis/flag-icon-css into my project. To do so, I followed these steps: npm install flag-icon-css --save T ...

Angular directive compatibility with Mozilla Firefox

I've encountered a strange issue with my directive in Firefox. The directive is designed to limit user input, and it functions correctly in Chrome. However, in Firefox, once the user reaches the input limit, they are unable to delete any characters - ...

What is the best way to change the location of a jQuery Mobile global popup?

I have a jQuery Mobile global popup that is initially empty and generated dynamically. I am utilizing the beforeposition event to detect when the popup opens. At this point, I load a configuration file or content file, create the content, and then add it t ...

Implementing Google Ads Code in NextJS for Automated Units

I'm currently working on a NextJS project and I need to integrate the Google AdSense code for automatic ads. The Google ad code I have is: <script async src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${process.env. ...

I am unable to send back my JSON object

I seem to be having trouble returning a JSON object as all I get is an undefined variable. The code below is supposed to fetch a JSON element from an API. It appears to work within the success: function, but when attempting to use that data elsewhere, it ...

Using Django to load a template and incorporate a loading spinner to enhance user experience during data retrieval

In my Django project, I need to load body.html first and then dashboard.html. The dashboard.html file is heavy as it works with python dataframes within the script tag. So, my goal is to display body.html first, and once it's rendered, show a loading ...

As a newcomer to Javascript, I am currently working on developing a CRUD-based application and could use some assistance with implementing the Edit functionality

I am currently in the process of developing a Javascript CRUD application that showcases data within an HTML Table. I have successfully implemented the Create, Read, and Delete functions. However, for the Edit function, I am looking to display the data in ...

Tips for applying a texture to only one side of a cube without using THREE.MultiMaterial to lower draw calls

Imagine a scenario where there is a cube featuring 2 different materials. While I am utilizing MultiMaterial, I have noticed that it results in 6 draw calls instead of just 2. This concerns me in terms of performance, especially if the project is scaled up ...

In JavaScript, when all values are false in an object, the object's value should be set to False

My task involves working with a JSON data object that contains multiple key-value pairs. I need to determine whether at least one value is false and set another variable to "false" accordingly. Here is the JSON data that I am handling: var objectVal = re ...

Issue with Refresh Triggering Update, localStorage, useState, useEffect Combination

I want my app to execute the code inside the useEffect hook every 5 seconds, regardless of whether the page is refreshed or not. Currently, the code only runs when the page is refreshed and then remains inactive until the page is refreshed again. It seems ...

Covering a doughnut shape with a twisting spiral

I want to achieve a hula hoop covered in tape effect using three.js. The 3D model should look similar to the image below. https://i.sstatic.net/lj9cR.jpg I have been able to create the hoop in 3D space using TorusGeometry and pan around, but I am strugg ...