gpt4 book ai didi

python - 使用 GLSL 的 OpenGL 阴影贴图

转载 作者:太空狗 更新时间:2023-10-29 21:11:27 25 4
gpt4 key购买 nike

我正在尝试使用 GLSL 使阴影贴图工作。不幸的是,即使我有相当不错的深度缓冲精度,我的深度渲染结果也无法使用。它像线框一样渲染,下图可能是更好的描述。

我还包括一个测试用例(包含着色器的单个文件),唯一的依赖项是 pyopengl。

alt text

# shadow mapping test
# utkualtinkaya at gmail
# shader is from http://www.fabiensanglard.net/shadowmapping/index.php

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.shaders import *
from OpenGL.GL.framebufferobjects import *
import math

class Camera:
def __init__(self):
self.rotx, self.roty = math.pi/4, math.pi/4
self.distance = 100
self.moving = False
self.ex, self.ey = 0, 0
self.size = (800, 600)

def load_matrices(self):
glViewport(0, 0, *self.size)
y = math.cos(self.roty) * self.distance
x = math.sin(self.roty) * math.cos(self.rotx) * self.distance
z = math.sin(self.roty) * math.sin(self.rotx) * self.distance

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, self.size[0]/float(self.size[1]), 1, 1000)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(x,y,z, 0,0,0, 0,1,0)

def on_mouse_button (self, b, s, x, y):
self.moving = not s
self.ex, self.ey = x, y
if b in [3, 4]:
dz = (1 if b == 3 else -1)
self.distance += self.distance/15.0 * dz;

def on_mouse_move(self, x, y, z = 0):
if self.moving:
self.rotx += (x-self.ex) / 300.0
self.roty += -(y-self.ey) / 300.0
self.ex, self.ey = x, y

def set_size(self, w, h):
self.size = w, h

class Shader():
def __init__(self):
self.is_built = False
self.uniforms = {}

def build(self):
self.program = compileProgram(
compileShader('''
uniform mat4 camMatrix;
uniform mat4 shadowMatrix;
varying vec4 depthProjection;
uniform bool useShadow;

void main() {
gl_Position = camMatrix * gl_ModelViewMatrix * gl_Vertex;
depthProjection = shadowMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
}
''',GL_VERTEX_SHADER),
compileShader('''
varying vec4 depthProjection;
uniform sampler2D shadowMap;
uniform bool useShadow;

void main () {
float shadow = 1.0;
if (useShadow) {
vec4 shadowCoord = depthProjection / depthProjection.w ;
// shadowCoord.z -= 0.0003;
float distanceFromLight = texture2D(shadowMap, shadowCoord.st).z;
if (depthProjection .w > 0.0)
shadow = distanceFromLight < shadowCoord.z ? 0.5 : 1.0 ;

}
gl_FragColor = shadow * gl_Color;
}
''',GL_FRAGMENT_SHADER),)
self.is_built = True

self.uniforms['camMatrix'] = glGetUniformLocation(self.program, 'camMatrix')
self.uniforms['shadowMatrix'] = glGetUniformLocation(self.program, 'shadowMatrix')
self.uniforms['shadowMap'] = glGetUniformLocation(self.program, 'shadowMap')
self.uniforms['useShadow'] = glGetUniformLocation(self.program, 'useShadow')
print self.uniforms

def use(self):
if not self.is_built:
self.build()
glUseProgram(self.program)

class Test:
def __init__(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowSize(800, 600)
glutInitWindowPosition(1120/2, 100)
self.window = glutCreateWindow("Shadow Test")
self.cam = Camera()
self.light = Camera()
self.cam.set_size(800, 600)
self.light.set_size(2048, 2048)
self.light.distance = 100
self.shader = Shader()
self.initialized = False

def setup(self):
self.initialized = True
glClearColor(0,0,0,1.0);
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)

self.fbo = glGenFramebuffers(1);
self.shadowTexture = glGenTextures(1)

glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)

w, h = self.light.size

glActiveTexture(GL_TEXTURE5)
glBindTexture(GL_TEXTURE_2D, self.shadowTexture)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, None)

glDrawBuffer(GL_NONE)
glReadBuffer(GL_NONE)

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.fbo, 0)

FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)
if FBOstatus != GL_FRAMEBUFFER_COMPLETE:
print ("GL_FRAMEBUFFER_COMPLETE_EXT failed, CANNOT use FBO\n");

glBindFramebuffer(GL_FRAMEBUFFER, 0)
#glActiveTexture(GL_TEXTURE0)

def draw(self):
glPushMatrix()
glTranslate(0, 10 ,0)
glColor4f(0, 1, 1, 1)
glutSolidCube(5)
glPopMatrix()

glPushMatrix()
glColor4f(0.5, 0.5, .5, 1)
glScale(100, 1, 100)
glutSolidCube(1)
glPopMatrix()

def apply_camera(self, cam):
cam.load_matrices()
model_view = glGetDoublev(GL_MODELVIEW_MATRIX);
projection = glGetDoublev(GL_PROJECTION_MATRIX);
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glMultMatrixd(projection)
glMultMatrixd(model_view)
glUniformMatrix4fv(self.shader.uniforms['camMatrix'], 1, False, glGetFloatv(GL_MODELVIEW_MATRIX))
glLoadIdentity()

def shadow_pass(self):
glUniform1i(self.shader.uniforms['useShadow'], 0)

glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
glClear(GL_DEPTH_BUFFER_BIT)
glCullFace(GL_FRONT)
self.apply_camera(self.light)
self.draw()
glBindFramebuffer(GL_FRAMEBUFFER, 0)

def final_pass(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

self.light.load_matrices()
model_view = glGetDoublev(GL_MODELVIEW_MATRIX);
projection = glGetDoublev(GL_PROJECTION_MATRIX);
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
bias = [ 0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0]
glLoadMatrixd(bias)
glMultMatrixd(projection)
glMultMatrixd(model_view)
glUniformMatrix4fv(self.shader.uniforms['shadowMatrix'], 1, False, glGetFloatv(GL_MODELVIEW_MATRIX))

glActiveTexture(GL_TEXTURE5)
glBindTexture(GL_TEXTURE_2D, self.shadowTexture)
glUniform1i(self.shader.uniforms['shadowMap'], 5)

glUniform1i(self.shader.uniforms['useShadow'], 1);

self.apply_camera(self.cam)
glLoadIdentity()
glCullFace(GL_BACK)
self.draw()

def render(self):
if not self.initialized: self.setup()
self.shader.use()
self.shadow_pass()
self.final_pass()
glutSwapBuffers()

def mouse_move(self, *args):
self.cam.on_mouse_move(*args)
self.light.on_mouse_move(*args)

def mouse_button(self, b, *args):
if b==0:
self.light.on_mouse_button(b, *args)
else:
self.cam.on_mouse_button(b, *args)

def main(self):
glutDisplayFunc(self.render)
glutIdleFunc(self.render)
glutMouseFunc(self.mouse_button)
glutMotionFunc(self.mouse_move)
glutReshapeFunc(self.cam.set_size)
#self.setup()
glutMainLoop()

if __name__ == '__main__':
test = Test()
test.main()

最佳答案

解决了,这是绑定(bind)问题,在阴影 channel 片段着色器中,我只是检查了一个 bool 值以禁用读取纹理,但这还不够。我应该在阴影传递之前取消绑定(bind)纹理,这在文档中提到为:

引自 OpenGL 引用资料:需要采取特殊的预防措施,以避免在纹理对象当前绑定(bind)并可能被当前顶点或片段着色器采样时将纹理图像附加到当前绑定(bind)的帧缓冲区。

NVIDIA 忽略了这一点,ATI 的行为几乎如文档所述“未定义”。

关于python - 使用 GLSL 的 OpenGL 阴影贴图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4484605/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com