问题描述
我正在三角形条(立方体)上使用 opengl 做一些非常简单的漫射照明。然后我尝试添加一些旋转,一切都消失了。
这是一个 MRE:
import pygame
pygame.init()
from OpenGL import GL
from OpenGL import glu
import math
import numpy as np
import copy
def Rec(r,angle):
x = r*math.cos(angle)
y = r*math.sin(angle)
return x,y
def Pol(x,y):
r = (x**2 + y**2)**(1/2)
angle = math.atan2(y,x)
return r,angle
class Cube:
def __init__(self,pos,size,color):
self.identity_vertices = np.array(((0.5,0.5,0.5),(-0.5,(0.5,-0.5,-0.5),-0.5)))
self.redefine(pos,color)
def draw(self):
GL.glMaterialfv(GL.GL_FRONT_AND_BACK,GL.GL_DIFFUSE,self.color)
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
data = (GL.GLfloat * len(self.vertices))(*self.vertices)
GL.glVertexPointer(3,GL.GL_FLOAT,data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP,14)
GL.gldisableClientState(GL.GL_VERTEX_ARRAY)
def update(self):
self.vertices = copy.copy(self.identity_vertices)
self.vertices*=self._size
self.vertices+=self._pos
self.vertices=self.vertices.flatten()
def redefine(self,color):
self._pos = [*pos]
self._size = [*size]
self.color = color
self.update()
display = (600,500)
screen = pygame.display.set_mode(display,pygame.DOUBLEBUF|pygame.OPENGL)
GL.glEnable(GL.GL_DEPTH_TEST)
GL.glEnable(GL.GL_LIGHTING)
GL.glEnable(GL.GL_LIGHT0)
GL.glLightfv(GL.GL_LIGHT0,(1.0,1.0,1.0))
GL.glLightfv(GL.GL_LIGHT0,GL.GL_AMBIENT,(0.1,0.1,1.0))
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
glu.gluPerspective(60,(display[0]/display[1]),100.0)
c = Cube((0,0),(2,2,2),(0.0,1.0))
pos = [0,8,0]
rot = math.pi
run = 1
clock = pygame.time.Clock()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = 0
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
rot += 0.1
if pressed[pygame.K_RIGHT]:
rot -= 0.1
pos[0],pos[2] = Rec(8,rot)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glLightfv(GL.GL_LIGHT0,GL.GL_POSITION,pos)
GL.glLightfv(GL.GL_LIGHT0,GL.GL_SPOT_DIRECTION,[*map(lambda x: math.copysign(1,-x),pos)])
glu.gluLookAt(*pos,1,0)
GL.glClearColor(0,1)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
c.draw()
pygame.display.flip()
clock.tick(60)
pygame.quit()
我的问题是光照是均匀的,整个立方体都是灰色或青色(或介于两者之间),并且没有提供渐变。此外,立方体通常是完全黑暗的,它只在特定旋转时显示。您可以通过使用左右箭头键围绕立方体旋转来重现此问题
运行一些测试后,我发现立方体唯一点亮的时间是相机相对于立方体位于负 z 方向时。这是有道理的,因为文档声明照明的默认方向是 (0,1)
。然后我尝试通过更改 GL_SPOT_DIRECTION
来解决这个问题,以适应这一点,但无济于事,因为这没有改变任何东西。而且,我正在使用漫射照明,它根本不应该有方向
为什么漫射照明会出现这种奇怪的方向性(如果这就是问题所在,那可能是完全不同的东西,这正是我诊断的情况),我该如何解决这个问题?
解决方法
如果您使用 OpenGL 固定功能管道,则可能需要调用 glEnable(GL_NORMALIZE)
。这将标准化您作为图形管道输入的每个法线(即您要绘制)。
通常,如果你知道你的法线是什么并且被正确绑定,你不需要这种显式的规范化。
主要是,要创建一个对象,您需要:
glBegin(GL_TRIANGLES);
{
glNormal3f(nx,ny,nz);
glColor3f(cx,cy,cz);
glVertex3f(vx,vy,vz);
// Here you add your vertices that you might want to draw in triangles
// 3 x vertices per triangle
...
}
glEnd();
多维数据集使用 GL_QUADS
可能更容易:
glBegin(GL_QUADS);
{
glNormal3f(nx,vz);
// Here you add your vertices that you might want to draw in quads.
// 4 x vertices per quad
...
}
glEnd();