def on_draw(): a = 1.6 b = a * sqrt(3) / 3 r = sqrt(1 - b * b) R = Vector3(a, a, a).normalized() * b cs = Matrix4.new_translate(R[0], R[1], R[2]) * Matrix4.new_look_at( Vector3(0, 0, 0), R, Vector3(0, 1, 0)) glDisable(GL_DEPTH_TEST) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() draw_coords(Matrix4.new_identity(), 2) draw_line((0, 0, 0), R, (1, 1, 0)) draw_coords(cs, r, 3) glEnable(GL_DEPTH_TEST) draw_triangle((a, 0, 0), (0, a, 0), (0, 0, a), (.5, .5, 1), .2) draw_sphere(3, (1, .5, .5), .2)
def on_draw(self): # Prevent trying to draw before things have been set up if not hasattr(self, "offscreen_buffer"): return # Model matrix we'll use to position the main model suzanne_model_matrix = (Matrix4.new_identity().rotatex( -math.pi / 2).rotatez(time())) # Rotate over time plane_model_matrix = Matrix4.new_rotatey(math.pi).translate(0, 0, 2) # Render to an offscreen buffer with self.offscreen_buffer, self.view_program, \ enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE): gl.glDepthMask(gl.GL_TRUE) w, h = self.size aspect = h / w # Calculate a view frustum; this is basically our camera. near = 5 far = 15 width = 2 height = 2 * aspect frustum = (Matrix4.new(near / width, 0, 0, 0, 0, near / height, 0, 0, 0, 0, -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0)) # The view matrix positions the camera in the scene view_matrix = (Matrix4.new_identity().translate(0, 0, -8)) # Send the matrices to GL gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, gl_matrix(frustum * view_matrix)) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(suzanne_model_matrix)) gl.glUniform4f(2, 0.3, 0.3, 1, 1) # Set the "color" uniform to blue self.suzanne.draw() # We'll also draw a simple plane behind the main model gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(plane_model_matrix)) gl.glUniform4f(2, 0.3, 1, 0.3, 1) # Set the "color" uniform to green self.plane.draw(mode=gl.GL_TRIANGLE_STRIP) # Render shadow buffer # Basically the same scene as above, but to a different buffer and from a different view with self.shadow_buffer, self.view_program, enabled( gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE): gl.glDepthMask(gl.GL_TRUE) frustum = Matrix4.new_perspective(1, 1, 1, 12) view_matrix = (Matrix4.new_identity().translate( 0, 0, -4).rotatey(0.5).rotatex(0.3)) light_pos = (view_matrix.inverse() * Point3(0, 0, 0)) light_view_matrix = frustum * view_matrix gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, gl_matrix(light_view_matrix)) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(suzanne_model_matrix)) gl.glUniform4f(2, 0.9, 0.3, 0.4, 1) self.suzanne.draw() gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(plane_model_matrix)) self.plane.draw(mode=gl.GL_TRIANGLE_STRIP) # Now draw the offscreen buffer to another buffer, combining it with the # lighting information to get a nice image. # Note: This step is pretty pointless here, as we might just draw directly to screen. # Just demonstrates how to do it. with self.vao, self.offscreen_buffer2, self.lighting_program, disabled( gl.GL_CULL_FACE, gl.GL_DEPTH_TEST): gl.glUniform3f(0, *light_pos) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(light_view_matrix)) # Bind some of the offscreen buffer's textures so the shader can read them. with self.offscreen_buffer["color"], self.offscreen_buffer["normal"], \ self.offscreen_buffer["position"], self.shadow_buffer["depth"]: gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) # Now render the finished image to the screen with self.vao, self.copy_program, disabled(gl.GL_CULL_FACE, gl.GL_DEPTH_TEST): with self.offscreen_buffer2["color"]: gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)