def __init__(self, *shaders: Shader): self.name = gl.glCreateProgram() for shader in shaders: gl.glAttachShader(self.name, shader.name) gl.glLinkProgram(self.name) success = gl.GLint(0) gl.glGetProgramiv(self.name, gl.GL_LINK_STATUS, byref(success)) if not success: log_length = gl.GLint(0) gl.glGetProgramiv(self.name, gl.GL_INFO_LOG_LENGTH, byref(log_length)) log_buffer = create_string_buffer(log_length.value) gl.glGetProgramInfoLog(self.name, log_length.value, None, log_buffer) self.logger.error("Error linking program %s, error # %d", self.name, success.value) self.logger.error("---Message---") for line in log_buffer.value.decode("ascii").splitlines(): self.logger.error("Program: " + line) self.logger.error("------") raise RuntimeError("Linking program failed.") # free resources for shader in shaders: gl.glDeleteShader(shader.name)
def compileShader(source, shaderType): """Compile shader source of given type (only needed by compileProgram)""" shader = gl.glCreateShaderObjectARB(shaderType) #were we given a source string or a ShaderCode object? if hasattr(source, 'src'): source = source.src prog = c_char_p(source) length = c_int(-1) gl.glShaderSourceARB(shader, 1, cast(byref(prog), POINTER(POINTER(c_char))), byref(length)) gl.glCompileShaderARB(shader) #check for errors status = c_int() gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(status)) if not status.value: # retrieve the log length gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(status)) # create a buffer for the log buffer = create_string_buffer(status.value) #from ctypes # retrieve the log text gl.glGetProgramInfoLog(shader, status, None, buffer) # print the log to the console print buffer.value gl.glDeleteShader(shader) raise ValueError, 'Shader compilation failed' return shader
def compileShader( source, shaderType ): """Compile shader source of given type (only needed by compileProgram)""" shader = gl.glCreateShaderObjectARB(shaderType) #were we given a source string or a ShaderCode object? if hasattr(source, 'src'): source = source.src prog = c_char_p(source) length = c_int(-1) gl.glShaderSourceARB(shader, 1, cast(byref(prog), POINTER(POINTER(c_char))), byref(length)) gl.glCompileShaderARB(shader) #check for errors status = c_int() gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(status)) if not status.value: # retrieve the log length gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(status)) # create a buffer for the log buffer = create_string_buffer(status.value)#from ctypes # retrieve the log text gl.glGetProgramInfoLog(shader, status, None, buffer) # print the log to the console print buffer.value gl.glDeleteShader(shader) raise ValueError, 'Shader compilation failed' return shader
def __init__(self, source, shader_type): self.__value = None type_dict = {"vert": gl.GL_VERTEX_SHADER, "geom": gl.GL_GEOMETRY_SHADER, "frag": gl.GL_FRAGMENT_SHADER} # create and compile shader shader = gl.glCreateShader(type_dict[shader_type]) source_ptr = ct.c_char_p(source) source_ptr_ptr = ct.cast(ct.pointer(source_ptr), ct.POINTER(ct.POINTER(ct.c_char))) gl.glShaderSource(shader, 1, source_ptr_ptr, None) gl.glCompileShader(shader) # check for error err_status = ct.c_int() gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, ct.byref(err_status)) if err_status.value != gl.GL_TRUE: # error occurred log_length = ct.c_int() gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, ct.byref(log_length)) log_buffer = (ct.c_char * log_length.value)() log_buffer_ptr = ct.cast(ct.pointer(log_buffer), ct.c_char_p) gl.glGetShaderInfoLog(shader, log_length.value, None, log_buffer_ptr) gl.glDeleteShader(shader) raise gl.GLException("Shader failed to compile: \n%s" % log_buffer.value) else: self.__value = shader
def compile_and_attach_shader(self, shader_files, shader_type): """ Parameters ---------- :shader_files: a list of shader files. :shader_type: `GL_VERTEX_SHADER` or `GL_FRAGMENT_SHADER`. Main steps to compile and attach a shader: 1. glCreateShader: create a shader of given type. 2. glShaderSource: load source code into the shader. 3. glCompileShader: compile the shader. 4. glGetShaderiv: retrieve the compiling status. 5. glGetShaderInfoLog: print the error info if compiling failed. 6. glAttachShader: attach the shader to our program if compiling succeeded. """ src = [] for src_f in shader_files: with open(src_f, "r") as f: src.append(f.read().encode("ascii")) # 1. create a shader shader = gl.glCreateShader(shader_type) # 2. load source code into the shader src_p = (ct.c_char_p * len(src))(*src) gl.glShaderSource( shader, len(src), ct.cast(ct.pointer(src_p), ct.POINTER(ct.POINTER(ct.c_char))), None, ) # 3. compile the shader gl.glCompileShader(shader) # 4. retrieve the compiling status compile_status = gl.GLint(0) gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, ct.byref(compile_status)) # 5. if compiling failed then print the error log if not compile_status: info_length = gl.GLint(0) gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, ct.byref(info_length)) error_info = ct.create_string_buffer(info_length.value) gl.glGetShaderInfoLog(shader, info_length, None, error_info) print(error_info.value.decode("ascii")) # 6. else attach the shader to our program else: gl.glAttachShader(self.program, shader) gl.glDeleteShader(shader)
def _create_device_objects(self): # save state last_texture = gl.GLint() gl.glGetIntegerv(gl.GL_TEXTURE_BINDING_2D, byref(last_texture)) last_array_buffer = gl.GLint() gl.glGetIntegerv(gl.GL_ARRAY_BUFFER_BINDING, byref(last_array_buffer)) last_vertex_array = gl.GLint() gl.glGetIntegerv(gl.GL_VERTEX_ARRAY_BINDING, byref(last_vertex_array)) self._shader_handle = gl.glCreateProgram() # note: no need to store shader parts handles after linking vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER) fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) gl.glShaderSource(vertex_shader, 1, make_string_buffer(self.VERTEX_SHADER_SRC), None) gl.glShaderSource(fragment_shader, 1, make_string_buffer(self.FRAGMENT_SHADER_SRC), None) gl.glCompileShader(vertex_shader) gl.glCompileShader(fragment_shader) gl.glAttachShader(self._shader_handle, vertex_shader) gl.glAttachShader(self._shader_handle, fragment_shader) gl.glLinkProgram(self._shader_handle) # note: after linking shaders can be removed gl.glDeleteShader(vertex_shader) gl.glDeleteShader(fragment_shader) self._attrib_location_tex = gl.glGetUniformLocation(self._shader_handle, create_string_buffer(b"Texture")) self._attrib_proj_mtx = gl.glGetUniformLocation(self._shader_handle, create_string_buffer(b"ProjMtx")) self._attrib_location_position = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"Position")) self._attrib_location_uv = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"UV")) self._attrib_location_color = gl.glGetAttribLocation(self._shader_handle, create_string_buffer(b"Color")) self._vbo_handle = gl.GLuint() gl.glGenBuffers(1, byref(self._vbo_handle)) self._elements_handle = gl.GLuint() gl.glGenBuffers(1, byref(self._elements_handle)) self._vao_handle = gl.GLuint() gl.glGenVertexArrays(1, byref(self._vao_handle)) gl.glBindVertexArray(self._vao_handle) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._vbo_handle) gl.glEnableVertexAttribArray(self._attrib_location_position) gl.glEnableVertexAttribArray(self._attrib_location_uv) gl.glEnableVertexAttribArray(self._attrib_location_color) gl.glVertexAttribPointer(self._attrib_location_position, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_POS_OFFSET)) gl.glVertexAttribPointer(self._attrib_location_uv, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_UV_OFFSET)) gl.glVertexAttribPointer(self._attrib_location_color, 4, gl.GL_UNSIGNED_BYTE, gl.GL_TRUE, imgui.VERTEX_SIZE, c_void_p(imgui.VERTEX_BUFFER_COL_OFFSET)) # restore state gl.glBindTexture(gl.GL_TEXTURE_2D, cast((c_int*1)(last_texture), POINTER(c_uint)).contents) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, cast((c_int*1)(last_array_buffer), POINTER(c_uint)).contents) gl.glBindVertexArray(cast((c_int*1)(last_vertex_array), POINTER(c_uint)).contents)
def __init__(self, *shaders: Shader): self.prog_id = prog_id = gl.glCreateProgram() shaders_id = [] for shader_code, shader_type in shaders: shader = compile_shader(shader_code, shader_type) gl.glAttachShader(self.prog_id, shader) shaders_id.append(shader) gl.glLinkProgram(self.prog_id) for shader in shaders_id: # Flag shaders for deletion. Will only be deleted once detached from program. gl.glDeleteShader(shader) self._uniforms: Dict[str, Uniform] = {} self._introspect_uniforms() weakref.finalize(self, Program._delete, shaders_id, prog_id)
def test_freeing(self): " Test if the shaders are freed correctly" vert_obj = ShaderObject.vertex() # Warning, borrowed_obj do not own the underlying shader so it will not be freed automatically borrowed_obj = ShaderObject(glCreateShader(GL_VERTEX_SHADER), owned=False) borrowed_sid = borrowed_obj.sid sid = vert_obj.sid del vert_obj del borrowed_obj gc.collect() self.assertEqual(GL_FALSE, glIsShader(sid), 'shader object is still valid') self.assertEqual(GL_TRUE, glIsShader(borrowed_sid), 'shader object was deleted') #Free the shader object glDeleteShader(borrowed_sid)
def compileShader(source, shaderType): """Compile shader source of given type (only needed by compileProgram)""" shader = GL.glCreateShaderObjectARB(shaderType) prog = c_char_p(source) length = c_int(-1) GL.glShaderSourceARB(shader, 1, cast(byref(prog), POINTER(POINTER(c_char))), byref(length)) GL.glCompileShaderARB(shader) #check for errors status = c_int() GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS, byref(status)) if not status.value: print_log(shader) GL.glDeleteShader(shader) raise ValueError, 'Shader compilation failed' return shader
def compileShader( source, shaderType ): """Compile shader source of given type (only needed by compileProgram)""" shader = GL.glCreateShaderObjectARB(shaderType) prog = c_char_p(source) length = c_int(-1) GL.glShaderSourceARB(shader, 1, cast(byref(prog), POINTER(POINTER(c_char))), byref(length)) GL.glCompileShaderARB(shader) #check for errors status = c_int() GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS, byref(status)) if not status.value: print_log(shader) GL.glDeleteShader(shader) raise ValueError, 'Shader compilation failed' return shader
def __init__(self, vert_path, frag_path): self.program = gl.glCreateProgram() # create vertex shader self.vert_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER) create_shader(self.vert_shader, vert_path) gl.glAttachShader(self.program, self.vert_shader) # create fragment shader self.frag_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) create_shader(self.frag_shader, frag_path) gl.glAttachShader(self.program, self.frag_shader) # link program and clean up gl.glLinkProgram(self.program) gl.glDeleteShader(self.vert_shader) gl.glDeleteShader(self.frag_shader)
def compileShader(source, shaderType): """Compile shader source of given type (only needed by compileProgram) """ shader = GL.glCreateShaderObjectARB(shaderType) # if Py3 then we need to convert our (unicode) str into bytes for C if type(source) != bytes: source = source.encode() prog = c_char_p(source) length = c_int(-1) GL.glShaderSourceARB(shader, 1, cast(byref(prog), POINTER(POINTER(c_char))), byref(length)) GL.glCompileShaderARB(shader) # check for errors status = c_int() GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS, byref(status)) if not status.value: GL.glDeleteShader(shader) raise ValueError('Shader compilation failed') return shader
def _compile_shader(vs_src, fs_src): vs = gl.glCreateShader(gl.GL_VERTEX_SHADER) vs_src_buf = c.create_string_buffer(vs_src) c_vs_src = c.cast(c.pointer(vs_src_buf), c.POINTER(c.c_char)) i = c.c_int32(len(vs_src)) gl.glShaderSource(vs, 1, c_vs_src, c.byref(i)) gl.glCompileShader(vs) fs = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) fs_src_buf = c.create_string_buffer(fs_src) c_fs_src = c.cast(c.pointer(fs_src_buf), c.POINTER(c.c_char)) i = c.c_int32(len(fs_src)) gl.glShaderSource(fs, 1, c_fs_src, c.byref(i)) gl.glCompileShader(fs) program = gl.glCreateProgram() gl.glAttachShader(program, vs) gl.glAttachShader(program, fs) gl.glLinkProgram(program) gl.glDeleteShader(vs) gl.glDeleteShader(fs) return program
def __del__(self): if self.owned and self.valid(): glDeleteShader(self.sid)
def __init__( self, ctx: "Context", *, vertex_shader: str, fragment_shader: str = None, geometry_shader: str = None, tess_control_shader: str = None, tess_evaluation_shader: str = None, out_attributes: List[str] = None, ): """Create a Program. :param Context ctx: The context this program belongs to :param str vertex_shader: vertex shader source :param str fragment_shader: fragment shader source :param str geometry_shader: geometry shader source :param str tess_control_shader: tessellation control shader source :param str tess_evaluation_shader: tessellation evaluation shader source :param List[str] out_attributes: List of out attributes used in transform feedback. """ self._ctx = ctx self._glo = glo = gl.glCreateProgram() self._out_attributes = out_attributes or [] self._geometry_info = (0, 0, 0) self._attributes = [] # type: List[AttribFormat] #: Internal cache key used with vertex arrays self.attribute_key = "INVALID" # type: str self._uniforms: Dict[str, Uniform] = {} shaders = [(vertex_shader, gl.GL_VERTEX_SHADER)] if fragment_shader: shaders.append((fragment_shader, gl.GL_FRAGMENT_SHADER)) if geometry_shader: shaders.append((geometry_shader, gl.GL_GEOMETRY_SHADER)) if tess_control_shader: shaders.append((tess_control_shader, gl.GL_TESS_CONTROL_SHADER)) if tess_evaluation_shader: shaders.append( (tess_evaluation_shader, gl.GL_TESS_EVALUATION_SHADER)) shaders_id = [] for shader_code, shader_type in shaders: shader = Program.compile_shader(shader_code, shader_type) gl.glAttachShader(self._glo, shader) shaders_id.append(shader) # For now we assume varyings can be set up if no fragment shader if not fragment_shader: self._setup_out_attributes() Program.link(self._glo) if geometry_shader: geometry_in = gl.GLint() geometry_out = gl.GLint() geometry_vertices = gl.GLint() gl.glGetProgramiv(self._glo, gl.GL_GEOMETRY_INPUT_TYPE, geometry_in) gl.glGetProgramiv(self._glo, gl.GL_GEOMETRY_OUTPUT_TYPE, geometry_out) gl.glGetProgramiv(self._glo, gl.GL_GEOMETRY_VERTICES_OUT, geometry_vertices) self._geometry_info = ( geometry_in.value, geometry_out.value, geometry_vertices.value, ) # Flag shaders for deletion. Will only be deleted once detached from program. for shader in shaders_id: gl.glDeleteShader(shader) # Handle uniforms self._introspect_attributes() self._introspect_uniforms() self._introspect_uniform_blocks() self.ctx.stats.incr("program") weakref.finalize(self, Program._delete, self.ctx, shaders_id, glo)
def delete(self): """Delete the current shader.""" gl.glDeleteProgram(self._pid) gl.glDeleteShader(self._fid) gl.glDeleteShader(self._vid)
def __del__(self): gl.glDeleteShader(self.gl_id)
def __del__(self): if self.__value is not None: gl.glDeleteShader(self.__value)