import argparse import os os.environ["PYOPENGL_PLATFORM"] = "egl" import numpy as np import OpenGL.EGL as egl from OpenGL.GL import * from OpenGL.GL import shaders from PIL import Image from OffscreenRenderer.gl_utils import create_opengl_context, init_frame_buffer from OffscreenRenderer.off_screen_render import VertextAttribType, IndexType, generate_vao, set_shader_params, render, \ read_texture VertextAttribType = np.float32 IndexType = np.uint32 OpenglVertexAttrType = GL_FLOAT OpenglTriangleIndexType = GL_UNSIGNED_INT class FlatRenderer: def __init__(self, height=512, width=512, texPath="./assets/measurement.png", back_black=False, phong=False): self.display, self.egl_surf, self.opengl_context = create_opengl_context( (width, height)) self.height = height self.width = width self.texID = read_texture(texPath) self.vao = None self.triangle_vertex_properties = None self.back_black = back_black if phong: from OffscreenRenderer.Shaders.backblack_phong_shaders import VERTEX_SHADER, GEOMETRY_SHADER, FRAGMENT_SHADER self.shader = shaders.compileProgram( shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER), shaders.compileShader(GEOMETRY_SHADER, GL_GEOMETRY_SHADER), shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER), ) else: if not back_black: from OffscreenRenderer.shaders import VERTEX_SHADER, FRAGMENT_SHADER self.shader = shaders.compileProgram( shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER), shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER), ) else: from OffscreenRenderer.Shaders.backblack_shaders import VERTEX_SHADER, GEOMETRY_SHADER, FRAGMENT_SHADER self.shader = shaders.compileProgram( shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER), shaders.compileShader(GEOMETRY_SHADER, GL_GEOMETRY_SHADER), shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER), ) self.rendered_image = np.zeros((height, width, 3), dtype=np.uint8) self.render_frame_object = init_frame_buffer(self.rendered_image) def __del__(self): #glDeleteFramebuffers(1, self.render_frame_object) egl.eglDestroySurface(self.display, self.egl_surf) egl.eglDestroyContext(self.display, self.opengl_context) def render(self, vertex_positions, vertex_texcoord, face_indices, matrix_model=None, matrix_view=None, matrix_proj=None): if self.vao is None: self.generate_vao(vertex_positions, vertex_texcoord, face_indices) else: self.update_vao(vertex_positions, vertex_texcoord, face_indices) glBindFramebuffer(GL_FRAMEBUFFER, self.render_frame_object) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glClearColor(0, 0, 0.0, 1.0) # glEnable(GL_MULTISAMPLE) # glDisable(GL_MULTISAMPLE) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glDepthMask(GL_TRUE) glDisable(GL_CULL_FACE) # glCullFace(GL_FRONT) glUseProgram(self.shader) # Orto projection in range [0; 1] set_shader_params(self.shader, matrix_model=matrix_model, matrix_view=matrix_view, matrix_proj=matrix_proj) glBindVertexArray(self.vao) render(GL_TRIANGLES, len(face_indices), self.texID) glBindVertexArray(0) glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_FRAMEBUFFER, self.render_frame_object) glReadBuffer(GL_COLOR_ATTACHMENT0) data = glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE) glBindFramebuffer(GL_FRAMEBUFFER, 0) # glDeleteFramebuffers(1, render_frame_object) glUseProgram(self.shader) image = Image.frombuffer("RGB", (self.width, self.height), data) return np.array(image) def generate_vao(self, vertex_positions: np.ndarray, texcoord: np.ndarray, face_indices: np.ndarray): assert vertex_positions.ndim == 2 assert vertex_positions.shape[1] == 3 assert vertex_positions.shape[0] == texcoord.shape[0] assert texcoord.shape[1] == 2 assert face_indices.ndim == 1 face_indices = face_indices.astype(IndexType) vertex_attributes = np.hstack( (vertex_positions, texcoord)).astype(VertextAttribType) num_pos_per_vertex = vertex_positions.shape[1] num_texcoord_per_vertex = texcoord.shape[1] triangle_vao = glGenVertexArrays(1) self.vao = triangle_vao glBindVertexArray(triangle_vao) num_properties_per_vertex = vertex_attributes.shape[1] triangle_vertex_properties = glGenBuffers(1) self.triangle_vertex_properties = triangle_vertex_properties glBindBuffer(GL_ARRAY_BUFFER, triangle_vertex_properties) glBufferData(GL_ARRAY_BUFFER, vertex_attributes.nbytes, vertex_attributes, GL_DYNAMIC_DRAW) glEnableVertexAttribArray(0) # Position attribute layout, size, stride, offset glVertexAttribPointer(0, num_pos_per_vertex, OpenglVertexAttrType, GL_FALSE, vertex_attributes.itemsize * num_properties_per_vertex, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) glVertexAttribPointer(1, num_texcoord_per_vertex, OpenglVertexAttrType, GL_FALSE, vertex_attributes.itemsize * num_properties_per_vertex, ctypes.c_void_p(vertex_attributes.itemsize * num_pos_per_vertex)) triangle_indices = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangle_indices) glBufferData(GL_ELEMENT_ARRAY_BUFFER, face_indices.nbytes, face_indices, GL_STATIC_DRAW) glBindVertexArray(0) def update_vao(self, vertex_positions: np.ndarray, texcoord: np.ndarray, face_indices: np.ndarray): assert vertex_positions.ndim == 2 assert vertex_positions.shape[1] == 3 assert vertex_positions.shape[0] == texcoord.shape[0] assert texcoord.shape[1] == 2 assert face_indices.ndim == 1 vertex_attributes = np.hstack( (vertex_positions, texcoord)).astype(VertextAttribType) num_pos_per_vertex = vertex_positions.shape[1] num_texcoord_per_vertex = texcoord.shape[1] triangle_vao = self.vao glBindVertexArray(triangle_vao) num_properties_per_vertex = vertex_attributes.shape[1] triangle_vertex_properties = self.triangle_vertex_properties glBindBuffer(GL_ARRAY_BUFFER, triangle_vertex_properties) glBufferData(GL_ARRAY_BUFFER, vertex_attributes.nbytes, vertex_attributes, GL_DYNAMIC_DRAW) glEnableVertexAttribArray(0) # Position attribute layout, size, stride, offset glVertexAttribPointer(0, num_pos_per_vertex, OpenglVertexAttrType, GL_FALSE, vertex_attributes.itemsize * num_properties_per_vertex, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) glVertexAttribPointer(1, num_texcoord_per_vertex, OpenglVertexAttrType, GL_FALSE, vertex_attributes.itemsize * num_properties_per_vertex, ctypes.c_void_p(vertex_attributes.itemsize * num_pos_per_vertex)) glBindVertexArray(0)