MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.38k stars 302 forks source link

Shading issue for inversion of face orientation #3624

Open Kevin-Mattheus-Moerman opened 7 months ago

Kevin-Mattheus-Moerman commented 7 months ago

Here is a simple code to visualize two triangles which share a single corner node:

using GLMakie
using GeometryBasics

s=1.0
V=Vector{GeometryBasics.Point{3, Float64}}(undef,5)
V[1 ] = GeometryBasics.Point{3, Float64}( 0.0,    s, 0.0)
V[2 ] = GeometryBasics.Point{3, Float64}( 0.0,   -s, 0.0)
V[3 ] = GeometryBasics.Point{3, Float64}(   s,  0.0, 0.0)
V[4 ] = GeometryBasics.Point{3, Float64}( 2*s,    s, 0.0)
V[5 ] = GeometryBasics.Point{3, Float64}( 2*s,    -s, 0.0)

F = Vector{TriangleFace{Int64}}(undef,2)
F[1 ] = TriangleFace{Int64}(1,2,3)
F[2 ] = TriangleFace{Int64}(3,4,5)

M=GeometryBasics.Mesh(V,F)
fig = Figure(size=(800,800))
ax1 = Axis3(fig[1, 1], aspect = :data, xlabel = "X", ylabel = "Y", zlabel = "Z", title = "A multi-object mesh")
poly!(ax1,GeometryBasics.Mesh(V,F), strokewidth=2,color=:white, strokecolor=:black, shading = FastShading, transparency=false)
fig

Despite the color being set to :white (or any other color I tried) this renders them both black:

Screenshot from 2024-02-11 09-21-48

In the next visualization I've added the face normal vectors in red. In addition I subdivided the triangles. Now it is clear this happens when the face normals flip from the one set of triangles to the next.

Screenshot from 2024-02-11 08-33-48

@SimonDanisch may be able to confirm, but my guess is that the shading algorithm uses "vertex" rather than face normals, and that the vertex normal for this shared node is zero. Probably because for the shared node the mean of the two faces produces the average between (0,0,1) and (0,0,-1). However, should the whole triangles be black like that? Perhaps the normals should not be allowed to be zero?

tpgillam commented 7 months ago

Could this be the cause of #3561 too maybe?

ffreyer commented 2 weeks ago

SimonDanisch may be able to confirm, but my guess is that the shading algorithm uses "vertex" rather than face normals, and that the vertex normal for this shared node is zero.

Yes, because OpenGL doesn't have face normals. It also doesn't have a glFaceIndex. If you want to have per-face normals you have to duplicate vertices to avoid sharing vertices.

GeometryBasics normal algorithm doesn't assume you want that. It just computes a normal for each face, adds it to each vertex and then normalizes it. We could consider adding a different normal generation in/after https://github.com/JuliaGeometry/GeometryBasics.jl/pull/173 that does grow the mesh

Probably because for the shared node the mean of the two faces produces the average between (0,0,1) and (0,0,-1). However, should the whole triangles be black like that? Perhaps the normals should not be allowed to be zero?

It's nan actually, which is maybe also something to clean up in https://github.com/JuliaGeometry/GeometryBasics.jl/pull/173. With 0 you would get a brighter color because of ambient light.

Could this be the cause of #3561 too maybe?

No, that issue has problems generating a face. This one is more or less just how vectors add up