3b1b / 3b1b/manim

Black Texture on Degenerate Surface Regions

未关闭
#2,324 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
bug
主要语言
Python
星标
93.8k
派生
7.7k
PR 合并指标
PR 指标待抓取

描述

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

**Code**:
```py
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](https://github.com/user-attachments/assets/bceb4fb4-5e57-4434-af8f-cbce9f46fcae)

Resolution (11, 11):
![Image](https://github.com/user-attachments/assets/80e84350-34bf-4196-a797-dd59f4d8da10)

### 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:
```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](https://github.com/user-attachments/assets/f1ca714f-33b4-4ac8-90b7-748bfcca9bfb)

Resolution (11, 11):
![Image](https://github.com/user-attachments/assets/e372af13-0c32-445a-bd51-e911616bc365)

**Conclusion**

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

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。