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

Black Texture on Degenerate Surface Regions #2324

Open
TiagoMLucio opened this issue Mar 14, 2025 · 1 comment
Open

Black Texture on Degenerate Surface Regions #2324

TiagoMLucio opened this issue Mar 14, 2025 · 1 comment
Labels

Comments

@TiagoMLucio
Copy link

Describe the bug

The texture does not render correctly on certain TexturedSurfaces (Sphere, Cone, Disk3D). In specific areas it appears completely black.

Code:

from manimlib import *


class SurfaceExample(Scene):
    CONFIG = {
        "camera_class": ThreeDCamera,
    }

    def construct(self):
        frame = self.camera.frame
        frame.set_euler_angles(
            theta=55 * DEGREES,
            phi=70 * DEGREES,
        )

        sphere = Sphere(radius=2.5, resolution=(4, 4))

        texture = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Whole_world_-_land_and_oceans.jpg/1280px-Whole_world_-_land_and_oceans.jpg"
        earth = TexturedSurface(sphere, texture, opacity=0.9)

        sphere.shift(LEFT * 3)
        earth.shift(RIGHT * 3)

        self.play(FadeIn(sphere))
        self.play(FadeIn(earth))

        self.wait()

Wrong display or Error traceback:

It is mainly noticeable in surfaces with low resolution:

Resolution (4, 4):
Image

Resolution (11, 11):
Image

Additional context

The issue occurs at surface points where one of the derivative vectors is degenerate:

point − du_point = 0 or point − dv_point = 0

Potential Fix

I added a conditional check in the texture_surface shader to detect du or dv with zero lengths, in which case the unit_normal must be calculated in a different way.

shaders/textured_surface/vert.glsl:

#version 330

in vec3 point;
in vec3 du_point;
in vec3 dv_point;
in vec2 im_coords;
in float opacity;

out vec3 v_point;
out vec3 v_unit_normal;
out vec2 v_im_coords;
out float v_opacity;

#INSERT emit_gl_Position.glsl
#INSERT get_unit_normal.glsl

void main(){
    v_point = point;
    vec3 du = du_point - point;
    vec3 dv = dv_point - point;

    if(length(dv) < 1e6 || length(du) < 1e-6){
        v_unit_normal = normalize(point);
    } else {
        v_unit_normal = normalize(cross(normalize(du), normalize(dv)));
    }

    v_im_coords = im_coords;
    v_opacity = opacity;
    emit_gl_Position(point);
}

The analytical normal of a sphere was used in the fallback case.

Results

Resolution (4, 4):
Image

Resolution (11, 11):
Image

Conclusion

I am not sure if this was the ideal solution, but it is working perfectly for various resolutions and surfaces now!

@Varniex
Copy link
Contributor

Varniex commented Mar 21, 2025

I guess this has been resolved with the latest commit. I tested your code with the resolution (4, 4), and I didn't encounter any black space / texture.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants