You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pygame与PyOpenGL中添加灯光并保留物体原颜色?

问题分析与修复方案

你的问题核心在于启用光照后,OpenGL默认不再使用你通过glColor3fv设置的顶点颜色,而是依赖材质属性来计算物体表面的最终颜色。因为你没有配置任何材质参数,所以立方体就变成了无颜色的状态(看起来像是消失了)。

下面是具体的修复步骤和代码调整:

1. 启用颜色材质关联

OpenGL提供了GL_COLOR_MATERIAL选项,可以让你设置的顶点颜色直接作为物体的漫反射材质颜色,这样既保留了原有顶点色,又能让光照效果生效。你需要在初始化阶段(循环外)启用这个功能,并指定颜色对应的材质属性:

glEnable(GL_COLOR_MATERIAL)
# 让顶点颜色同时影响漫反射和环境光材质
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)

2. 优化灯光设置

  • 不要在循环内反复开关灯光(glEnable(GL_LIGHT0)/glDisable(GL_LIGHT0)),这会降低性能,只需要在初始化时启用一次即可。
  • 调整灯光的环境光参数(GL_AMBIENT),你的原设置(0, 1.5, 1, 0)数值超过了1.0的合理范围,会导致过曝,建议控制在0-1之间,比如(0.2, 0.2, 0.2, 1.0)。
  • 灯光位置的设置用glLightfv更规范,参数格式保持一致。

3. 修改后的完整代码

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

# 你的顶点、边、面、颜色定义
verticies = (
    (1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1),
    (1, -1, 1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1)
)

edges = (
    (0,1), (1,2), (2,3), (3,0),
    (4,5), (5,7), (7,6), (6,4),
    (0,4), (1,5), (2,7), (3,6)
)

surfaces = (
    (0,1,2,3), (3,2,7,6), (6,7,5,4),
    (4,5,1,0), (1,5,7,2), (4,0,3,6)
)

colors = (
    (1,0,0), (0,1,0), (0,0,1),
    (1,1,0), (1,0,1), (0,1,1),
    (0.5,0.5,0.5), (0.5,0,0),
)

def Cube():
    glBegin(GL_QUADS)
    for surface in surfaces:
        x = 0
        for vertex in surface:
            x += 1
            glColor3fv(colors[x])
            glVertex3fv(verticies[vertex])
    glEnd()
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(verticies[vertex])
    glEnd()

def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
    glTranslatef(0.0,0.0, -5)

    # 初始化光照与颜色材质
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
    
    # 配置灯光参数
    glLightfv(GL_LIGHT0, GL_POSITION, (0.0, 5.0, 5.0, 1.0))  # 点光源位置
    glLightfv(GL_LIGHT0, GL_AMBIENT, (0.2, 0.2, 0.2, 1.0))   # 基础环境光
    glLightfv(GL_LIGHT0, GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0))   # 漫反射光颜色

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glRotatef(1, 3, 1, 1)
        Cube()
        pygame.display.flip()
        pygame.time.wait(10)

main()

4. 针对OBJ加载模型的额外建议

对于你加载的纯白色OBJ模型,因为没有顶点颜色,你可以:

  • 如果OBJ文件包含顶点颜色,确保加载代码正确读取并调用glColor3fv设置;
  • 如果没有顶点颜色,可以手动给模型的面或顶点分配材质颜色,或者通过调整灯光的方向、强度来产生明暗对比,凸显物体轮廓;
  • 添加glEnable(GL_DEPTH_TEST)到初始化代码中,解决模型面重叠的问题,提升显示层次感。

内容的提问来源于stack exchange,提问作者underfloor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:12:50