The edges of the cubemap in THREE.js appear murky

I am attempting to create a black skybox with white dots (stars) in three.js. However, due to the perspective effect, the dots appear darker in the corners where they are further away (as they get smaller and dimmer). Is there a way to make the appearance more uniform so that the corners are not as pronounced?

Here is an example (the camera is focused on one corner):

// setting up the scene
var scene, camera, renderer;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.05, 1000);
camera.position.z = -0.01;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000, 1);
document.body.appendChild(renderer.domElement);

// creating canvas with dots
var canvas, context, texture, geometry, mesh, material, x, y, s, dx, dy;
canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
context = canvas.getContext('2d');
context.fillStyle = 'white';
for (y = 0; y < 512; y += 8) {
    for (x = 0; x < 512; x += 8) {
        s = 1;
        context.fillRect(x, y, s, s);
    }
}

// creating cube with canvas texture 
var texture, material, geometry, mesh;
texture = new THREE.CanvasTexture(canvas);
material = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide});
geometry = new THREE.BoxGeometry(100, 100, 100);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

camera.lookAt(1, 1, 1);
renderer.render(scene, camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.js"></script>

Instead of adjusting the size of the dots based on their distance from the center of the canvas when generating them, I would prefer a solution within three.js framework so that modifying the canvas is unnecessary. The denser distribution of dots in the corner is not an issue here as this demo aims for simplicity, while the actual implementation will have a more uniform dot distribution.

Answer №1

This phenomenon can be seen as a form of visual trickery. Instead of actually darkening the corners, it appears that way due to the use of lower resolution MipMaps in the texture sampling process as the texture size decreases. For example, if you have a single white pixel surrounded by seven black ones, the MipMapping at smaller scales will gradually blend into a predominantly black texture.

To mitigate this issue, one approach is to make the white dots relatively larger compared to their surrounding area. Alternatively, you could disable MipMapping using

texture.minFilter = THREE.LinearFilter;
or NearestFilter, although this might result in a less desired rough-edged appearance. You can explore other Minification Filter options here.

In the code snippet below, I have utilized LinearFilter and a 2px white square. While the visual outcome may not be perfect, it demonstrates both potential solutions:

// Setting up the scene
var scene, camera, renderer;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.05, 1000);
camera.position.z = -0.01;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000, 1);
document.body.appendChild(renderer.domElement);

// Creating the canvas with white dots
var canvas, context, texture, geometry, mesh, material, x, y, s;
canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
context = canvas.getContext('2d');
context.fillStyle = 'white';
for (y = 0; y < 512; y += 8) {
    for (x = 0; x < 512; x += 8) {
        s = 2;
        context.fillRect(x, y, s, s);
    }
}

// Generating a cube with canvas texture 
var texture, material, geometry, mesh;
texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.LinearFilter;
material = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide});
geometry = new THREE.BoxGeometry(100, 100, 100);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

camera.lookAt(1, 1, 1);
renderer.render(scene, camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.js"></script>

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

Display with organized information, Arrange with unprocessed data in DataTables.net

Below is a snippet of the datatables configuration I am working with: { "dom" : "rltip", "processing" : true, "serverSide" : false, "order" : [ [ 1 , "desc" ] ], "searching" : false, data: [ { "column-a" : "Samp ...

What is the process for creating a linked TreeNode in the Ant tree design?

After completing a tree design utilizing Ant Design, I encountered an issue where certain nodes within the tree needed to act as links. Despite my attempts to directly assign links, they were not functioning properly. array.map((node) => { if(node.t ...

Tips for adjusting image hues in Internet Explorer?

I have successfully altered the colors of PNG images in Chrome and Firefox using CSS3. Here is my code: #second_image{ -webkit-filter: hue-rotate(59deg); filter: hue-rotate(59deg); } <img src='http://i.im ...

Crafting a personalized arrow for sorting headers in Angular Material

Currently working on an Angular 5 project and I'm looking to implement a custom sort icon in the header. The goal is to achieve a similar effect to this example, without using the default arrow. I attempted to modify the CSS styles, but it wasn' ...

Does the image alter based on the selection in the dropdown menu?

When I utilize the Templating Example from the select2 library, everything seems to work for the first dropdown value change. The correct image is previewed as expected. However, when trying to change the value a second time, a second image is appended but ...

Creating variables in Typescript

I'm puzzled by the variable declaration within an Angular component and I'd like to understand why we declare it in the following way: export class AppComponent { serverElements = []; newServerName = ''; newServerContent = &apos ...

Despite reaching a video readystate of 4 in HTML5, the video still hangs and does not play smoothly

Using html5, I am currently working with video and audio. I have encountered an issue where sometimes the video hangs even after its readyState === 4. The cause of this problem is unclear to me. I aim for a solution where if the video's readyState = ...

What is the procedure for closing a snackbar when the close button is clicked?

I am having trouble closing a snackbar when the close button is clicked. The snackbar should initially pop up on page load and only close when manually triggered. I have set the timeout to zero, but the snackbar does not close when the close button is clic ...

What is the most efficient way to enable seamless communication between sibling components in Vue.js 2?

Just starting out with Vue.js 2 and I'm really enjoying it so far despite being new to it. Currently using the latest version. I've begun working on my first larger application and ran into a scenario right off the bat where I have a main app co ...

Typescript: The .ts file does not recognize the definition of XMLHttpRequest

I have encountered an issue with a .ts file containing the following code: var xhttp = new XMLHttpRequest(); After running the grunt task to compile the ts files using typescript, no errors were reported. However, when I attempt to instantiate the class ...

What is the best way to combine HTML and JavaScript code within a single JavaScript file?

Is there a way to include a responsive iframe without any scroll in multiple websites by using just one line of code? I found this snippet that seems promising: <script src="testfile.js"></script> The testfile.js contains the necessary HTML a ...

After entering text manually, the textarea.append() function ceases to function properly

I've encountered a puzzling issue with a tiny fiddle I created: https://jsfiddle.net/wn7aLf3o/4/ The scenario is that clicking on 'append' should add an "X" to the textarea. It functions perfectly until I manually input some text in the te ...

What could be causing PHP to fail to send form scores to the PHP MyAdmin database?

I recently ventured into web development and took on a college project website where I built a form in HTML containing various radio button questions. To handle the validation of answers against the correct ones, I utilized JavaScript. With some assistance ...

The element type provided is not valid: it should be a string for built-in components or a class/function for composite components. However, an object was received instead. - React Native

After conducting extensive research, I have been unable to find a solution as to why this issue persists. Can anyone shed some light on what the error might be referring to? Error: Element type is invalid: expected a string (for built-in components) or a c ...

Emphasize sections of text within a chart

Looking for a Specific Solution: I've encountered similar problems before, but this one has a unique twist. What I'm trying to achieve is to search for a substring within a table, highlight that substring, and hide all other rows (tr's) th ...

Guide to importing external CSS styles into Angular 2 using the require method

I'm facing an issue with loading an external css file in different environment files. My setup includes two environments: development and production. Loading the css file locally works fine in development mode, but not in production mode. environment ...

How can we assign priority to the child element for detection by the "mouseover" event in jQuery?

Can you help me figure out how to make the "mouseover" event prioritize detecting the child element over its parent? This is the jQuery code I've been using: <script> $(function() { $("li").mouseover(function(event){ $('#log&a ...

Placing a moveable object in a designated spot for dropping at the desired location

I've been attempting to clone and drop a draggable object at the exact position within a droppable area where the drop event takes place. While I have come across examples online that demonstrate appending draggables to droppables, they all tend to re ...

How can you efficiently update another ng-model value based on a select input in AngularJS using ng-change?

<select data-ng-init="selectedItem='previewWidth = 1920; previewHeight = 1080'" data-ng-model="selectedItem" data-ng-change="GetNewData(); {{selectedItem}}"> <option value="previewWidth = 1920; previe ...

Press the button to access the URL within the current window

Working with Angular, I attempted to develop a function to open a URL in the current window. However, the code below within the controller actually opens a new window: $scope.openUrl = function(url) { $window.open(url); }; ...when using ng-click=&apo ...