【问题标题】:opengl diffuse light becoming oddly directional, but not changing based on GL_SPOT_DIRECTIONopengl 漫射光变得奇怪的方向性,但不会根据 GL_SPOT_DIRECTION 改变
【发布时间】: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


【解决方案1】:

如果您使用的是 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, ny, nz);
    glColor3f(cx, cy, cz);
    glVertex3f(vx, vy, vz);
    
    // Here you add your vertices that you might want to draw in quads.
    // 4 x vertices per quad
    ...
}
glEnd();

【讨论】:

    猜你喜欢
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    相关资源
    最近更新 更多