如何在OpenGL中使用高光照明?我使用python,我一直在尝试学习它是如何工作的,我已经能够使纹理工作,深度,创建一个基本的游戏,但现在我试图使镜面照明像手电筒一样工作,所以我不断地改变它的位置,使其与玩家的位置和方向一致,但它不起作用!在
import pyglet, math
from pyglet.gl import *
tela = pyglet.window.Window(height=500, width=500, caption="Halloween")
glEnable(GL_DEPTH_TEST)
glEnable(GL_TEXTURE_2D)
glEnable(GL_LIGHTING)
glLightfv(GL_LIGHT0, GL_AMBIENT, (GLfloat*4)(0,0,0,1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (GLfloat*4)(0,0,0,1))
glEnable(GL_LIGHT0)
tela.set_mouse_visible(False)
pos = [0,0,0]
rotX = rotY = pre = 0
comando = {"a":0,"d":0,"w":0,"s":0}
Dparede = pyglet.image.load("inf/Parede_Branca.png").get_image_data().get_data('RGBA', 225*4)
parede = pyglet.resource.image("inf/Parede_Branca.png").get_texture()
Dchao = pyglet.image.load("inf/Madeira.png").get_image_data().get_data('RGBA', 225*4)
chao = pyglet.resource.image("inf/Madeira.png").get_texture()
@tela.event
def on_draw():
global pos, comando, rotX, rotY, parede, chao, Dchao, Dparede
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
if comando["w"] == 1:
pos[2] += math.cos(math.pi*rotX/180)
pos[0] += math.sin(math.pi*rotX/180)
if comando["s"] == 1:
pos[2] -= math.cos(math.pi*rotX/180)
pos[0] -= math.sin(math.pi*rotX/180)
if comando["d"] == 1:
pos[2] += math.sin(math.pi*rotX/180)
pos[0] -= math.cos(math.pi*rotX/180)
if comando["a"] == 1:
pos[2] -= math.sin(math.pi*rotX/180)
pos[0] += math.cos(math.pi*rotX/180)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, 1, 0.1, 1000)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
if pos[0] < -188:
pos[0] = -188
if pos[2] < -188:
pos[2] = -188
if pos[0] > 188:
pos[0] = 188
if pos[2] > 188:
pos[2] = 188
glLightfv(GL_LIGHT0, GL_SPECULAR, (GLfloat*4)(1,1,1,1))
glLightfv(GL_LIGHT0, GL_POSITION, (GLfloat*4)(pos[0],pos[1]-1,pos[2],1))
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, (GLfloat*3)(pos[0]+1000*(math.sin(math.pi*rotX/180)),pos[1]+1000*(math.cos(math.pi*rotY/180)), pos[2]+1000*(math.cos(math.pi*rotX/180))))
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, (GLfloat*1)(45))
gluLookAt(pos[0], pos[1], pos[2], pos[0]+math.sin(math.pi*rotX/180), pos[1]+math.cos(math.pi*rotY/180), pos[2]+math.cos(math.pi*rotX/180), 0, 10, 0)
glBindTexture(GL_TEXTURE_2D, chao.id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 225, 225, 0, GL_RGBA, GL_UNSIGNED_BYTE, Dchao)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat*4)(1,1,1,1))
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (GLfloat*1)(100))
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (GLfloat*4)(0,0,0,1))
# chão
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(-200,-20,200)
glTexCoord2f(0,10)
glVertex3f(-200,-20,-200)
glTexCoord2f(10,10)
glVertex3f(200,-20,-200)
glTexCoord2f(10,0)
glVertex3f(200,-20,200)
glEnd()
glBindTexture(GL_TEXTURE_2D, parede.id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 225, 225, 0, GL_RGBA, GL_UNSIGNED_BYTE, Dparede)
# teto
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(-200,20,200)
glTexCoord2f(0,50)
glVertex3f(-200,20,-200)
glTexCoord2f(50,50)
glVertex3f(200,20,-200)
glTexCoord2f(50,0)
glVertex3f(200,20,200)
glEnd()
# parede
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(-200,20,200)
glTexCoord2f(0,50)
glVertex3f(-200,20,-200)
glTexCoord2f(10,50)
glVertex3f(-200,-20,-200)
glTexCoord2f(10,0)
glVertex3f(-200,-20,200)
glEnd()
# parede
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(-200,-20,-200)
glTexCoord2f(0,50)
glVertex3f(200,-20,-200)
glTexCoord2f(10,50)
glVertex3f(200,20,-200)
glTexCoord2f(10,0)
glVertex3f(-200,20,-200)
glEnd()
# parede
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(200,-20,-200)
glTexCoord2f(0,50)
glVertex3f(200,-20,200)
glTexCoord2f(10,50)
glVertex3f(200,20,200)
glTexCoord2f(10,0)
glVertex3f(200,20,-200)
glEnd()
# parede
glBegin(GL_POLYGON)
glTexCoord2f(0,0)
glVertex3f(-200,-20,200)
glTexCoord2f(0,50)
glVertex3f(200,-20,200)
glTexCoord2f(10,50)
glVertex3f(200,20,200)
glTexCoord2f(10,0)
glVertex3f(-200,20,200)
glEnd()
@tela.event
def on_key_press(k,m):
global comando
if k == pyglet.window.key.A:
comando["a"] = 1
if k == pyglet.window.key.D:
comando["d"] = 1
if k == pyglet.window.key.W:
comando["w"] = 1
if k == pyglet.window.key.S:
comando["s"] = 1
if k == pyglet.window.key.Q:
tela.close()
@tela.event
def on_key_release(k,m):
global comando
if k == pyglet.window.key.A:
comando["a"] = 0
if k == pyglet.window.key.D:
comando["d"] = 0
if k == pyglet.window.key.W:
comando["w"] = 0
if k == pyglet.window.key.S:
comando["s"] = 0
@tela.event
def on_mouse_motion(x, y, dx, dy):
global rotX, rotY, pre
if pre == 0:
rotX-=dx/2
if rotY >= 0:
rotY = -1
if rotY <= -180:
rotY = -179
rotY+=dy
if x > 400 or x < 100 or y > 400 or y < 100:
tela.set_mouse_position(250,250)
pre = 1
else:
pre = 0
def SRO(dt):
on_draw()
pyglet.clock.schedule_interval(SRO, 1/120)
pyglet.app.run()
我已经尝试过改变glMaterial,或者改变照明中的不同东西,但是没有任何工作正常,我只想让灯光像手电筒一样工作,请用代码给出答案
你想做的是不可能的,因为gouraud shading是固定函数光模型。另请参见OpenGL Lighting on texture plane is not working,这是一个关于类似问题的问题。您必须将曲面(墙和地板)细分为更小的瓷砖,因为灯光仅针对顶点坐标进行计算并在曲面上插值。曲面中间的高光不会出现。在
我知道你不会满意的。但是请注意,用^{}/^{} 序列绘制固定函数矩阵堆栈和固定函数逐顶点光模型,几十年来一直不推荐使用。请参见Fixed Function Pipeline和Legacy OpenGL。
阅读关于Vertex Specification和Shader的最新渲染方式。在
如果要“看到”任何内容,则必须跳过聚光灯,因为它无法与几何体一起工作:
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, (GLfloat*1)(45))
但是激活环境漫射光:
对于光的计算,需要曲面的法向量。在
激活灯光模型^{} 侧:
^{pr2}$按^{} 设置法向量:
当灯光位置由^{} 设置时,位置将乘以当前模型视图矩阵。
这意味着如果在设置视图矩阵之前设置了位置(
gluLookAt
),则灯光位置相对于相机(视图空间位置)。如果它是在视图矩阵设置之后设置的,那么灯光位置必须在世界坐标系中,因为它是由视图矩阵变换的。在
如果你希望光源是相机的位置,那么你必须在视图矩阵由
gluLookAt
设置之前,将灯光设置到位置(0,0,0),。在如果你想让聚光灯工作(或多或少),那么唯一的可能就是使用一个非常小的^{} 参数(例如1):
另一种可能是实现一个简单的Per Fragment Lighting着色器程序:
创建着色器程序源代码:
编译并链接程序:
在程序主循环之前加载纹理:
绘制场景时使用该程序:
相关问题 更多 >
编程相关推荐