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

Shading goes black for meshes featuring locally inverted normals #3755

Open
3 tasks done
Kevin-Mattheus-Moerman opened this issue Apr 1, 2024 · 2 comments
Open
3 tasks done

Comments

@Kevin-Mattheus-Moerman
Copy link

  • are you running newest version (version from docs) ?
  • can you reproduce the bug with a fresh environment ? (]activate --temp; add Makie)
  • What platform + GPU are you on? -> Ubuntu 22.04, NVIDIA T550 Laptop GPU

It looks like there is an interpolation error for color data (and/or shading?) when the normal directions are inverted. This is probably due to normal direction interpolation which will return a zero length vector when interpolating between two adjacent and inverted normal vectors.

Here I inverted the face orientations for half of a sphere. The only thing to see here is that the shading seems to flip to a different state. This looks like the desired behaviour:
Screenshot from 2024-04-01 09-51-28

However, when the normal directions are exactly negated it looks like we get funny behaviour. Here I inverted the faces halfway a quadrilateral plate mesh. As you can see we now get sudden and odd back regions:
Screenshot from 2024-04-01 09-54-50

It looks like perhaps Makie should detect that the interpolation produced a zero length vector, next it should be renormalised and be forced to point in the direction of the closest healthy vertex or face normal.

Below is some code I used to study this, which features simple sets of triangles which produces the following image:
image

using GLMakie
using GeometryBasics

F1 = TriangleFace{Int64}[[1,2,3],[6,4,5]]
V1 = Point3{Float64}[[0.0, 1.0, 0.0], [0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [2.25, 1.0, 0.0], [2.25, -1.0, 0.0],[1.25,0,0]]
C1 = [v[1] for v ∈ V1] # x-coordinates as colors

F2 = TriangleFace{Int64}[[1,2,3],[3,4,5]]
V2 = Point3{Float64}[[0.0, 1.0, 0.0], [0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [2.0, 1.0, 0.0], [2.0, -1.0, 0.0]]
C2 = [v[1] for v ∈ V2] # x-coordinates as colors

F3 = TriangleFace{Int64}[[1,2,3],[5,4,3]]
V3 = Point3{Float64}[[0.0, 1.0, 0.0], [0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [2.0, 1.0, 0.0], [2.0, -1.0, 0.0]]
C3 = [v[1] for v ∈ V3] # x-coordinates as colors

F4 = TriangleFace{Int64}[[1,2,3],[4,5,6]]
V4 = Point3{Float64}[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [1.25, 0.0, 0.0], [1.25, 1.0, 0.0],[2.25, 0.0, 0.0]]
C4 = [v[1] for v ∈ V4] # x-coordinates as colors

F5 = TriangleFace{Int64}[[1,2,3],[3,4,2]]
V5 = Point3{Float64}[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [2.0, 0.0, 0.0]]
C5 = [v[1] for v ∈ V5] # x-coordinates as colors

F6 = TriangleFace{Int64}[[1,2,3],[2,4,3]]
V6 = Point3{Float64}[[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [2.0, 0.0, 0.0]]
C6 = [v[1] for v ∈ V6] # x-coordinates as colors


## Visualization
fig = Figure(size=(800,800))

ax = Axis3(fig[1, 1], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Separate, inverted")
hp = poly!(ax,GeometryBasics.Mesh(V1,F1), color=C1, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

ax = Axis3(fig[1, 2], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Touching, inverted")
hp = poly!(ax,GeometryBasics.Mesh(V2,F2), color=C2, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

ax = Axis3(fig[1, 3], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Touching consistent")
hp = poly!(ax,GeometryBasics.Mesh(V3,F3), color=C3, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

ax = Axis3(fig[2, 1], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Separate,inverted")
hp = poly!(ax,GeometryBasics.Mesh(V4,F4), color=C4, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

ax = Axis3(fig[2, 2], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Touching, inverted")
hp = poly!(ax,GeometryBasics.Mesh(V5,F5), color=C5, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

ax = Axis3(fig[2, 3], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "Touching consistent")
hp = poly!(ax,GeometryBasics.Mesh(V6,F6), color=C6, shading = FastShading, transparency=false,colormap=Reverse(:Spectral),strokewidth=3,strokecolor=:black)

fig
@ffreyer
Copy link
Collaborator

ffreyer commented Apr 2, 2024

We could try doing something like normal = normalize(normal + vec3(1e-6, 0, 0)) at the start of

vec3 blinn_phong(vec3 light_color, vec3 light_dir, vec3 camdir, vec3 normal, vec3 color) {
// diffuse coefficient (how directly does light hits the surface)
float diff_coeff = smooth_zero_max(dot(light_dir, -normal)) +
backlight * smooth_zero_max(dot(light_dir, normal));
// DEBUG - visualize diff_coeff, i.e. the angle between light and normals
// if (diff_coeff > 0.999)
// return vec3(0, 0, 1);
// else
// return vec3(1 - diff_coeff,diff_coeff, 0.05);
// specular coefficient (does reflected light bounce into camera?)
vec3 H = normalize(light_dir + camdir);
float spec_coeff = pow(max(dot(H, -normal), 0.0), shininess) +
backlight * pow(max(dot(H, normal), 0.0), shininess);
if (diff_coeff <= 0.0 || isnan(spec_coeff))
spec_coeff = 0.0;
return light_color * vec3(diffuse * diff_coeff * color + specular * spec_coeff);
}

to avoid interpolating to vec3(0). This probably requires earlier normalize(normal) calls to be removed, e.g.
color.rgb = illuminate(normalize(o_world_normal), color.rgb);

since this may lead to nan on some gpus. CairoMakie (primitves.jl) and WGLMakie (shaders in assets folder) should be pretty analogous.

@Kevin-Mattheus-Moerman
Copy link
Author

Looks like I posted this before, sorry for the duplicate: #3624 (comment)

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

2 participants