def SendAndRecv(self, sendCmd, sendValue, checkRecvCmd, checkReceiveValue): # send message - must be a tuple type self.pipe.send((sendCmd, sendValue)) # wait recv message - must be a tuple type recv, value = self.pipe.recv() if self.simpleLog: logger.log(MINOR_INFO, "Pipe : Send %s and Recv %s in %s" % ( get_command_name(sendCmd), get_command_name(recv), getTraceCallStack())) else: logger.log(MINOR_INFO, "Pipe : Send %s, %s and Recv %s, %s in %s" % ( get_command_name(sendCmd), str(sendValue), get_command_name(recv), str(value), getTraceCallStack())) # check receive correct command and value if recv != checkRecvCmd or (checkReceiveValue is not None and checkReceiveValue != value): if self.simpleLog: logger.log(MINOR_INFO, "Pipe : RecvFailed %s and Send %s in %s" % (get_command_name(recv), COMMAND.FAIL, getTraceCallStack())) else: logger.log(MINOR_INFO, "Pipe : RecvFailed %s, %s and Send %s, %s in %s" % ( get_command_name(recv), str(value), COMMAND.FAIL, "None", getTraceCallStack())) logger.error("ERROR : Received %s not %s" % (recv, checkRecvCmd)) raise BaseException("Pipe receive error.") return value
def get_numpy_dtype(data_type): if GL_BYTE == data_type: return np.int8 elif GL_UNSIGNED_BYTE == data_type: return np.uint8 elif GL_UNSIGNED_BYTE == data_type: return np.uint8 elif GL_SHORT == data_type: return np.int16 elif GL_UNSIGNED_SHORT == data_type: return np.uint16 elif GL_INT == data_type: return np.int32 elif GL_UNSIGNED_INT == data_type: return np.uint32 elif GL_UNSIGNED_INT64 == data_type: return np.uint64 elif GL_FLOAT == data_type: return np.float32 elif GL_DOUBLE == data_type: return np.float64 logger.error('Cannot convert to numpy dtype. UNKOWN DATA TYPE(%s)', data_type) return np.uint8
def IsExtensionSupported(TargetExtension): """ Accesses the rendering context to see if it supports an extension. Note, that this test only tells you if the OpenGL library supports the extension. The PyOpenGL system might not actually support the extension. """ Extensions = glGetString(GL_EXTENSIONS) Extensions = Extensions.split() bTargetExtension = str.encode(TargetExtension) for extension in Extensions: if extension == bTargetExtension: break else: # not found surpport msg = "OpenGL rendering context does not support '%s'" % TargetExtension logger.error(msg) raise BaseException(msg) # Now determine if Python supports the extension # Exentsion names are in the form GL_<group>_<extension_name> # e.g. GL_EXT_fog_coord # Python divides extension into modules # g_fVBOSupported = IsExtensionSupported ("GL_ARB_vertex_buffer_object") # from OpenGL.GL.EXT.fog_coord import * m = re.match(reCheckGLExtention, TargetExtension) if m: group_name = m.groups()[0] extension_name = m.groups()[1] else: msg = "GL unsupport error, %s" % TargetExtension logger.error(msg) raise BaseException(msg) extension_module_name = "OpenGL.GL.%s.%s" % (group_name, extension_name) try: __import__(extension_module_name) logger.info("PyOpenGL supports '%s'" % TargetExtension) except: msg = 'Failed to import', extension_module_name logger.error(msg) raise BaseException(msg) return True
def parsing_matrix(self, xml_node): xml_matrix = xml_node.find('matrix') if xml_matrix is not None: # transform matrix matrix = get_xml_text(xml_matrix) matrix = [eval(x) for x in matrix.split()] if len(matrix) == 16: self.matrix = np.array(matrix, dtype=np.float32).reshape(4, 4) else: # location, rotation, scale xml_translate = xml_node.find('translate') if xml_translate is not None: translation = [ eval(x) for x in get_xml_text(xml_translate).split() ] if len(translation) == 3: matrix_translate(self.matrix, *translation) else: logger.error('%s node has a invalid translate.' % self.name) xml_rotates = xml_node.findall('rotate') for xml_rotate in xml_rotates: rotation = [eval(x) for x in get_xml_text(xml_rotate).split()] if len(rotation) == 4: axis = get_xml_attrib(xml_rotate, 'sid') if axis == 'rotationX': matrix_rotate_x(self.matrix, rotation[3]) elif axis == 'rotationY': matrix_rotate_y(self.matrix, rotation[3]) elif axis == 'rotationZ': matrix_rotate_z(self.matrix, rotation[3]) else: logger.error('%s node has a invalid rotate.' % self.name) xml_scale = xml_node.find('scale') if xml_scale is not None: scale = [eval(x) for x in get_xml_text(xml_scale).split()] if len(scale) == 3: matrix_scale(self.matrix, *scale) else: logger.error('%s node has a invalid scale.' % self.name)
def initialize(): try: logger.info("=" * 30) infos = [ GL_VERSION, GL_RENDERER, GL_VENDOR, GL_SHADING_LANGUAGE_VERSION ] for info in infos: info_string = glGetString(info) if type(info_string) == bytes: info_string = info_string.decode("utf-8") logger.info("%s : %s" % (info.name, info_string)) # set value setattr(OpenGLContext, info.name, info_string) infos = [ GL_MAX_VERTEX_ATTRIBS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_UNIFORM_COMPONENTS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_GEOMETRY_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, GL_MAX_UNIFORM_BLOCK_SIZE, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_DRAW_BUFFERS, GL_MAX_TEXTURE_COORDS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_VARYING_FLOATS ] for info in infos: logger.info("%s : %s" % (info.name, glGetIntegerv(info))) # set value setattr(OpenGLContext, info.name, glGetIntegerv(info)) # shader storage infos = [ GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS ] for info in infos: logger.info("%s : %s" % (info.name, glGetIntegerv(info))) # set value setattr(OpenGLContext, info.name, glGetIntegerv(info)) # compute shader OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_COUNT = [ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, i)[0] for i in range(3) ] OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_SIZE = [ glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, i)[0] for i in range(3) ] logger.info("%s : %s" % (GL_MAX_COMPUTE_WORK_GROUP_COUNT.name, OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_COUNT)) logger.info("%s : %s" % (GL_MAX_COMPUTE_WORK_GROUP_SIZE.name, OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_SIZE)) # OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS = glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS) # logger.info("%s : %s" % ( # GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS.name, OpenGLContext.GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS # )) logger.info("=" * 30) except BaseException: logger.error(traceback.format_exc())
def loadDDS(imagepath): if not os.path.exists(imagepath): logger.error("Cannot open %s file" % imagepath) return None with open(imagepath, "rb") as fp: filecode = struct.unpack("4s", fp.read(4))[0] if filecode.decode('ascii') != "DDS ": logger.error("%s is not dds file." % imagepath) return None # read header header = struct.unpack("124s", fp.read(124))[0] height = struct.unpack("I", header[8:12])[0] width = struct.unpack("I", header[12:16])[0] linearSize = struct.unpack("I", header[16:20])[0] mipMapCount = struct.unpack("I", header[24:28])[0] fourCC = struct.unpack("4s", header[80:84])[0] fourCC = fourCC.decode('ascii') # read buffer bufsize = (linearSize * 2) if mipMapCount > 1 else linearSize buffer = fp.read(bufsize) # buffer = np.asarray(buffer) buffer = np.fromstring(buffer, dtype=np.ubyte) # texture desc components = 4 blockSize = 16 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT if fourCC == "DXT1": format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT components = 3 blockSize = 8 elif fourCC == "DXT3": format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT elif fourCC == "DXT5": format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT else: logger.error("not support %s format" % fourCC) return None # Create one OpenGL texture offset = 0 textureID = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, textureID) for level in range(mipMapCount): if width > 0 and height > 0: size = int((width + 3)/4) * int((height + 3)/4) * blockSize # TODO : implement glCompressedTexImage2D # glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, size, buffer.ctypes.data) glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, buffer) offset += size width /= 2 height /= 2 else: break return textureID return None
def CreateUniformDataFromString(data_type, strValue=None): """ return converted data from string or default data """ if data_type == 'bool': return np.bool(strValue) if strValue else np.bool(False) elif data_type == 'float': # return float(strValue) if strValue else 0.0 return np.float32(strValue) if strValue else np.float32(0) elif data_type == 'int': # return int(strValue) if strValue else 0 return np.int32(strValue) if strValue else np.int32(0) elif data_type == 'uint': # return int(strValue) if strValue else 0 return np.uint32(strValue) if strValue else np.uint32(0) elif data_type in ('vec2', 'vec3', 'vec4', 'bvec2', 'bvec3', 'bvec4', 'ivec2', 'ivec3', 'ivec4', 'uvec2', 'uvec3', 'uvec4'): if data_type in ('bvec2', 'bvec3', 'bvec4', 'ivec2', 'ivec3', 'ivec4'): dtype = np.int32 elif data_type in ('uvec2', 'uvec3', 'uvec4'): dtype = np.uint32 else: dtype = np.float32 componentCount = int(data_type[-1]) if strValue is not None: vecValue = eval(strValue) if type(strValue) is str else strValue if len(vecValue) == componentCount: return np.array(vecValue, dtype=dtype) else: logger.error(ValueError("%s need %d float members." % (data_type, componentCount))) raise ValueError else: return np.array([1, ] * componentCount, dtype=dtype) elif data_type in ('mat2', 'mat3', 'mat4', 'dmat2', 'dmat3', 'dmat4'): if data_type in ('dmat2', 'dmat3', 'dmat4'): dtype = np.float32 else: dtype = np.double componentCount = int(data_type[-1]) if strValue is not None: vecValue = eval(strValue) if type(strValue) is str else strValue if len(vecValue) == componentCount: return np.array(vecValue, dtype=dtype) else: logger.error(ValueError("%s need %d float members." % (data_type, componentCount))) raise ValueError else: return np.eye(componentCount, dtype=dtype) elif data_type in ('sampler2D', 'image2D'): texture = CoreManager.instance().resource_manager.get_texture(strValue or 'common.flat_gray') return texture elif data_type == 'sampler2DMS': logger.warn('sampler2DMS need multisample texture.') return CoreManager.instance().resource_manager.get_texture(strValue or 'common.flat_gray') elif data_type == 'sampler2DArray': return CoreManager.instance().resource_manager.get_texture(strValue or 'common.default_2d_array') elif data_type in ('sampler3D', 'image3D'): return CoreManager.instance().resource_manager.get_texture(strValue or 'common.default_3d') elif data_type == 'samplerCube': texture = CoreManager.instance().resource_manager.get_texture(strValue or 'common.default_cube') return texture error_message = 'Cannot find uniform data of %s.' % data_type logger.error(error_message) raise ValueError(error_message) return None
def bind_uniform(self, texture, level=0, access=GL_READ_WRITE): if texture is not None: texture.bind_image(self.textureIndex, level, access) elif self.show_message: self.show_message = False logger.error("%s %s is None" % (self.name, self.__class__.__name__))
def initialize(self, cmdQueue, uiCmdQueue, cmdPipe, project_filename=""): # process start logger.info('Platform : %s' % platformModule.platform()) logger.info("Process Start : %s" % GetClassName(self)) self.cmdQueue = cmdQueue self.uiCmdQueue = uiCmdQueue self.cmdPipe = cmdPipe self.config = Config("config.ini", log_level) self.regist_command() # ready to launch - send message to ui if self.cmdPipe: self.cmdPipe.SendAndRecv(COMMAND.UI_RUN, None, COMMAND.UI_RUN_OK, None) from PyEngine3D.UI import ViewportManager from PyEngine3D.OpenGLContext import OpenGLContext from PyEngine3D.ResourceManager import ResourceManager from PyEngine3D.Render import Renderer, RenderTargetManager, FontManager, RenderOptionManager, EffectManager from .SceneManager import SceneManager from .ProjectManager import ProjectManager self.opengl_context = OpenGLContext self.viewport_manager = ViewportManager.instance() self.render_option_manager = RenderOptionManager.instance() self.rendertarget_manager = RenderTargetManager.instance() self.resource_manager = ResourceManager.instance() self.font_manager = FontManager.instance() self.renderer = Renderer.instance() self.scene_manager = SceneManager.instance() self.effect_manager = EffectManager.instance() self.project_manager = ProjectManager.instance() # check invalid project if not self.project_manager.initialize(self, project_filename): self.valid = False self.exit() return False # do First than other manager initalize. Because have to been opengl init from pygame.display.set_mode width, height = self.project_manager.config.Screen.size full_screen = self.project_manager.config.Screen.full_screen if self.config.hasValue('Project', 'game_backend'): self.last_game_backend = self.config.getValue( 'Project', 'game_backend') self.last_game_backend = self.last_game_backend.lower() def run_pygame(): from .GameBackend import GameBackend_pygame self.game_backend = GameBackend_pygame.PyGame(self) self.last_game_backend = GameBackNames.PYGAME def run_pyglet(): from .GameBackend import GameBackend_pyglet self.game_backend = GameBackend_pyglet.PyGlet(self) self.last_game_backend = GameBackNames.PYGLET # try 2 times. for i in range(2): if self.last_game_backend == GameBackNames.PYGAME: try: run_pygame() break except: logger.error( "The pygame library does not exist and execution failed. Run again with the pyglet." ) self.last_game_backend = GameBackNames.PYGLET else: try: run_pyglet() break except: logger.error( "The pyglet library does not exist and execution failed. Run again with the pygame." ) self.last_game_backend = GameBackNames.PYGAME else: logger.error( 'PyGame or PyGlet is required. Please run "pip install -r requirements.txt" and try again.' ) # send a message to close ui if self.uiCmdQueue: self.uiCmdQueue.put(COMMAND.CLOSE_UI) return False self.game_backend.create_window(width, height, full_screen) self.opengl_context.initialize() self.send_game_backend_list(self.game_backend_list) index = self.game_backend_list.index( self.last_game_backend ) if self.last_game_backend in self.game_backend_list else 0 self.send_current_game_backend_index(index) if not self.game_backend.valid: self.error('game_backend initializing failed') # initialize managers self.resource_manager.initialize(self, self.project_manager.project_dir) self.viewport_manager.initialize(self) self.render_option_manager.initialize(self) self.rendertarget_manager.initialize(self) self.font_manager.initialize(self) self.renderer.initialize(self) self.effect_manager.initialize(self) self.scene_manager.initialize(self) self.viewport_manager.build_ui() self.script_manager = None # self.load_script_manager(reload=False) # new scene self.game_backend.reset_screen() self.scene_manager.new_scene() self.send(COMMAND.SORT_UI_ITEMS) return True
def update(self): current_time = time.perf_counter() delta = current_time - self.current_time if self.vsync and delta < self.limit_delta or delta == 0.0: return self.acc_time += delta self.frame_count += 1 self.curr_min_delta = min(delta, self.curr_min_delta) self.curr_max_delta = max(delta, self.curr_max_delta) # set timer self.current_time = current_time self.delta = delta self.fps = 1.0 / delta self.update_time = delta * 1000.0 # millisecond start_time = time.perf_counter() if self.video_resized and self.video_resize_time < self.current_time: self.video_resized = False self.video_resize_time = 0 self.game_backend.resize_scene_to_window() touch_event = self.viewport_manager.update(delta) self.update_command() self.resource_manager.update() if not touch_event and self.viewport_manager.main_viewport.collide( *self.get_mouse_pos()): if self.is_play_mode: if self.script_manager is not None: try: self.script_manager.update(delta) except: logger.error(traceback.format_exc()) else: self.update_camera() self.scene_manager.update_scene(delta) # Start Render Scene end_time = time.perf_counter() self.logic_time = (end_time - start_time) * 1000.0 # millisecond start_time = end_time if not self.video_resized: # render_light_probe scene self.renderer.render_light_probe( self.scene_manager.main_light_probe) # render sceme self.renderer.render_scene() # render viewport self.viewport_manager.render() end_time = time.perf_counter() self.render_time = (end_time - start_time) * 1000.0 # millisecond start_time = end_time # end of render scene self.opengl_context.present() # swap buffer self.game_backend.flip() end_time = time.perf_counter() self.present_time = (end_time - start_time) * 1000.0 # millisecond self.acc_logic_time += self.logic_time self.acc_gpu_time += self.gpu_time self.acc_render_time += self.render_time self.acc_present_time += self.present_time if 1.0 < self.acc_time: self.avg_logic_time = self.acc_logic_time / self.frame_count self.avg_gpu_time = self.acc_gpu_time / self.frame_count self.avg_render_time = self.acc_render_time / self.frame_count self.avg_present_time = self.acc_present_time / self.frame_count self.acc_logic_time = 0.0 self.acc_gpu_time = 0.0 self.acc_render_time = 0.0 self.acc_present_time = 0.0 self.min_delta = self.curr_min_delta * 1000.0 self.max_delta = self.curr_max_delta * 1000.0 self.curr_min_delta = sys.float_info.max self.curr_max_delta = sys.float_info.min self.avg_ms = self.acc_time / self.frame_count * 1000.0 self.avg_fps = 1000.0 / self.avg_ms self.frame_count = 0 self.acc_time = 0.0 # debug info # print(self.fps, self.update_time) self.font_manager.log("%.2f fps" % self.avg_fps) self.font_manager.log("%.2f ms (%.2f ms ~ %.2f ms)" % (self.avg_ms, self.min_delta, self.max_delta)) self.font_manager.log("CPU : %.2f ms" % self.avg_logic_time) self.font_manager.log("GPU : %.2f ms" % self.avg_gpu_time) self.font_manager.log("Render : %.2f ms" % self.avg_render_time) self.font_manager.log("Present : %.2f ms" % self.avg_present_time) render_count = len(self.scene_manager.skeleton_solid_render_infos) render_count += len( self.scene_manager.skeleton_translucent_render_infos) render_count += len(self.scene_manager.static_solid_render_infos) render_count += len(self.scene_manager.static_translucent_render_infos) self.font_manager.log("Render Count : %d" % render_count) self.font_manager.log("Point Lights : %d" % self.scene_manager.point_light_count) self.font_manager.log("Effect Count : %d" % len(self.effect_manager.render_effects)) self.font_manager.log("Particle Count : %d" % self.effect_manager.alive_particle_count) # selected object transform info selected_object = self.scene_manager.get_selected_object() if selected_object: self.font_manager.log("Selected Object : %s" % selected_object.name) if hasattr(selected_object, 'transform'): self.font_manager.log( selected_object.transform.get_transform_infos()) self.gpu_time = (time.perf_counter() - start_time) * 1000.0 if self.need_to_gc_collect: self.need_to_gc_collect = False gc.collect()
def error(self, msg): logger.error(msg) self.close()
def generate_font_data(resource_name, distance_field_font, anti_aliasing, font_size, padding, unicode_block_name, range_min, range_max, source_filepath, preview_path=''): logger.info("Convert Font %s %s : %s" % (resource_name, unicode_block_name, source_filepath)) back_ground_color = (0, 0, 0) font_color = (255, 255, 255) count = abs(range_max - range_min) + 1 count_of_side = int(math.ceil(math.sqrt(count))) # make texture size to power of 2. # texture_size = (2 ** math.ceil(math.log2(texture_size))) if 4 < texture_size else 4 try: unicode_font = ImageFont.truetype(source_filepath, font_size - padding * 2) except: logger.error(traceback.format_exc()) return None max_font_size = font_size for unicode_index in range(range_min, range_max + 1): unicode_text = chr( unicode_index ) # u"\u2605" + u"\u2606" + u"Текст на русском" + u"파이썬" width, height = unicode_font.getsize(unicode_text) max_font_size = max(max_font_size, max(width, height)) font_size = max_font_size texture_size = font_size * count_of_side if texture_size > 8096: logger.error("%s texture size is too large. %d" % (unicode_block_name, texture_size)) return None image = Image.new("RGB", (texture_size, texture_size), back_ground_color) draw = ImageDraw.Draw(image) if anti_aliasing: draw.fontmode = "L" else: draw.fontmode = "1" unicode_index = range_min for y in range(count_of_side): for x in range(count_of_side): unicode_text = chr( unicode_index ) # u"\u2605" + u"\u2606" + u"Текст на русском" + u"파이썬" draw.text((x * font_size, y * font_size), unicode_text, font=unicode_font, fill=font_color) unicode_index += 1 if unicode_index >= range_max: break else: continue break # Flip Vertical # image = image.transpose(Image.FLIP_TOP_BOTTOM) image_data = image.tobytes("raw", image.mode, 0, -1) if distance_field_font: image_data = DistanceField(font_size, image.size[0], image.size[1], image.mode, image_data) # save for preview if preview_path: texture_name = "_".join([resource_name, unicode_block_name]) image = Image.frombytes(image.mode, image.size, image_data) image.save(os.path.join(preview_path, texture_name + ".png")) # image.show() font_data = dict(unicode_block_name=unicode_block_name, range_min=range_min, range_max=range_max, text_count=count, font_size=font_size, count_of_side=count_of_side, image_mode=image.mode, image_width=image.size[0], image_height=image.size[1], image_data=image_data, texture=None) return font_data
def CreateVertexArrayBuffer(geometry_data): geometry_name = geometry_data.get('name', 'VertexArrayBuffer') # logger.info("Load %s geometry." % geometry_name) mode = geometry_data.get('mode', GL_TRIANGLES) positions = geometry_data.get('positions', []) indices = geometry_data.get('indices', []) bone_indicies = geometry_data.get('bone_indicies', []) bone_weights = geometry_data.get('bone_weights', []) vertex_count = len(positions) if 0 == vertex_count: logger.error("%s geometry has no position data." % geometry_name) return None if 0 == len(indices): logger.error("%s geometry has no index data." % geometry_name) return None if not isinstance(positions, np.ndarray): positions = np.array(positions, dtype=np.float32) if not isinstance(indices, np.ndarray): indices = np.array(indices, dtype=np.uint32) if not isinstance(bone_indicies, np.ndarray): bone_indicies = np.array(bone_indicies, dtype=np.float32) if not isinstance(bone_weights, np.ndarray): bone_weights = np.array(bone_weights, dtype=np.float32) colors = geometry_data.get('colors', [ [1.0, 1.0, 1.0, 1.0], ] * vertex_count) texcoords = geometry_data.get('texcoords', [ [0.0, 0.0], ] * vertex_count) normals = geometry_data.get('normals', [ [1.0, 1.0, 1.0], ] * vertex_count) tangents = geometry_data.get('tangents', []) if not isinstance(colors, np.ndarray): colors = np.array(colors, dtype=np.float32) if not isinstance(texcoords, np.ndarray): texcoords = np.array(texcoords, dtype=np.float32) if not isinstance(normals, np.ndarray): normals = np.array(normals, dtype=np.float32) if not isinstance(tangents, np.ndarray): tangents = np.array(tangents, dtype=np.float32) if len(tangents) == 0: is_triangle_mode = (GL_TRIANGLES == mode) tangents = compute_tangent(is_triangle_mode, positions, texcoords, normals, indices) if 0 < len(bone_indicies) and 0 < len(bone_weights): vertex_array_buffer = VertexArrayBuffer(geometry_name, mode, [ positions, colors, normals, tangents, texcoords, bone_indicies, bone_weights ], indices) else: vertex_array_buffer = VertexArrayBuffer( geometry_name, mode, [positions, colors, normals, tangents, texcoords], indices) return vertex_array_buffer
def bind_texture(self, wrap=None): logger.error('%s RenderBuffer cannot use bind_texture method.' % self.name)
def __parsing_final_code__(self, is_engine_resource, engine_shader_directory, project_shader_directory, shader_type_name, shader_version, compile_option, external_macros={}): if self.shader_code == "" or self.shader_code is None: return "" # remove comment block shader_code = re.sub(reComment, "", self.shader_code) code_lines = shader_code.splitlines() # combine macro combined_macros = OrderedDict() # default macro for macro in self.default_macros: combined_macros[macro] = self.default_macros[macro] # shader type macro combined_macros[shader_type_name] = "1" # external macro if external_macros is None: external_macros = {} for macro in external_macros: if external_macros[macro] is None or external_macros[macro] is '': combined_macros[macro] = 0 else: combined_macros[macro] = external_macros[macro] # insert shader version - ex) #version 430 core final_code_lines = [ shader_version, "# extension GL_EXT_texture_array : enable" ] # insert defines to final code for macro in combined_macros: final_code_lines.append("#define %s %s" % (macro, str(combined_macros[macro]))) # global texture function if ShaderCompileOption.USE_GLOBAL_TEXTURE_FUNCTION in compile_option: final_code_lines.append("#if __VERSION__ >= 130") # ex) replace texture2D -> texutre, textureCubeLod -> textureLod for texture_target in texture_targets: if "Lod" in texture_target: final_code_lines.append("#define %s textureLod" % texture_target) elif "Grad" in texture_target: final_code_lines.append("#define %s textureGrad" % texture_target) else: final_code_lines.append("#define %s texture" % texture_target) final_code_lines.append("#endif") # insert version as comment include_files = dict() # { 'filename': uuid } # do parsing line_num = 0 macro_depth = 0 macro_result = [ True, ] macro_code_remove = True while line_num < len(code_lines): code = code_lines[line_num] line_num += 1 # remove comment if "//" in code: code = code.split("//")[0] # macro parsing m = re.search(reMacroStart, code) if m is not None: macro, expression = m.groups() expression = expression.strip() if macro == 'define' or macro == 'undef': define_expression = expression.split('(')[0].strip() if ' ' in define_expression: define_name, define_value = define_expression.split( ' ', 1) else: define_name, define_value = define_expression, None # check external macro if macro == 'define' and define_name in external_macros: continue # ignore legacy macro if macro == 'define' and define_name not in combined_macros: combined_macros[define_name] = define_value elif macro == 'undef' and define_name in combined_macros: combined_macros.pop(define_name) elif macro == 'ifdef': macro_depth += 1 if expression in combined_macros: macro_result.append(True) else: macro_result.append(False) elif macro == 'ifndef': macro_depth += 1 if expression not in combined_macros: macro_result.append(True) else: macro_result.append(False) elif macro == 'if' or macro == 'elif' and not macro_result[ macro_depth]: variables = re.findall(reVariable, expression) variables.sort(key=lambda x: len(x), reverse=True) for variable in variables: if variable in combined_macros: while True: final_value = combined_macros[variable] if final_value not in combined_macros: break variable = final_value expression = re.sub(reVariable, str(final_value), expression, 1) expression = expression.replace('&&', ' and ') expression = expression.replace('||', ' or ') # expression = re.sub('\!?!\=', 'not ', expression) # Important : To avoid errors, convert the undecalred variables to zero. expression = re.sub(reVariable, '0', expression) result = True if eval(expression) else False if macro == 'if': macro_depth += 1 macro_result.append(result) elif macro == 'elif': macro_result[macro_depth] = result elif macro == 'else': macro_result[macro_depth] = not macro_result[macro_depth] elif macro == 'endif': macro_depth -= 1 macro_result.pop() # be in failed macro block. continue elif not macro_result[macro_depth]: if not macro_code_remove: # make comment final_code_lines.append("// " + code) continue # is version code? m = re.search(reVersion, code) if m is not None: version_code = m.groups()[0].strip() if final_code_lines[ 0] == "" or version_code > final_code_lines[0]: final_code_lines[0] = version_code continue # find include block m = re.search(reInclude, code) if m is not None: is_include_file_exists = False include_file_in_engine = os.path.join(engine_shader_directory, m.groups()[0]) include_file_in_project = os.path.join( project_shader_directory, m.groups()[0]) if is_engine_resource: if os.path.exists(include_file_in_engine): include_file = include_file_in_engine is_include_file_exists = True else: include_file = include_file_in_project else: if os.path.exists(include_file_in_project): include_file = include_file_in_project is_include_file_exists = True else: include_file = include_file_in_engine # insert include code valid = False if is_include_file_exists or os.path.exists(include_file): try: f = codecs.open(include_file, mode='r', encoding='utf-8') include_source = f.read() # remove comment block include_source = re.sub(reComment, "", include_source) include_code_lines = include_source.splitlines() f.close() valid = True except BaseException: logger.error(traceback.format_exc()) if valid: if include_file in include_files: unique_id = include_files[include_file] else: unique_id = "UUID_" + str( uuid.uuid3(uuid.NAMESPACE_DNS, include_file)).replace("-", "_") include_files[include_file] = unique_id if include_file not in self.include_files: self.include_files.append(include_file) # insert included code final_code_lines.append( "//------------ INCLUDE -------------//") final_code_lines.append("// " + code) # include comment include_code_lines.insert(0, "#ifndef %s" % unique_id) include_code_lines.insert(1, "#define %s" % unique_id) include_code_lines.append("#endif /* %s */" % unique_id) code_lines = include_code_lines + code_lines[line_num:] line_num = 0 if not valid: logger.error( "Shader parsing error.\n\t--> Cannot open %s file." % include_file) continue # append code block final_code_lines.append(code) return '\n'.join(final_code_lines)
def __init__(self, core_manager): GameBackend.__init__(self, core_manager) logger.info('GameBackend : pygame %s' % pygame.__version__) # centered window os.environ['SDL_VIDEO_CENTERED'] = '1' pygame.mixer.pre_init(44100, -16, 2, 4096) pygame.mixer.init() pygame.init() self.screen_width = pygame.display.Info().current_w self.screen_height = pygame.display.Info().current_h self.set_mouse_grab(self.get_mouse_grab()) pygame.font.init() if not pygame.font.get_init(): logger.error('Could not render font.') return # ASCII commands Keyboard.BACKSPACE = K_BACKSPACE Keyboard.TAB = K_TAB # Keyboard.LINEFEED = K_LINEFEED Keyboard.CLEAR = K_CLEAR Keyboard.RETURN = K_RETURN Keyboard.ENTER = K_KP_ENTER Keyboard.PAUSE = K_PAUSE Keyboard.SCROLLLOCK = K_SCROLLOCK Keyboard.SYSREQ = K_SYSREQ Keyboard.ESCAPE = K_ESCAPE Keyboard.SPACE = K_SPACE # Cursor control and motion Keyboard.HOME = K_HOME Keyboard.LEFT = K_LEFT Keyboard.UP = K_UP Keyboard.RIGHT = K_RIGHT Keyboard.DOWN = K_DOWN Keyboard.PAGEUP = K_PAGEUP Keyboard.PAGEDOWN = K_PAGEDOWN Keyboard.END = K_END # Keyboard.BEGIN = K_BEGIN # Misc functions Keyboard.DELETE = K_DELETE # Keyboard.SELECT = K_SELECT Keyboard.PRINT = K_PRINT # Keyboard.EXECUTE = K_EXECUTE Keyboard.INSERT = K_INSERT # Keyboard.UNDO = K_UNDO # Keyboard.REDO = K_REDO Keyboard.MENU = K_MENU # Keyboard.FIND = K_FIND # Keyboard.CANCEL = K_CANCEL Keyboard.HELP = K_HELP Keyboard.BREAK = K_BREAK # Keyboard.MODESWITCH = K_MODESWITCH # Keyboard.SCRIPTSWITCH = K_SCRIPTSWITCH # Keyboard.FUNCTION = K_FUNCTION # Number pad Keyboard.NUMLOCK = K_NUMLOCK # Keyboard.NUM_SPACE = K_NUM_SPACE # Keyboard.NUM_TAB = K_NUM_TAB # Keyboard.NUM_ENTER = K_NUM_ENTER # Keyboard.NUM_F1 = K_NUM_F1 # Keyboard.NUM_F2 = K_NUM_F2 # Keyboard.NUM_F3 = K_NUM_F3 # Keyboard.NUM_F4 = K_NUM_F4 # Keyboard.NUM_HOME = K_NUM_HOME # Keyboard.NUM_LEFT = K_NUM_LEFT # Keyboard.NUM_UP = K_NUM_UP # Keyboard.NUM_RIGHT = K_NUM_RIGHT # Keyboard.NUM_DOWN = K_NUM_DOWN # Keyboard.NUM_PRIOR = K_NUM_PRIOR # Keyboard.NUM_PAGE_UP = K_NUM_PAGE_UP # Keyboard.NUM_NEXT = K_NUM_NEXT # Keyboard.NUM_PAGE_DOWN = K_NUM_PAGE_DOWN # Keyboard.NUM_END = K_NUM_END # Keyboard.NUM_BEGIN = K_NUM_BEGIN # Keyboard.NUM_INSERT = K_NUM_INSERT # Keyboard.NUM_DELETE = K_NUM_DELETE # Keyboard.NUM_EQUAL = K_NUM_EQUAL # Keyboard.NUM_MULTIPLY = K_NUM_MULTIPLY # Keyboard.NUM_ADD = K_NUM_ADD # Keyboard.NUM_SEPARATOR = K_NUM_SEPARATOR # Keyboard.NUM_SUBTRACT = K_NUM_SUBTRACT # Keyboard.NUM_DECIMAL = K_NUM_DECIMAL # Keyboard.NUM_DIVIDE = K_NUM_DIVIDE # Keyboard.NUM_0 = K_NUM_0 # Keyboard.NUM_1 = K_NUM_1 # Keyboard.NUM_2 = K_NUM_2 # Keyboard.NUM_3 = K_NUM_3 # Keyboard.NUM_4 = K_NUM_4 # Keyboard.NUM_5 = K_NUM_5 # Keyboard.NUM_6 = K_NUM_6 # Keyboard.NUM_7 = K_NUM_7 # Keyboard.NUM_8 = K_NUM_8 # Keyboard.NUM_9 = K_NUM_9 # Function keys Keyboard.F1 = K_F1 Keyboard.F2 = K_F2 Keyboard.F3 = K_F3 Keyboard.F4 = K_F4 Keyboard.F5 = K_F5 Keyboard.F6 = K_F6 Keyboard.F7 = K_F7 Keyboard.F8 = K_F8 Keyboard.F9 = K_F9 Keyboard.F10 = K_F10 Keyboard.F11 = K_F11 Keyboard.F12 = K_F12 Keyboard.F13 = K_F13 Keyboard.F14 = K_F14 Keyboard.F15 = K_F15 # Keyboard.F16 = K_F16 # Keyboard.F17 = K_F17 # Keyboard.F18 = K_F18 # Keyboard.F19 = K_F19 # Keyboard.F20 = K_F20 # Modifiers Keyboard.LSHIFT = K_LSHIFT Keyboard.RSHIFT = K_RSHIFT Keyboard.LCTRL = K_LCTRL Keyboard.RCTRL = K_RCTRL Keyboard.CAPSLOCK = K_CAPSLOCK Keyboard.LMETA = K_LMETA Keyboard.RMETA = K_RMETA Keyboard.LALT = K_LALT Keyboard.RALT = K_RALT # Keyboard.LWINDOWS = K_LWINDOWS # Keyboard.RWINDOWS = K_RWINDOWS # Keyboard.LCOMMAND = K_LCOMMAND # Keyboard.RCOMMAND = K_RCOMMAND # Keyboard.LOPTION = K_LOPTION # Keyboard.ROPTION = K_ROPTION # Latin-1 Keyboard.SPACE = K_SPACE # Keyboard.EXCLAMATION = K_EXCLAMATION # Keyboard.DOUBLEQUOTE = K_DOUBLEQUOTE Keyboard.HASH = K_HASH # Keyboard.POUND = K_POUND Keyboard.DOLLAR = K_DOLLAR # Keyboard.PERCENT = K_PERCENT Keyboard.AMPERSAND = K_AMPERSAND # Keyboard.APOSTROPHE = K_APOSTROPHE Keyboard.PARENLEFT = K_LEFTPAREN Keyboard.PARENRIGHT = K_RIGHTPAREN Keyboard.ASTERISK = K_ASTERISK Keyboard.PLUS = K_PLUS Keyboard.COMMA = K_COMMA Keyboard.MINUS = K_MINUS Keyboard.PERIOD = K_PERIOD Keyboard.SLASH = K_SLASH Keyboard.BACKQUOTE = K_BACKQUOTE Keyboard._0 = K_0 Keyboard._1 = K_1 Keyboard._2 = K_2 Keyboard._3 = K_3 Keyboard._4 = K_4 Keyboard._5 = K_5 Keyboard._6 = K_6 Keyboard._7 = K_7 Keyboard._8 = K_8 Keyboard._9 = K_9 Keyboard.COLON = K_COLON Keyboard.SEMICOLON = K_SEMICOLON Keyboard.LESS = K_LESS Keyboard.EQUAL = K_EQUALS Keyboard.GREATER = K_GREATER Keyboard.QUESTION = K_QUESTION Keyboard.AT = K_AT Keyboard.BRACKETLEFT = K_LEFTBRACKET Keyboard.BACKSLASH = K_BACKSLASH Keyboard.BRACKETRIGHT = K_RIGHTBRACKET # Keyboard.ASCIICIRCUM = K_ASCIICIRCUM Keyboard.UNDERSCORE = K_UNDERSCORE # Keyboard.GRAVE = K_GRAVE Keyboard.QUOTELEFT = K_QUOTE Keyboard.A = K_a Keyboard.B = K_b Keyboard.C = K_c Keyboard.D = K_d Keyboard.E = K_e Keyboard.F = K_f Keyboard.G = K_g Keyboard.H = K_h Keyboard.I = K_i Keyboard.J = K_j Keyboard.K = K_k Keyboard.L = K_l Keyboard.M = K_m Keyboard.N = K_n Keyboard.O = K_o Keyboard.P = K_p Keyboard.Q = K_q Keyboard.R = K_r Keyboard.S = K_s Keyboard.T = K_t Keyboard.U = K_u Keyboard.V = K_v Keyboard.W = K_w Keyboard.X = K_x Keyboard.Y = K_y Keyboard.Z = K_z # Keyboard.BRACELEFT = K_LEFTBRACE # Keyboard.BAR = K_BAR # Keyboard.BRACERIGHT = K_BRACERIGHT # Keyboard.ASCIITILDE = K_ASCIITILDEC for symbol in Keyboard.__dict__: self.key_pressed[Keyboard.__dict__[symbol]] = False self.valid = True
def DistanceField(font_size, image_width, image_height, image_mode, image_data): # GL setting glFrontFace(GL_CCW) glEnable(GL_TEXTURE_2D) glDisable(GL_DEPTH_TEST) glDisable(GL_CULL_FACE) glDisable(GL_LIGHTING) glDisable(GL_BLEND) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) # Create Shader vertex_shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertex_shader, SIMPLE_VERTEX_SHADER) glCompileShader(vertex_shader) if glGetShaderiv(vertex_shader, GL_COMPILE_STATUS) != 1 or True: infoLogs = glGetShaderInfoLog(vertex_shader) if infoLogs: if type(infoLogs) == bytes: infoLogs = infoLogs.decode("utf-8") print(infoLogs) fragment_shader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragment_shader, SIMPLE_PIXEL_SHADER) glCompileShader(fragment_shader) if glGetShaderiv(fragment_shader, GL_COMPILE_STATUS) != 1 or True: infoLogs = glGetShaderInfoLog(fragment_shader) if infoLogs: if type(infoLogs) == bytes: infoLogs = infoLogs.decode("utf-8") print(infoLogs) # Create Program program = glCreateProgram() # Link Shaders glAttachShader(program, vertex_shader) glAttachShader(program, fragment_shader) glLinkProgram(program) # delete shader glDetachShader(program, vertex_shader) glDetachShader(program, fragment_shader) glDeleteShader(vertex_shader) glDeleteShader(fragment_shader) # Vertex Array Data dtype = np.float32 positions = np.array([(-1, 1, 0), (-1, -1, 0), (1, -1, 0), (1, 1, 0)], dtype=np.float32) texcoords = np.array([(0, 1), (0, 0), (1, 0), (1, 1)], dtype=np.float32) indices = np.array([0, 1, 2, 0, 2, 3], dtype=np.uint32) # data serialize vertex_datas = np.hstack([positions, texcoords]).astype(dtype) # crate vertex array vertex_array = glGenVertexArrays(1) glBindVertexArray(vertex_array) vertex_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) glBufferData(GL_ARRAY_BUFFER, vertex_datas, GL_STATIC_DRAW) index_buffer_size = indices.nbytes index_buffer = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer) glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, indices, GL_STATIC_DRAW) # Create Texture texture_format = GL_RGBA if image_mode == 'RGB': texture_format = GL_RGB texture_buffer = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture_buffer) glTexImage2D(GL_TEXTURE_2D, 0, texture_format, image_width, image_height, 0, texture_format, GL_UNSIGNED_BYTE, image_data) glGenerateMipmap(GL_TEXTURE_2D) 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_LINEAR_MIPMAP_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glBindTexture(GL_TEXTURE_2D, 0) # Create RenderTarget render_target_buffer = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, render_target_buffer) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL_POINTER) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glBindTexture(GL_TEXTURE_2D, 0) # Create FrameBuffer frame_buffer = glGenFramebuffers(1) gl_error = glCheckFramebufferStatus(GL_FRAMEBUFFER) if gl_error != GL_FRAMEBUFFER_COMPLETE: logger.error("glCheckFramebufferStatus error %d." % gl_error) # Bind Frame Buffer glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_target_buffer, 0) glReadBuffer(GL_COLOR_ATTACHMENT0) glDrawBuffers(1, [ GL_COLOR_ATTACHMENT0, ]) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0) glViewport(0, 0, image_width, image_height) glClearColor(1.0, 1.0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT) # bind program glUseProgram(program) font_size_location = glGetUniformLocation(program, "font_size") glUniform1f(font_size_location, font_size) # bind texture texture_location = glGetUniformLocation(program, "texture_font") glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, texture_buffer) glUniform1i(texture_location, 0) # Bind Vertex Array glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer) vertex_position_size = positions[0].nbytes vertex_texcoord_size = texcoords[0].nbytes vertex_buffer_size = vertex_position_size + vertex_texcoord_size location = 0 offset = 0 stride = len(positions[0]) glEnableVertexAttribArray(location) glVertexAttribPointer(location, stride, GL_FLOAT, GL_FALSE, vertex_buffer_size, c_void_p(offset)) location = 1 offset += vertex_position_size stride = len(texcoords[0]) glEnableVertexAttribArray(1) glVertexAttribPointer(location, stride, GL_FLOAT, GL_FALSE, vertex_buffer_size, c_void_p(offset)) # bind index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer) # Draw Quad glDrawElements(GL_TRIANGLES, index_buffer_size, GL_UNSIGNED_INT, NULL_POINTER) # Save glBindTexture(GL_TEXTURE_2D, render_target_buffer) save_image_data = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE) glBindTexture(GL_TEXTURE_2D, 0) return save_image_data