| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| from ctypes import * |
|
|
| import numpy as np |
| from .framework import * |
|
|
| GLUT = None |
|
|
|
|
| |
| class Render: |
|
|
| def __init__(self, |
| width=1600, |
| height=1200, |
| name='GL Renderer', |
| program_files=['simple.fs', 'simple.vs'], |
| color_size=1, |
| ms_rate=1, |
| egl=False): |
| self.width = width |
| self.height = height |
| self.name = name |
| self.use_inverse_depth = False |
| self.egl = egl |
|
|
| glEnable(GL_DEPTH_TEST) |
|
|
| glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE) |
| glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE) |
| glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE) |
|
|
| |
| shader_list = [] |
|
|
| for program_file in program_files: |
| _, ext = os.path.splitext(program_file) |
| if ext == '.vs': |
| shader_list.append(loadShader(GL_VERTEX_SHADER, program_file)) |
| elif ext == '.fs': |
| shader_list.append(loadShader(GL_FRAGMENT_SHADER, |
| program_file)) |
| elif ext == '.gs': |
| shader_list.append(loadShader(GL_GEOMETRY_SHADER, |
| program_file)) |
|
|
| self.program = createProgram(shader_list) |
|
|
| for shader in shader_list: |
| glDeleteShader(shader) |
|
|
| |
| self.model_mat_unif = glGetUniformLocation(self.program, 'ModelMat') |
| self.persp_mat_unif = glGetUniformLocation(self.program, 'PerspMat') |
|
|
| self.vertex_buffer = glGenBuffers(1) |
|
|
| |
| self.quad_program, self.quad_buffer = self.init_quad_program() |
|
|
| |
| self.frame_buffer = glGenFramebuffers(1) |
| glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer) |
|
|
| self.intermediate_fbo = None |
| if ms_rate > 1: |
| |
| self.color_buffer = [] |
| for i in range(color_size): |
| color_buffer = glGenTextures(1) |
| multi_sample_rate = ms_rate |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_buffer) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
| GL_CLAMP_TO_EDGE) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
| GL_CLAMP_TO_EDGE) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
| GL_LINEAR) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
| GL_LINEAR) |
| glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, |
| multi_sample_rate, GL_RGBA32F, |
| self.width, self.height, GL_TRUE) |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0) |
| glFramebufferTexture2D(GL_FRAMEBUFFER, |
| GL_COLOR_ATTACHMENT0 + i, |
| GL_TEXTURE_2D_MULTISAMPLE, color_buffer, |
| 0) |
| self.color_buffer.append(color_buffer) |
|
|
| self.render_buffer = glGenRenderbuffers(1) |
| glBindRenderbuffer(GL_RENDERBUFFER, self.render_buffer) |
| glRenderbufferStorageMultisample(GL_RENDERBUFFER, |
| multi_sample_rate, |
| GL_DEPTH24_STENCIL8, self.width, |
| self.height) |
| glBindRenderbuffer(GL_RENDERBUFFER, 0) |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, |
| GL_DEPTH_STENCIL_ATTACHMENT, |
| GL_RENDERBUFFER, self.render_buffer) |
|
|
| attachments = [] |
| for i in range(color_size): |
| attachments.append(GL_COLOR_ATTACHMENT0 + i) |
| glDrawBuffers(color_size, attachments) |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
|
|
| self.intermediate_fbo = glGenFramebuffers(1) |
| glBindFramebuffer(GL_FRAMEBUFFER, self.intermediate_fbo) |
|
|
| self.screen_texture = [] |
| for i in range(color_size): |
| screen_texture = glGenTextures(1) |
| glBindTexture(GL_TEXTURE_2D, screen_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 + i, GL_TEXTURE_2D, |
| screen_texture, 0) |
| self.screen_texture.append(screen_texture) |
|
|
| glDrawBuffers(color_size, attachments) |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
| else: |
| self.color_buffer = [] |
| for i in range(color_size): |
| color_buffer = glGenTextures(1) |
| glBindTexture(GL_TEXTURE_2D, color_buffer) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, |
| GL_CLAMP_TO_EDGE) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
| GL_CLAMP_TO_EDGE) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
| GL_NEAREST) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
| GL_NEAREST) |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width, |
| self.height, 0, GL_RGBA, GL_FLOAT, None) |
| glFramebufferTexture2D(GL_FRAMEBUFFER, |
| GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, |
| color_buffer, 0) |
| self.color_buffer.append(color_buffer) |
|
|
| |
| self.depth_buffer = glGenTextures(1) |
| glBindTexture(GL_TEXTURE_2D, self.depth_buffer) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) |
| glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, |
| GL_COMPARE_R_TO_TEXTURE) |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL) |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, self.width, |
| self.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, |
| GL_TEXTURE_2D, self.depth_buffer, 0) |
|
|
| attachments = [] |
| for i in range(color_size): |
| attachments.append(GL_COLOR_ATTACHMENT0 + i) |
| glDrawBuffers(color_size, attachments) |
| self.screen_texture = self.color_buffer |
|
|
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
|
|
| |
| self.render_texture = None |
|
|
| |
| |
| self.render_texture_v2 = {} |
|
|
| |
| self.vertex_data = None |
| self.vertex_dim = None |
| self.n_vertices = None |
|
|
| self.model_view_matrix = None |
| self.projection_matrix = None |
|
|
| if not egl: |
| global GLUT |
| import OpenGL.GLUT as GLUT |
| GLUT.glutDisplayFunc(self.display) |
|
|
| def init_quad_program(self): |
| shader_list = [] |
|
|
| shader_list.append(loadShader(GL_VERTEX_SHADER, "quad.vs")) |
| shader_list.append(loadShader(GL_FRAGMENT_SHADER, "quad.fs")) |
|
|
| the_program = createProgram(shader_list) |
|
|
| for shader in shader_list: |
| glDeleteShader(shader) |
|
|
| |
| |
| quad_vertices = np.array([ |
| -1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0, |
| -1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0 |
| ]) |
|
|
| quad_buffer = glGenBuffers(1) |
| glBindBuffer(GL_ARRAY_BUFFER, quad_buffer) |
| glBufferData(GL_ARRAY_BUFFER, quad_vertices, GL_STATIC_DRAW) |
|
|
| glBindBuffer(GL_ARRAY_BUFFER, 0) |
|
|
| return the_program, quad_buffer |
|
|
| def set_mesh(self, vertices, faces): |
| self.vertex_data = vertices[faces.reshape([-1])] |
| self.vertex_dim = self.vertex_data.shape[1] |
| self.n_vertices = self.vertex_data.shape[0] |
|
|
| glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer) |
| glBufferData(GL_ARRAY_BUFFER, self.vertex_data, GL_STATIC_DRAW) |
|
|
| glBindBuffer(GL_ARRAY_BUFFER, 0) |
|
|
| def set_viewpoint(self, projection, model_view): |
| self.projection_matrix = projection |
| self.model_view_matrix = model_view |
|
|
| def draw_init(self): |
| glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer) |
| glEnable(GL_DEPTH_TEST) |
|
|
| glClearColor(0.0, 0.0, 0.0, 0.0) |
| if self.use_inverse_depth: |
| glDepthFunc(GL_GREATER) |
| glClearDepth(0.0) |
| else: |
| glDepthFunc(GL_LESS) |
| glClearDepth(1.0) |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) |
|
|
| def draw_end(self): |
| if self.intermediate_fbo is not None: |
| for i in range(len(self.color_buffer)): |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, self.frame_buffer) |
| glReadBuffer(GL_COLOR_ATTACHMENT0 + i) |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.intermediate_fbo) |
| glDrawBuffer(GL_COLOR_ATTACHMENT0 + i) |
| glBlitFramebuffer(0, 0, self.width, self.height, 0, 0, |
| self.width, self.height, GL_COLOR_BUFFER_BIT, |
| GL_NEAREST) |
|
|
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
| glDepthFunc(GL_LESS) |
| glClearDepth(1.0) |
|
|
| def draw(self): |
| self.draw_init() |
|
|
| glUseProgram(self.program) |
| glUniformMatrix4fv(self.model_mat_unif, 1, GL_FALSE, |
| self.model_view_matrix.transpose()) |
| glUniformMatrix4fv(self.persp_mat_unif, 1, GL_FALSE, |
| self.projection_matrix.transpose()) |
|
|
| glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer) |
|
|
| glEnableVertexAttribArray(0) |
| glVertexAttribPointer(0, self.vertex_dim, GL_DOUBLE, GL_FALSE, 0, None) |
|
|
| glDrawArrays(GL_TRIANGLES, 0, self.n_vertices) |
|
|
| glDisableVertexAttribArray(0) |
|
|
| glBindBuffer(GL_ARRAY_BUFFER, 0) |
|
|
| glUseProgram(0) |
|
|
| self.draw_end() |
|
|
| def get_color(self, color_id=0): |
| glBindFramebuffer( |
| GL_FRAMEBUFFER, self.intermediate_fbo |
| if self.intermediate_fbo is not None else self.frame_buffer) |
| glReadBuffer(GL_COLOR_ATTACHMENT0 + color_id) |
| data = glReadPixels(0, |
| 0, |
| self.width, |
| self.height, |
| GL_RGBA, |
| GL_FLOAT, |
| outputType=None) |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
| rgb = data.reshape(self.height, self.width, -1) |
| rgb = np.flip(rgb, 0) |
| return rgb |
|
|
| def get_z_value(self): |
| glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer) |
| data = glReadPixels(0, |
| 0, |
| self.width, |
| self.height, |
| GL_DEPTH_COMPONENT, |
| GL_FLOAT, |
| outputType=None) |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
| z = data.reshape(self.height, self.width) |
| z = np.flip(z, 0) |
| return z |
|
|
| def display(self): |
| self.draw() |
|
|
| if not self.egl: |
| |
| |
|
|
| |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) |
|
|
| |
| glClearColor(0.0, 0.0, 0.0, 0.0) |
| glClear(GL_COLOR_BUFFER_BIT) |
|
|
| |
| glUseProgram(self.quad_program) |
| glBindBuffer(GL_ARRAY_BUFFER, self.quad_buffer) |
|
|
| size_of_double = 8 |
| glEnableVertexAttribArray(0) |
| glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, |
| 4 * size_of_double, None) |
| glEnableVertexAttribArray(1) |
| glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, |
| 4 * size_of_double, |
| c_void_p(2 * size_of_double)) |
|
|
| glDisable(GL_DEPTH_TEST) |
|
|
| |
| |
| glActiveTexture(GL_TEXTURE0) |
| glBindTexture(GL_TEXTURE_2D, self.screen_texture[0]) |
| glUniform1i( |
| glGetUniformLocation(self.quad_program, 'screenTexture'), 0) |
|
|
| glDrawArrays(GL_TRIANGLES, 0, 6) |
|
|
| glDisableVertexAttribArray(1) |
| glDisableVertexAttribArray(0) |
|
|
| glEnable(GL_DEPTH_TEST) |
| glBindBuffer(GL_ARRAY_BUFFER, 0) |
| glUseProgram(0) |
|
|
| GLUT.glutSwapBuffers() |
| GLUT.glutPostRedisplay() |
|
|
| def show(self): |
| if not self.egl: |
| GLUT.glutMainLoop() |
|
|