【发布时间】:2021-03-17 06:43:45
【问题描述】:
我在三角形条(立方体)上使用 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, 0.5),
(-0.5, -0.5, 0.5),
(-0.5, -0.5, -0.5),
(-0.5, 0.5, 0.5),
(-0.5, 0.5, -0.5),
(0.5, 0.5, 0.5),
(0.5, 0.5, -0.5),
(0.5, -0.5, 0.5),
(0.5, -0.5, -0.5),
(-0.5, -0.5, -0.5),
(0.5, 0.5, -0.5),
(-0.5, 0.5, -0.5)))
self.redefine(pos, size, 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, 0, data)
GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 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, pos, size, 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, GL.GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0))
GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, (0.1, 0.1, 0.1, 1.0))
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluPerspective(60, (display[0]/display[1]), 0.1, 100.0)
c = Cube((0, 0, 0), (2, 2, 2), (0.0, 1.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, 0, 0, 0, 0, 1, 0)
GL.glClearColor(0, 0, 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, 0, 1)。然后,我尝试通过更改 GL_SPOT_DIRECTION 来解决此问题以适应此问题,但无济于事,因为这并没有改变任何东西。而且,我使用的是漫反射照明,它根本不应该有方向
为什么漫反射照明会出现这种奇怪的方向性(如果这甚至是问题,它可能完全不同,这正是我所诊断的),我该如何解决这个问题?
【问题讨论】:
-
法线向量在哪里 (
glNormalPointer)? -
法线 = (0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0 )
-
我尝试了这些法线,但效果不佳
-
你知道一个关于法线的好问题吗?我对他们还是有点动摇
-
了解 OpenGL 固定函数模型是没有意义的,它已经被弃用了几十年。(LearnOpenGL - Basic Lighting)
标签: python opengl pygame lighting