format='%(levelname)s:%(module)s.%(funcName)s: %(message)s') with window: glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) ssao_geometry_program = program.create(*glsl.read("ssao_geometry")) # create gBuffer # -------------- gBuffer = glGenFramebuffers(1) ssao_width = window.width ssao_height = window.height gPosition, gNormal, gAlbedo = glGenTextures(3) with fbo.bind(gBuffer): # create color attachments glDrawBuffers( 3, [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2]) for i, tex in enumerate([gPosition, gNormal, gAlbedo]): glBindTexture(GL_TEXTURE_2D, tex) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, ssao_width, ssao_height, 0, GL_RGB, GL_FLOAT, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) # attach to color glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, tex, 0) glBindTexture(GL_TEXTURE_2D, 0)
def render(self): # Animate # ------- import math, time spotlight.position = glm.vec3(math.cos(time.time() * 3) * 4, 0.3, -4) spotlight.direction = -spotlight.position pointlight.position = glm.vec3( math.cos(time.time()) * 4, 4, math.sin(time.time()) * 4) self.camera.transform = glm.inverse(self.window.view_matrix) # Render passes # ------------- ## Geometry self.geometry_pass.camera = self.camera # window.projection_matrix, window.view_matrix self.geometry_pass.render() ## Shadowmaps dirlight.shadowpass.camera = dirlight.camera dirlight.shadowpass.render() spotlight.shadowpass.camera = spotlight.camera spotlight.shadowpass.render() pointlight.shadowpass.position = pointlight.position pointlight.shadowpass.render() ## Lighting self.lighting_pass.cameraPos = self.camera.position self.lighting_pass.gPosition = self.geometry_pass.gPosition self.lighting_pass.gNormal = self.geometry_pass.gNormal self.lighting_pass.gAlbedoSpecular = self.geometry_pass.gAlbedoSpecular self.lighting_pass.gRoughness = self.geometry_pass.gRoughness self.lighting_pass.gMetallic = self.geometry_pass.gMetallic self.lighting_pass.gEmissive = self.geometry_pass.gEmissive self.lighting_pass.render() ## Forward rendering # - Copy depth from geometry pass glBindFramebuffer(GL_READ_FRAMEBUFFER, self.geometry_pass.gBuffer) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.forward_fbo) # write to default framebuffer glBlitFramebuffer(0, 0, self.width, self.height, 0, 0, self.width, self.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST) glBindFramebuffer(GL_READ_FRAMEBUFFER, self.lighting_pass.fbo) glBlitFramebuffer(0, 0, self.width, self.height, 0, 0, self.width, self.height, GL_COLOR_BUFFER_BIT, GL_NEAREST) glBindFramebuffer(GL_FRAMEBUFFER, 0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) glDepthMask(GL_FALSE) with fbo.bind(self.forward_fbo): # draw skybox glViewport(0, 0, self.width, self.height) with program.use(self.skybox_program) as prog: program.set_uniform(prog, 'projection', self.camera.projection) sky_view = glm.mat4(glm.mat3(self.camera.view)) program.set_uniform(prog, 'view', sky_view) program.set_uniform(prog, 'cameraPos', self.camera.position) program.set_uniform(prog, 'skybox', 0) program.set_uniform(prog, 'groundProjection', True) glActiveTexture(GL_TEXTURE0 + 0) glBindTexture(GL_TEXTURE_CUBE_MAP, self.environment_pass.cubemap) imdraw.cube(prog, flip=True) glBindTexture(GL_TEXTURE_CUBE_MAP, 0) glDepthMask(GL_TRUE) ## Tonemapping self.tonemapping_pass.hdrimage = self.lighting_pass.beauty self.tonemapping_pass.exposure = 0.0 self.tonemapping_pass.gamma = 2.2 self.tonemapping_pass.render() # Render to screen # ---------------- glViewport(0, 0, self.width, self.height) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glDisable(GL_DEPTH_TEST) # draw to screen imdraw.texture(self.tonemapping_pass.ldrimage, (0, 0, self.width, self.height)) # debug imdraw.texture(self.geometry_pass.gPosition, (0, 0, 90, 90)) imdraw.texture(self.geometry_pass.gNormal, (100, 0, 90, 90)) imdraw.texture(self.geometry_pass.gAlbedoSpecular, (200, 0, 90, 90), shuffle=(0, 1, 2, -1)) imdraw.texture(self.geometry_pass.gAlbedoSpecular, (300, 0, 90, 90), shuffle=(3, 3, 3, -1)) imdraw.texture(self.geometry_pass.gRoughness, (400, 0, 90, 90), shuffle=(0, 0, 0, -1)) imdraw.texture(self.geometry_pass.gMetallic, (500, 0, 90, 90), shuffle=(0, 0, 0, -1)) imdraw.texture(dirlight.shadowpass.texture, (0, 100, 90, 90), shuffle=(0, 0, 0, -1)) imdraw.texture(spotlight.shadowpass.texture, (100, 100, 90, 90), shuffle=(0, 0, 0, -1)) imdraw.cubemap(pointlight.shadowpass.cubemap, (200, 100, 90, 90), self.window.projection_matrix, self.window.view_matrix) imdraw.texture(self.environment_tex, (0, 200, 90, 90)) imdraw.cubemap(self.environment_pass.cubemap, (100, 200, 90, 90), self.window.projection_matrix, self.window.view_matrix) imdraw.cubemap(self.irradiance_pass.irradiance, (200, 200, 90, 90), self.window.projection_matrix, self.window.view_matrix) imdraw.cubemap(self.prefilter_pass.prefilter, (300, 200, 90, 90), self.window.projection_matrix, self.window.view_matrix) imdraw.texture(self.brdf_pass.brdflut, (400, 200, 90, 90)) imdraw.texture(self.lighting_pass.beauty, (0, 300, 90, 90)) # swap buffers # ------------ self.window.swap_buffers() GLFWViewer.poll_events()
def setup(self): logging.debug("setup viewer") # Render passes # ------------- # geometry self.geometry_pass.setup() # environment self.environment_tex = texture.create(self.environment_image, 0, format=GL_RGB, wrap_s=GL_CLAMP_TO_EDGE, wrap_t=GL_CLAMP_TO_EDGE, min_filter=GL_LINEAR, mag_filter=GL_LINEAR) self.environment_pass.texture = self.environment_tex self.environment_pass.setup() self.environment_pass.render() # ibl self.prefilter_pass.setup() self.prefilter_pass.environment = self.environment_pass.cubemap self.prefilter_pass.render() self.irradiance_pass.setup() self.irradiance_pass.environment = self.environment_pass.cubemap self.irradiance_pass.render() self.brdf_pass.setup() self.brdf_pass.render() # shadows dirlight.shadowpass.setup() spotlight.shadowpass.setup() pointlight.shadowpass.setup() # lighting self.lighting_pass.setup() self.lighting_pass.irradiance = self.irradiance_pass.irradiance self.lighting_pass.prefilter = self.prefilter_pass.prefilter self.lighting_pass.brdf = self.brdf_pass.brdflut # setup forward rendering self.forward_fbo = glGenFramebuffers(1) with fbo.bind(self.forward_fbo): glDrawBuffers(1, [GL_COLOR_ATTACHMENT0 + 0]) self.forward_texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.forward_texture) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width, self.height, 0, GL_RGBA, GL_FLOAT, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.forward_texture, 0) glBindTexture(GL_TEXTURE_2D, 0) # create depth+stencil buffer rbo = glGenRenderbuffers(1) glBindRenderbuffer(GL_RENDERBUFFER, rbo) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self.width, self.height) glBindRenderbuffer(GL_RENDERBUFFER, 0) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo) assert glCheckFramebufferStatus( GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE self.skybox_program = program.create(*glsl.read('skybox')) # tonemapping self.tonemapping_pass.setup()
phong_program = program.create(*glsl.read('phong')) pbr_program = program.create(*glsl.read('pbr')) # Setup Shadow mapping # ==================== depth_program = program.create(*glsl.read('simple_depth')) shadow_fbo = glGenFramebuffers(1) shadow_fbo_width, shadow_fbo_height = 1024, 1024 shadow_tex = texture.create((shadow_fbo_width, shadow_fbo_height), slot=2, format=GL_DEPTH_COMPONENT, wrap_s=GL_CLAMP_TO_BORDER, wrap_t=GL_CLAMP_TO_BORDER, border_color=(1.0, 1.0, 1.0, 1.0)) with fbo.bind(shadow_fbo): # dont render color data glDrawBuffer(GL_NONE) # dont render color data glReadBuffer(GL_NONE) # attach depth component to texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_tex, 0) assert glCheckFramebufferStatus( GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE # Setup Tonemapping with HDR fbo # ============================== tonemapping_program = program.create(*glsl.read('tonemapping')) # setup fbo
dirlight_shadowsize = 1024, 1024 glBindTexture(GL_TEXTURE_2D, dirlight_shadowmap) glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, *dirlight_shadowsize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, np.array([1, 1, 1, 1])) glBindTexture(GL_TEXTURE_2D, 0) dirlight_fbo = glGenFramebuffers(1) with fbo.bind(dirlight_fbo): # dont render color data glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) # attach depth component glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dirlight_shadowmap, 0) assert glCheckFramebufferStatus( GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE ## spotlight shadow setup spotlight_fbo = glGenFramebuffers(1) spotlight_shadowmap = glGenTextures(1) spotlight_shadowsize = 1024, 1024 glBindTexture(GL_TEXTURE_2D, spotlight_shadowmap)
shadowTransforms.append( shadowProj * glm.lookAt(lightPos, lightPos + glm.vec3(0.0, -1.0, 0.0), glm.vec3(0.0, 0.0, -1.0))) shadowTransforms.append( shadowProj * glm.lookAt(lightPos, lightPos + glm.vec3(0.0, 0.0, 1.0), glm.vec3(0.0, -1.0, 0.0))) shadowTransforms.append( shadowProj * glm.lookAt(lightPos, lightPos + glm.vec3(0.0, 0.0, -1.0), glm.vec3(0.0, -1.0, 0.0))) shadowTransforms = np.array([np.array(m) for m in shadowTransforms]) glViewport(0, 0, shadow_width, shadow_height) with fbo.bind(shadow_depth_fbo), program.use( point_shadow_program) as prog: glClear(GL_DEPTH_BUFFER_BIT) for i in range(6): program.set_uniform(prog, "shadowMatrices[{}]".format(i), shadowTransforms[i]) program.set_uniform(prog, 'farPlane', far_plane) program.set_uniform(prog, 'lightPos', lightPos) # draw scene program.set_uniform(prog, 'model', glm.translate(glm.mat4(1), (-1, 0.5, -1))) imdraw.cube(prog) program.set_uniform(prog, 'model', glm.translate(glm.mat4(1), (1, 0.5, -1))) imdraw.cube(prog)