How to project an image onto a sphere using Three.js

Currently, I am using Three.js to work on a project where I have a sphere and I'm attempting to apply this eyeball image here onto it.

The issue I am facing is that the outcome appears stretched, as shown below:

How can I properly map the texture without any distortion?

Below is my code for creating the sphere and applying the texture:

var geometry = new THREE.SphereGeometry(0.5,100,100);
var material = new THREE.MeshPhongMaterial( { map: THREE.ImageUtils.loadTexture('eyeballmap.jpg',THREE.SphericalRefractionMapping) } );
var eyeball = new THREE.Mesh( geometry, material );
eyeball.overdraw = true;
eyeball.castShadow = true;
scene.add( eyeball );

Answer №1

The solution to your query lies within the image you provided a link to.

This image bears resemblance to a MatCap image utilized in spherical environment mapping.

An appropriate shader for this type of environment map would entail using the sphere's normal as the UV index to access the texture map.

<script id="vertex_shader" type="x-shader/x-vertex">

varying vec3 vNormal;

void main() {

    vNormal = normal;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

}

</script>

<script id="fragment_shader" type="x-shader/x-fragment">

uniform sampler2D tex;

varying vec3 vNormal;

void main() {

    vec2 uv = normalize( vNormal ).xy * 0.5 + 0.5;

    vec3 color = texture2D( tex, uv ).rgb;

    if ( vNormal.z < - 0.85 ) color = vec3( 0.777, 0.74, 0.74 ); // back of eye
    
    gl_FragColor = vec4( color, 1.0 );

}

</script>
const uniforms = {
    "tex": { value: texture }   
};

const material = new THREE.ShaderMaterial( {
    uniforms        : uniforms,
    vertexShader    : document.getElementById( 'vertex_shader' ).textContent,
    fragmentShader  : document.getElementById( 'fragment_shader' ).textContent
} );

scene.add( new THREE.Mesh( new THREE.SphereGeometry( 30, 32, 16 ), material ) );

Implemented with three.js version r.147

Answer №2

Your current texture only captures the visible portion of the eye, not the entire sphere. Consider adding white space around your existing texture to account for the unseen parts of the sphere.

Answer №3

By simply changing the size of the image to 1024x512 instead of 512x512, you can achieve the solution without altering any code:

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

However, the original square images actually depict slightly more than half of a sphere: half a sphere is represented by the circle at the center, which has a radius of 256 pixels:

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

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

Steps for removing a click handler from an element and all of its child elements

Is there a way to prevent my #lightbox element from being affected by an event handler attached to the body? $('body :not(#lightbox)').click(function() { $('#lightbox').hide(); }); The Lighbox is positioned in the center. I wa ...

What are the steps to ensure a successful deeplink integration on iOS with Ionic?

Recently, I was working on a hybrid mobile app for Android/iOS using Nuxt 3, TypeScript, and Ionic. The main purpose of the app is to serve as an online store. One important feature involves redirecting users to the epay Halyk website during the payment pr ...

Challenges with Validating Bootstrap Datepicker Functionality

I need to restrict the datepicker input control to only allow selection of dates from the current date onwards. Despite trying to implement validation using the bootstrap-datepicker library and the following JavaScript code, I am still facing issues: $(& ...

If an Angular reactive form component has a particular value

I am working with a group of radio buttons. When a user chooses the option "yes," I would like to display an additional input box on the form. Link to Code Example HTML.component <div formGroupName="radioButtonsGroup" class="form-group col-6 pl-0 pt- ...

jQuery Each Loop failing to retrieve data during iteration

Encountered a peculiar issue while working with an each loop. The situation may seem a bit tangled but I'm constrained to manipulating the code with jQuery due to it being part of a larger framework that can't be modified. As a way to simplify t ...

Angular 2 ngFor generates a collection of rows and columns forming a single large column

It seems that ngfor is generating divs one by one, resulting in a poor design where they are stacked on top of each other. I would like to achieve a layout like this: [1] [2] [3] [4] [5] [6] However, the current outcome looks like this: [ 1 ] [ 2 ] [ 3 ...

Issue arise when utilizing async/await in conjunction with .forEach method

My code is attempting to make a basic request to Redis in order to retrieve all the values (not keys) from my database. However, I am encountering an issue where the tab is being returned before the .forEach function even begins. This is evident because ...

retrieving a promise fails during the set interval

Hey there! I'm currently a computer science student and still getting the hang of things. Recently, I encountered an issue that I can't seem to solve on my own. The problem is related to fetching data from my MongoDB database every few seconds an ...

Adding a collection of items to an array in preparation for organizing

Realizing that sorting objects is not feasible - despite the necessity of having the object values sorted - I conclude that the only option is to move the object array content into a new array for sorting purposes. The following code generates the output ...

Issue with Bootstrap carousel: image protrudes past boundaries of parent container

Struggling with setting up a bootstrap carousel on my page. I want the image to extend beyond the parent div, positioned at the bottom rather than the top. How can I achieve this without disrupting the default carousel behavior? Here's a sketch of how ...

Utilizing Props in Vue.js to Access Data for v-model

After browsing online, I attempted to pass props to data in the following manner: Child Component: props: { idInput: { type: String, required: false }, nameInput: { type: String, required: false }, }, data() { return { id: this.idInput, na ...

Obtaining only a portion of the text when copying and editing it

I have a React application where I am attempting to copy text from an HTML element, modify it, and then send it back to the user. I have been successful in achieving this, but I am facing an issue where even if I select only a portion of the text, I still ...

Tips for effectively utilizing the display: inline property in conjunction with ng-repeat

I am struggling to create a timeline with a broken structure on my website. I suspect that the issue lies in using display:inline. When attempting to apply this to my site: https://i.stack.imgur.com/4Ur7k.png the layout gets distorted: https://i.stack.i ...

Steps to reinitialize the error code after removal from the roster

Currently, I am working on creating a series of textboxes and dropdown menus using jQuery. So far, the add function is functioning smoothly without any glitches. However, my issue lies within the delete function. It works well when deleting sequentially, ...

JavaScript server variable

How can I access a server-side asp.net variable in JavaScript? I'm trying to achieve something like this: function setBookmark(val) { document.getElementById('<%# hBookmark.ClientID %>').value=val; } Is there any way to accomplis ...

using javascript to trigger android function

Looking to create a button in HTML that triggers a call from an Android device via JavaScript. Here is the code snippet I have tried, but it's not functioning as expected. Please note, I am new to Android development: public class MainActivity extend ...

Unlock the Power of Rendering MUI Components in ReactJS Using a For Loop

Hey there! Hope everything is going well. I've been working on a fun project creating an Advent/Chocolate Box Calendar using ReactJS. One challenge I'm facing is figuring out how to iterate over a for loop for each day in December and render it ...

"Creating a dynamic Vue array using computed property from the provided dataset

Let's consider a scenario where data is retrieved from a store: let itemsData=[ {id:1,data:[...]}, {id:2,data:[...]}, {id:3,data:[...]} ] The goal here is to create another array, itemsSelected, that looks like this: let itemsSelected=[ {id:1 ...

Ways to retrieve the value of an Object that may have a key that is undefined

Is there a method similar to Angular's $parse service that can be used for accessing nested object properties? Consider an object structure like this: const obj = { items: [ { store: { type: '' } } ] }; Sce ...

Using Node.js to acquire Steroids.js through downloading

Currently in search of downloading Steroids.js by Appgyver, however I keep encountering an issue: My lack of experience using Node.js makes it difficult to pinpoint the problem, but I suspect it is unrelated to Steroids.js itself. Despite having a version ...