Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird artifacts with MeshPhysicalMaterial on the sphere primitive when ANISOTROPY > 0 #28341

Closed
holographicGirl opened this issue May 11, 2024 · 8 comments
Milestone

Comments

@holographicGirl
Copy link

holographicGirl commented May 11, 2024

Description

If I apply a MeshPhysicalMaterial to a sphere I get weird reflections for certain values of specular, roughness, metallic, when the anisotropy is > 0.
I pasted an example below where you can see these reflections are very smooth on the cube and the quad (floor) but on the sphere they look as if I am using flat shading (which I am not).
In the example I am using:

        // Material with anisotropy
        var mat = new THREE.MeshPhysicalMaterial({
            color: 0xffffff,
            roughness: 0.3,
            specularIntensity: 1.0,
            metalness: 1.0,
            clearcoat: 0.0,  // Added for physical appearance
            clearcoatRoughness: 0.1,
            anisotropy: 1,   // Set anisotropy
            anisotropyDirection: new THREE.Vector2(0, 1),  // Set the anisotropy direction
            anisotropyRotation: 90 * Math.PI / 180,
        });

I see these "artifacts" only when the anisotropy is > 0

Does anyone have any idea why I get this only on the sphere and what is it caused by?

Reproduction steps

Use the html code below as the example

  1. copy the code in an HTML file and open it
  2. play with different values of roughness, anisotropy, metallic, specular to see how this reflections changes (on the sphere)

Code

<!DOCTYPE html>
<html>
<head>
    <title>Three.js Simple Scene with Orbit Controls</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.164.1/three.module.js"></script> -->
    <!-- <script src="https://raw.githubusercontent.com/mrdoob/three.js/r164/examples/jsm/controls/OrbitControls.js"></script> -->
    <script type="module">
        // import { OrbitControls } from 'https://raw.githubusercontent.com/mrdoob/three.js/r164/examples/jsm/controls/OrbitControls.js';
        import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.164.1/three.module.js';
        // Scene setup
        var scene = new THREE.Scene();
        scene.background = new THREE.Color("rgb(128,128,128)");

        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // Adding Orbit Controls
       //var controls = new THREE.OrbitControls(camera, renderer.domElement);

        // Material with anisotropy
        var mat = new THREE.MeshPhysicalMaterial({
            color: 0xffffff,
            roughness: 0.3,
            specularIntensity: 1.0,
            metalness: 1.0,
            clearcoat: 0.0,  // Added for physical appearance
            clearcoatRoughness: 0.1,
            anisotropy: 1,   // Set anisotropy
            anisotropyDirection: new THREE.Vector2(0, 1),  // Set the anisotropy direction
            anisotropyRotation: 90 * Math.PI / 180,
        });

        // Plane
        var planeGeometry = new THREE.PlaneGeometry(5, 5);
        var plane = new THREE.Mesh(planeGeometry, mat);
        plane.rotation.x = -Math.PI / 2;
        scene.add(plane);

        // Sphere
        var sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);
        var sphere = new THREE.Mesh(sphereGeometry, mat);
        sphere.position.y = 0.5;
        scene.add(sphere);
        // sphereGeometry.computeTangents();

        // Cube
        var cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
        var cube = new THREE.Mesh(cubeGeometry, mat);
        cube.position.x = 2;
        cube.position.y = 0.5;
        scene.add(cube);

        // Point light
        var light = new THREE.PointLight(0xffffff, 1, 100);
        light.position.set(0, 2.5, 3);
        light.power = 30;
        scene.add(light);

        // Camera position
        camera.position.x = 1;
        camera.position.z = 4;
        camera.position.y = 1.2;
        camera.rotation.x = -Math.PI / 5;

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);
            // controls.update();  // only required if controls.enableDamping = true, or if controls.autoRotate = true
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>
</html>

Live example

Screenshots

Screen Shot 2024-05-11 at 15 03 57

Version

r164

Device

Desktop

Browser

Chrome

OS

MacOS

@Spiri0
Copy link
Contributor

Spiri0 commented May 12, 2024

I think the THREE.MeshPhysicalMaterial doesn't have a phong, but I'm not sure.
The reason why your sphere looks like that is because you can see the triangles because of the missing phong. Since the other non-curved objects all have the same surface normal vector, this effect does not occur for them.
So these are not artefacts, but rather a rendering carried out strictly according to the surface normals, i.e. very physical. Probably more physical than you would like.
As mentioned, I'm not sure about the presence or absence of the phong value in the physicalMaterial, but if it's really the case as I suspect that from a really proper physical point of view there is no phong in the physicalMaterial, then you need to do this with your own shader

@holographicGirl
Copy link
Author

holographicGirl commented May 12, 2024

I am not sure what you mean by not having a phong.

I forgot to mention that I see these artifacts on the sphere but not on the cylinder, which is also curved (and I was pretty surprised)

@Spiri0
Copy link
Contributor

Spiri0 commented May 12, 2024

I've now made myself a little smarter and yes, the MeshPhysicalMaterial has phong and usually looks very smooth. I've now made a CodePen myself with r164 ​​and used something from the three.js example about physicalMaterial.

https://codepen.io/Spiri0/pen/VwOYXXo

This looks nice and smooth until I set the anisotropy value from 0 to a number.
On the left the sphere with anisotropy: 0
and on the right the sphere with anisotropy: 1

It's the same with r160. I admit I don't know why that is. One of the developers will certainly know that

@holographicGirl
Copy link
Author

Thanks a lot for testing it out too!

I hope someone knows what's going on and will help :)

@holographicGirl holographicGirl changed the title Weird artifacts with MeshPhysicalMaterial on the sphere primitive Weird artifacts with MeshPhysicalMaterial on the sphere primitive when ANISOTROPY > 0 May 12, 2024
@holographicGirl
Copy link
Author

holographicGirl commented May 12, 2024

It must be related to the anisotropy code, since even if I modify this code in WebGLMaterials.js:

		if ( material.anisotropy > 0 ) {

			uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );

			if ( material.anisotropyMap ) {

				uniforms.anisotropyMap.value = material.anisotropyMap;

				refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform );

			}

		}

and I comment if ( material.anisotropy > 0 ), I see these artifacts even just setting the anisotropy to 0.

@WestLangley
Copy link
Collaborator

Duplicate of #27440

anisotropy requires tangents, and if the geometry does not have them, there are other conditions. See the glTF spec.

Add this:

geometry.computeTangents();

@Spiri0
Copy link
Contributor

Spiri0 commented May 12, 2024

Ah, that's it thanks WestLangley. I added the tangent calculation to the CodePen example and it looks clean.

https://codepen.io/Spiri0/pen/VwOYXXo

Screenshot_20240513_011753_Chrome

@holographicGirl
Copy link
Author

Thanks a lot @WestLangley !! Makes sense :)

@Mugen87 Mugen87 closed this as not planned Won't fix, can't repro, duplicate, stale May 13, 2024
@Mugen87 Mugen87 added this to the r165 milestone May 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants