OpenGL中围绕对象边翻转的法线
我正在使用OpenGL渲染3D参数化曲面。在大多数情况下,它似乎运行良好,但是 在几何体边缘周围的某些部分,几乎就像法线指向内部() 我怀疑问题在于我的片段着色器或曲面法线,特别是在它们接近垂直于摄影机方向的区域。以下是顶点的创建方式:OpenGL中围绕对象边翻转的法线,opengl,render,vispy,Opengl,Render,Vispy,我正在使用OpenGL渲染3D参数化曲面。在大多数情况下,它似乎运行良好,但是 在几何体边缘周围的某些部分,几乎就像法线指向内部() 我怀疑问题在于我的片段着色器或曲面法线,特别是在它们接近垂直于摄影机方向的区域。以下是顶点的创建方式: # --- Python imports --- import numpy as np # --- Internal imports --- from glmesh import MeshApp3D # -------------------------
# --- Python imports ---
import numpy as np
# --- Internal imports ---
from glmesh import MeshApp3D
# -----------------------------------------------------------
# Torus parameters
radius1 = 1.0
radius2 = 0.2
# Define torus
torus = ( lambda u,v : np.cos(u)*(radius1+radius2*np.cos(v)),
lambda u,v : np.sin(u)*(radius1+radius2*np.cos(v)),
lambda u,v : radius2*np.sin(v) )
# Generate grid of points on the torus
nSamples = 100
U = np.linspace(0.0,2*np.pi,nSamples)
V = np.linspace(0.0,-2*np.pi,nSamples)
grid = np.array(
[
[ [torus[componentIndex](u,v) for u in U] for v in V ] for componentIndex in (0,1,2)
],
dtype=np.float32 )
# -----------------------------------------------------------
# Rearrange grid to a list of points
vertices = np.reshape(
np.transpose( grid,
axes=(1,2,0)),
( nSamples*nSamples ,3))
# Generate triangle indices in a positive permutation
# For example:
# 7---8---9
# | / | / |
# 4---5---6
# | / | / |
# 1---2---3
#
# (1,5,4) (1,2,5) (2,6,5) (2,3,6) (4,8,7) (4,5,8) (5,9,8) (5,6,9)
faces = np.zeros( ( 2*(nSamples-1)*(nSamples-1), 3 ), dtype=np.uint32 )
k = 0
for j in range(nSamples-1):
for i in range(nSamples-1):
jni = j*nSamples+i
faces[k] = [ jni,
jni+nSamples+1,
jni+nSamples ]
faces[k+1] = [ jni,
jni+1,
jni+1+nSamples ]
k+=2
# -----------------------------------------------------------
# -----------------------------------------------------------
meshApp = MeshApp3D( {'vertices' : vertices, 'faces' : faces},
colors=(1.0,1.0,1.0) )
meshApp.run()
片段着色器:
varying vec3 position;
varying vec3 normal;
varying vec4 color;
void main() {
// Diffuse
vec3 lightDir = normalize( position - vec3($lightPos) );
float diffuse = dot( normal, lightDir );
//diffuse = min( max(diffuse,0.0), 1.0 );
// Specular
vec3 halfWayVector = normalize( ( lightDir+vec3($cameraDir) )/2.0 );
float specular = min( max( dot(halfWayVector,normal) ,0.0), 1.0 );
specular = specular * specular * specular * specular;
specular = specular * specular * specular * specular;
specular = specular * specular * specular * specular;
// Additive
vec3 fragColor = vec3($lightColor) * color.xyz;
fragColor = fragColor * ( $diffuseMaterialConstant * diffuse +
$specularMaterialConstant * specular)
+ $ambientMaterialConstant * vec3($ambientLight) * color.xyz;
gl_FragColor = vec4(fragColor,1.0);
}
代码的其余部分在模块中进行了分解,但简而言之,发生了以下情况:
- a由顶点和面构成
- 法线在MeshData内部生成,基于顶点位置及其定义相应三角形的顺序
- 创建并初始化画布和OpenGL窗口
- 网格绘制为三角形条带
7---8---9
| / | / |
4---5---6
| / | / |
1---2---3
v
^
|
---> u
(1,5,4) (1,2,5) (2,6,5) (2,3,6) (4,8,7) (4,5,8) (5,9,8) (5,6,9)
它最初的目的是为二维函数z=f(x,y)生成三角形,并且对它们很有效,但我在将其应用于参数曲面r(u,v)=[x(u,v),y(u,v),z(u,v)]时遇到了问题。例如,这就是为什么参数v从0变为-2pi而不是+2pi的原因(否则法线将指向内部)
关于图像中出现故障的原因有什么想法吗?
(或关于更好的三角形生成的任何建议?检查三角形绕组一致性的一种方法是启用背面消隐。如果黑色三角形消失了,那么你就知道你已经将它们向后定位了。我想这就是如何使用vispy启用消隐:我想我们可能对如何生成法线和顶点着色器感兴趣。我还想知道你的三角形是否太小,所以你可能正在做的叉积有时会退化。@prideout谢谢你关于剔除的提示,它帮助我找到了问题所在。默认情况下,剔除在vispy中设置为“背面”。将其更改为“front”会导致与原始帖子中显示的第二张图片相同的情况(有目的地反转法线)。你可以看到,即使三角形露出了它们的背部,它们也没有被剔除。原因是一些三角形被复制:三角形绘制模式被设置为“三角形带”,而不是“三角形”,这会创建一些重复。将绘图模式设置为“三角形”解决了所有问题。@KelemenMáté很高兴你能做到这一点。如果您认为可以在vispy库中提供或简化任何内容,请在vispy github存储库中创建一个问题,让我知道。谢谢。检查三角形绕组是否一致的一种方法是启用背面消隐。如果黑色三角形消失了,那么你就知道你已经将它们向后定位了。我想这就是如何使用vispy启用消隐:我想我们可能对如何生成法线和顶点着色器感兴趣。我还想知道你的三角形是否太小,所以你可能正在做的叉积有时会退化。@prideout谢谢你关于剔除的提示,它帮助我找到了问题所在。默认情况下,剔除在vispy中设置为“背面”。将其更改为“front”会导致与原始帖子中显示的第二张图片相同的情况(有目的地反转法线)。你可以看到,即使三角形露出了它们的背部,它们也没有被剔除。原因是一些三角形被复制:三角形绘制模式被设置为“三角形带”,而不是“三角形”,这会创建一些重复。将绘图模式设置为“三角形”解决了所有问题。@KelemenMáté很高兴你能做到这一点。如果您认为可以在vispy库中提供或简化任何内容,请在vispy github存储库中创建一个问题,让我知道。谢谢