def render(self, environment, camera: Camera360): super().render() # run a quasi monte-carlo simulation on the environment lighting to create a prefilter (cube)map. with puregl.program.use(self.program): puregl.program.set_uniform(self.program, "environmentMap", 0) puregl.program.set_uniform(self.program, "projectionMatrix", camera.projection) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_CUBE_MAP, environment) with puregl.fbo.bind(self.fbo): maxMipLevels = 5 for mip in range(maxMipLevels): # resize framebuffer according to mip-level size. mipWidth = int(128 * glm.pow(0.5, mip)) mipHeight = int(128 * glm.pow(0.5, mip)) glBindRenderbuffer(GL_RENDERBUFFER, self.rbo) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight) glViewport(0, 0, mipWidth, mipHeight) roughness = mip / (maxMipLevels - 1) puregl.program.set_uniform(self.program, "roughness", roughness) for i in range(6): puregl.program.set_uniform(self.program, "viewMatrix", camera.views[i]) glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, self.prefilter, mip) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) imdraw.cube(self.program, flip=True) return self.prefilter
def shade(self, ray, pos, normal, light): output = glm.vec3(0.0) nlightDirection, lightColor = light.getIllumination(pos) nnormal = glm.normalize(normal) diffuseIntensity = glm.dot(nnormal, nlightDirection) output = output + self.diffuse * lightColor * glm.clamp( diffuseIntensity, 0.0, 1.0) nview = glm.normalize(ray.origin - pos) nhalf = glm.normalize(nview + nlightDirection) specularIntensity = glm.pow(glm.dot(nhalf, nnormal), self.shininess) output = output + self.specular * lightColor * glm.clamp( specularIntensity, 0.0, 1.0) output = output + self.emission return glm.vec3(glm.clamp(output.x, 0.0, 1.0), glm.clamp(output.y, 0.0, 1.0), glm.clamp(output.z, 0.0, 1.0))
from editor.render.graphics.examples.viewer import Viewer viewer = Viewer() # assets environment_image = assets.imread('hdri/Tropical_Beach_3k.hdr').astype( np.float32) # scene scene = Scene() scene.add_child( Mesh(transform=glm.translate(glm.mat4(1), (0.0, 0.5, 0.0)), geometry=Geometry(*imdraw.geo.sphere()), material=Material(albedo=glm.vec3(0.5), emission=(0, 0, 0), roughness=glm.pow(0.5, 2), metallic=0.0))) scene.add_child(Mesh(geometry=Geometry(*imdraw.geo.plane()))) dirlight = DirectionalLight(direction=glm.vec3(1, -6, -2), color=glm.vec3(1.0), intensity=1.0, position=-glm.vec3(1, -6, -2), radius=5, near=1, far=30) scene.add_child(dirlight) spotlight = SpotLight(position=glm.vec3(-1, 0.5, -3), direction=glm.vec3(1, -0.5, 3), color=glm.vec3(0.04, 0.6, 1.0),
glGenerateMipmap(GL_TEXTURE_CUBE_MAP) # run a quasi monte-carlo simulation on the environment lighting to create a prefilter (cube)map. with program.use(prefilterShader): program.set_uniform(prefilterShader, "environmentMap", 0) program.set_uniform(prefilterShader, "projectionMatrix", capture_projection) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_CUBE_MAP, env_cubemap) with fbo.bind(capture_fbo): maxMipLevels = 5 for mip in range(maxMipLevels): # resize framebuffer according to mip-level size. mipWidth = int(128 * glm.pow(0.5, mip)) mipHeight = int(128 * glm.pow(0.5, mip)) glBindRenderbuffer(GL_RENDERBUFFER, capture_rbo) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight) glViewport(0, 0, mipWidth, mipHeight) roughness = mip / (maxMipLevels - 1) program.set_uniform(prefilterShader, "roughness", roughness) for i in range(6): program.set_uniform(prefilterShader, "viewMatrix", capture_views[i]) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
Mesh(transform=glm.translate(glm.mat4(1), (x, 0.5, j * 1.5)), geometry=Geometry(*imdraw.geo.sphere()), material=Material(albedo=glm.vec3(0.5), emission=(0, 0, 0), roughness=roughness, metallic=float(j)))) for j in range(2): for x, roughness in zip(np.linspace(-6, 6, 10), np.linspace(0, 1, 10)): scene.add_child( Mesh(transform=glm.translate(glm.mat4(1), (x, 0.5, j * 1.5 - 3)), geometry=Geometry(*imdraw.geo.sphere()), material=Material(albedo=glm.vec3(0.5), emission=(0, 0, 0), roughness=glm.pow(roughness, 2), metallic=float(j)))) dirlight = DirectionalLight(direction=glm.vec3(1, -6, -2), color=glm.vec3(1.0), intensity=1.0, position=-glm.vec3(1, -6, -2), radius=5, near=1, far=30) scene.add_child(dirlight) spotlight = SpotLight(position=glm.vec3(-1, 0.5, -3), direction=glm.vec3(1, -0.5, 3), color=glm.vec3(0.04, 0.6, 1.0), intensity=150.0,
def update(self, deltaTime): # movement in camera coordinates movement = self._currentTransform.orientation * (self._movementInput * self.movementSpeedMod) if self.mode == 0: # rotate position around target # figure out where the old target is oldTarget = self._desiredTransform.position \ + self._desiredTransform.orientation * glm.vec3(0, 0, -1) * self._desiredTargetDistance # rotate the camera self._desiredTransform.orientation = glm.normalize( glm.angleAxis(self._rotationInput.x, self.worldUp) * self._desiredTransform.orientation * glm.angleAxis(self._rotationInput.y, glm.vec3(1, 0, 0))) # move so old target matches new target newTarget = self._desiredTransform.position \ + self._desiredTransform.orientation * glm.vec3(0, 0, -1) * self._desiredTargetDistance self._desiredTransform.position += oldTarget - newTarget # pan # zooming, make sure distance to the target does not become negative if self._desiredTargetDistance + self._movementInput.z > 0.01 * self.zoomSpeed: self._desiredTargetDistance += self._movementInput.z # now just apply movement self._desiredTransform.position += movement # interpolate # interpolate distance to target self._currentTargetDistance = glm.mix( self._currentTargetDistance, self._desiredTargetDistance, glm.pow(deltaTime, self.movementSmoothing)) # interpolate current target position desiredTarget = self._desiredTransform.position + self._desiredTransform.orientation * glm.vec3( 0, 0, -1) * self._desiredTargetDistance oldActualTarget = self._currentTransform.position + self._currentTransform.orientation * glm.vec3( 0, 0, -1) * self._currentTargetDistance oldActualTarget = glm.mix( oldActualTarget, desiredTarget, glm.pow(deltaTime, self.movementSmoothing)) # interpolate orientation self._currentTransform.orientation = glm.slerp( self._currentTransform.orientation, self._desiredTransform.orientation, glm.pow(deltaTime, self.rotationSmoothing)) # calculate proper position using difference that was created by rotation and moving the target newActualTarget = self._currentTransform.position + self._currentTransform.orientation * glm.vec3( 0, 0, -1) * self._currentTargetDistance self._currentTransform.position += oldActualTarget - newActualTarget elif self.mode == 1: # movement self._desiredTransform.position += movement # rotation self._desiredTransform.orientation = glm.normalize( glm.angleAxis(self._rotationInput.x, self.worldUp) * self._desiredTransform.orientation * glm.angleAxis(self._rotationInput.y, glm.vec3(1, 0, 0))) # interpolate between transform and desired transform self._currentTransform.position = glm.mix( self._currentTransform.position, self._desiredTransform.position, glm.pow(deltaTime, self.movementSmoothing)) self._currentTransform.orientation = glm.slerp( self._currentTransform.orientation, self._desiredTransform.orientation, glm.pow(deltaTime, self.rotationSmoothing)) self.modelMatrix = self._currentTransform.mat4() self.viewMatrix = glm.inverse(self.modelMatrix) self._rotationInput.x = 0 self._rotationInput.y = 0 self._movementInput.x = 0 self._movementInput.y = 0 self._movementInput.z = 0 self.movementSpeedMod = 1.0