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, ec, fill_color, line_color, line_width, line_loop): self._ec = ec self._line_width = line_width self._line_loop = line_loop # whether or not lines drawn are looped # initialize program and shaders from pyglet import gl self._program = gl.glCreateProgram() vertex = gl.glCreateShader(gl.GL_VERTEX_SHADER) buf = create_string_buffer(tri_vert.encode('ASCII')) ptr = cast(pointer(pointer(buf)), POINTER(POINTER(c_char))) gl.glShaderSource(vertex, 1, ptr, None) gl.glCompileShader(vertex) _check_log(vertex, gl.glGetShaderInfoLog) fragment = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) buf = create_string_buffer(tri_frag.encode('ASCII')) ptr = cast(pointer(pointer(buf)), POINTER(POINTER(c_char))) gl.glShaderSource(fragment, 1, ptr, None) gl.glCompileShader(fragment) _check_log(fragment, gl.glGetShaderInfoLog) gl.glAttachShader(self._program, vertex) gl.glAttachShader(self._program, fragment) gl.glLinkProgram(self._program) _check_log(self._program, gl.glGetProgramInfoLog) gl.glDetachShader(self._program, vertex) gl.glDetachShader(self._program, fragment) gl.glUseProgram(self._program) # Prepare buffers and bind attributes loc = gl.glGetUniformLocation(self._program, b'u_view') view = ec.window_size_pix view = np.diag([2. / view[0], 2. / view[1], 1., 1.]) view[-1, :2] = -1 view = view.astype(np.float32).ravel() gl.glUniformMatrix4fv(loc, 1, False, (c_float * 16)(*view)) self._counts = dict() self._colors = dict() self._buffers = dict() self._points = dict() self._tris = dict() for kind in ('line', 'fill'): self._counts[kind] = 0 self._colors[kind] = (0., 0., 0., 0.) self._buffers[kind] = dict(array=gl.GLuint()) gl.glGenBuffers(1, pointer(self._buffers[kind]['array'])) self._buffers['fill']['index'] = gl.GLuint() gl.glGenBuffers(1, pointer(self._buffers['fill']['index'])) gl.glUseProgram(0) self.set_fill_color(fill_color) self.set_line_color(line_color)
def compile_shader(source: str, shader_type: gl.GLenum) -> gl.GLuint: """Compile the shader code of the given type. `shader_type` could be GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, ... Returns the shader id as a GLuint """ shader = gl.glCreateShader(shader_type) source_bytes = source.encode('utf-8') # Turn the source code string into an array of c_char_p arrays. strings = byref(cast(c_char_p(source_bytes), POINTER(c_char))) # Make an array with the strings lengths lengths = pointer(c_int(len(source_bytes))) gl.glShaderSource(shader, 1, strings, lengths) gl.glCompileShader(shader) result = c_int() gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(result)) if result.value == gl.GL_FALSE: msg = create_string_buffer(512) length = c_int() gl.glGetShaderInfoLog(shader, 512, byref(length), msg) raise ShaderException( f"Shader compile failure ({result.value}): {msg.value.decode('utf-8')}" ) return shader
def shader(stype, src): ''' create and compile a shader of type stype with source code src return the shader (the return value of glCreateShader) ''' handle = gl.glCreateShader(stype) buffer = ctypes.create_string_buffer(src) buf_pointer = ctypes.cast(ctypes.pointer(ctypes.pointer(buffer)), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))) length = ctypes.c_int(len(src) + 1) gl.glShaderSource(handle, 1, buf_pointer, ctypes.byref(length)) gl.glCompileShader(handle) success = gl.GLint(0) gl.glGetShaderiv(handle, gl.GL_COMPILE_STATUS, ctypes.pointer(success)) length = gl.GLint(0) gl.glGetShaderiv(handle, gl.GL_INFO_LOG_LENGTH, ctypes.pointer(length)) buffer = ctypes.create_string_buffer(length.value) gl.glGetShaderInfoLog(handle, length, None, buffer) log = buffer.value[:length.value].decode('ascii') for line in log.splitlines(): logging.debug('GLSL: ' + line) if not success: raise Exception('Compiling of the shader failed.') return handle
def compile_shader(source: str, shader_type: gl.GLenum) -> gl.GLuint: """Compile the shader code of the given type. `shader_type` could be GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, ... Returns the shader id as a GLuint """ shader = gl.glCreateShader(shader_type) source_bytes = source.encode("utf-8") # Turn the source code string into an array of c_char_p arrays. strings = byref(cast(c_char_p(source_bytes), POINTER(c_char))) # Make an array with the strings lengths lengths = pointer(c_int(len(source_bytes))) gl.glShaderSource(shader, 1, strings, lengths) gl.glCompileShader(shader) result = c_int() gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(result)) if result.value == gl.GL_FALSE: msg = create_string_buffer(512) length = c_int() gl.glGetShaderInfoLog(shader, 512, byref(length), msg) raise ShaderException( (f"Error compiling {SHADER_TYPE_NAMES[shader_type]} " f"({result.value}): {msg.value.decode('utf-8')}\n" f"---- [{SHADER_TYPE_NAMES[shader_type]}] ---\n") + "\n".join(f"{str(i+1).zfill(3)}: {line} " for i, line in enumerate(source.split("\n")))) return shader
def createShader(self, strings, shadertype): # create the shader handle shader = gl.glCreateShader(shadertype) # convert the source strings into a ctypes pointer-to-char array, and upload them # this is deep, dark, dangerous black magick - don't try stuff like this at home! strings = tuple(s.encode('ascii') for s in strings) # Nick added, for python3 src = (c_char_p * len(strings))(*strings) gl.glShaderSource(shader, len(strings), cast(pointer(src), POINTER(POINTER(c_char))), None) # compile the shader gl.glCompileShader(shader) # retrieve the compile status compile_success = c_int(0) gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(compile_success)) # if compilation failed, print the log if compile_success: gl.glAttachShader(self.id, shader) else: gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(compile_success)) # retrieve the log length buffer = create_string_buffer(compile_success.value) # create a buffer for the log gl.glGetShaderInfoLog(shader, compile_success, None, buffer) # retrieve the log text print(buffer.value) # print the log to the console
def __init__(self, shader_type, source): if shader_type not in GLShader.shader_type_name: raise ValueError self._shader_type = shader_type self._source = source super().__init__(gl.glCreateShader(shader_type)) if isinstance(source, str): source = source.encode() if not isinstance(source, bytes): raise TypeError c_source = ctypes.create_string_buffer(source) c_source = ctypes.cast( ctypes.pointer(ctypes.pointer(c_source)), ctypes.POINTER(ctypes.POINTER(gl.GLchar)), ) gl.glShaderSource(self.gl_id, 1, c_source, None) gl.glCompileShader(self.gl_id) rc = gl.GLint(0) gl.glGetShaderiv(self.gl_id, gl.GL_COMPILE_STATUS, ctypes.byref(rc)) if not rc: gl.glGetShaderiv(self.gl_id, gl.GL_INFO_LOG_LENGTH, ctypes.byref(rc)) buffer = ctypes.create_string_buffer(rc.value) gl.glGetShaderInfoLog(self.gl_id, rc, None, buffer) raise GLObjectException("{}\n{}".format( GLShader.shader_type_name[shader_type], buffer.value.decode()))
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 createShader(self, strings, type): count = len(strings) #If no code if count < 1: return shader = gl.glCreateShader(type) # ctypes magic: convert python [strings] to C (char**). src = (c_char_p * count)(*strings) gl.glShaderSource(shader, count, cast(pointer(src), POINTER(POINTER(c_char))), None) gl.glCompileShader(shader) # Retrieve the compile status status = c_int(0) gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(status)) # If compilation failed, get log and abort. if not status: gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(status)) log = create_string_buffer(status.value) gl.glGetShaderInfoLog(shader, status, None, log) raise Exception("Compiling shaders failed: {0}".format(log.value)) else: # If all is well, attach the shader to the program gl.glAttachShader(self.handle, shader)
def __init__(self, shader_type, *, source=None, path=None): """ Creates a shader object from either a source string or a text file at path. Args: shader_type: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER. source: String of the code to use for the shader. path: Path to a text file containing the code for the shader. """ assert source is not None or path is not None, "The source or a path to the source is missing." if path: source = open(path).read() handle = -1 try: handle = glCreateShader(shader_type) glShaderSource(handle, 1, c_string_array(source, count=1), None) glCompileShader(handle) except GLException: debug_shader(handle) super(Shader, self).__init__(handle) self.shader_type = shader_type self.source = source self.path = path if CHECK_ERROR: debug_shader(self)
def compile_shader(shader_type, shader_source): ''' Compile a shader and print error messages. ''' shader_name = gl.glCreateShader(shader_type) src_buffer = ctypes.create_string_buffer(shader_source) buf_pointer = ctypes.cast(ctypes.pointer(ctypes.pointer(src_buffer)), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))) length = ctypes.c_int(len(shader_source) + 1) gl.glShaderSource(shader_name, 1, buf_pointer, ctypes.byref(length)) gl.glCompileShader(shader_name) # test if compilation is succesful and print status messages success = gl.GLint(0) gl.glGetShaderiv(shader_name, gl.GL_COMPILE_STATUS, ctypes.byref(success)) length = gl.GLint(0) gl.glGetShaderiv(shader_name, gl.GL_INFO_LOG_LENGTH, ctypes.byref(length)) log_buffer = ctypes.create_string_buffer(length.value) gl.glGetShaderInfoLog(shader_name, length, None, log_buffer) log_message = log_buffer.value[:length.value].decode('ascii').strip() if log_message: sys.stderr.write(log_message + '\n') if not success: raise ValueError('Compiling of the shader failed.') return shader_name
def compile_shader(shader_type, shader_source): ''' Compile a shader and print error messages. ''' shader_name = gl.glCreateShader(shader_type) src_buffer = ctypes.create_string_buffer(shader_source) buf_pointer = ctypes.cast(ctypes.pointer(ctypes.pointer(src_buffer)), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))) length = ctypes.c_int(len(shader_source) + 1) gl.glShaderSource(shader_name, 1, buf_pointer, ctypes.byref(length)) gl.glCompileShader(shader_name) # test if compilation is succesful and print status messages success = gl.GLint(0) gl.glGetShaderiv(shader_name, gl.GL_COMPILE_STATUS, ctypes.byref(success)) length = gl.GLint(0) gl.glGetShaderiv(shader_name, gl.GL_INFO_LOG_LENGTH, ctypes.byref(length)) log_buffer = ctypes.create_string_buffer(length.value) gl.glGetShaderInfoLog(shader_name, length, None, log_buffer) for line in log_buffer.value[:length.value].decode('ascii').splitlines(): print('GLSL: ' + line) assert success, 'Compiling of the shader failed.' return shader_name
def createShader(self, strings, shadertype): # create the shader handle shader = gl.glCreateShader(shadertype) # convert the source strings into a ctypes pointer-to-char array, and upload them # this is deep, dark, dangerous black magick - don't try stuff like this at home! strings = tuple(s.encode('ascii') for s in strings) # Nick added, for python3 src = (c_char_p * len(strings))(*strings) gl.glShaderSource(shader, len(strings), cast(pointer(src), POINTER(POINTER(c_char))), None) # compile the shader gl.glCompileShader(shader) # retrieve the compile status compile_success = c_int(0) gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(compile_success)) # if compilation failed, print the log if compile_success: gl.glAttachShader(self.id, shader) else: gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(compile_success)) # retrieve the log length buffer = create_string_buffer( compile_success.value) # create a buffer for the log gl.glGetShaderInfoLog(shader, compile_success, None, buffer) # retrieve the log text print(buffer.value) # print the log to the console
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 compile(self): self.id = gl.glCreateShader(self.type) num, src = self._srcToArray() gl.glShaderSource(self.id, num, src, None) gl.glCompileShader(self.id) if not self.getCompileStatus(): il = self.getInfoLog() raise CompileError(il)
def shader(shader_type, src): assert(shader_type == gl.GL_VERTEX_SHADER or shader_type == gl.GL_FRAGMENT_SHADER) s = gl.glCreateShader(shader_type); srclen = c_int(len(src)) psrc = c_char_p(src) lpsrc = ctypes.cast(psrc, LP_c_char) gl.glShaderSource(s, 1, pointer(lpsrc), byref(srclen)) gl.glCompileShader(s) return check_shader_or_program_status(s)
def compile(self): self.id = gl.glCreateShader(self.type) num, src = self._srcToArray() gl.glShaderSource(self.id, num, src, None) gl.glCompileShader(self.id) if not self.getCompileStatus(): raise CompileError(self.getInfoLog())
def compile_and_attach_shader(self, source_strings, shader_type): ''' source_strings: a list of one or more strings that are possibly read from some files. shader_type: must be one of gl.GL_VERTEX_SHADER, gl.GL_FRAGMENT_SHADER, gl.GL_GEOMETRY_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 compile status 5. glGetShaderInfoLog: print the error info if compiling failed 6. glAttachShader: attach the shader to our program if compiling successed ''' # a preprocessing to make the code compatible with python3. src = tuple(s.encode('ascii') for s in source_strings) # 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 compile 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) # 6. else attach the shader to our program else: gl.glAttachShader(self.program, shader)
def __init__(self, source="", type='vertex'): """ Vertex, Fragment, or Geometry shader. Parameters ---------- source : string or list String or list of strings. The GLSL source code for the shader. type : {'vertex', 'fragment', 'geometry'} Type of shader. """ shader_type = {'vertex': gl.GL_VERTEX_SHADER, 'fragment': gl.GL_FRAGMENT_SHADER,} ## 'geometry': gl.GL_GEOMETRY_SHADER} if isinstance(source, basestring): source = [source] count = len(source) # if we have no source code, ignore this shader if count < 1: raise GLSLError("No GLSL source provided.") # create the shader handle shader = gl.glCreateShader(shader_type[type]) # convert the source strings into a ctypes pointer-to-char array, # and upload them. This is deep, dark, dangerous black magick - # don't try stuff like this at home! src = (c_char_p * count)(*source) gl.glShaderSource(shader, count, cast(pointer(src), POINTER(POINTER(c_char))), None) # compile the shader gl.glCompileShader(shader) temp = c_int(0) # retrieve the compile status gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, byref(temp)) # create a buffer for the log buffer = create_string_buffer(temp.value) # retrieve the log text gl.glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console raise GLSLError(buffer.value) self.handle = shader self.source = "\n".join(source)
def compile(self): self.id = gl.glCreateShader(self.shader_type) self.sources = self._load_sources() num, src = self._sources_to_array() gl.glShaderSource(self.id, num, src, None) gl.glCompileShader(self.id) if not self.get_compile_status(): raise CompileError(self.get_info_log())
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 test_valid(self): " Test if generated objects are valid" vert_obj = ShaderObject.vertex() frag_obj = ShaderObject.fragment() bad_obj = ShaderObject(8000, owned=True) borrowed_obj = ShaderObject(glCreateShader(GL_VERTEX_SHADER), owned=True) self.assertTrue(vert_obj.valid(), 'vertex shader is not valid') self.assertTrue(frag_obj.valid(), 'fragment shader is not valid') self.assertTrue(borrowed_obj.valid(), 'other vertex shader is not valid') self.assertFalse(bad_obj.valid(), 'bad shader is valid') self.assertTrue(vert_obj, 'vertex shader is not valid') self.assertFalse(bad_obj, 'bad shader is valid')
def compile_and_attach_shader(self, source_strings, shader_type): ''' source_strings: a list of one or more strings that are possibly read from some files. shader_type: must be one of gl.GL_VERTEX_SHADER, gl.GL_FRAGMENT_SHADER, gl.GL_GEOMETRY_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 compile status 5. glGetShaderInfoLog: print the error info if compiling failed 6. glAttachShader: attach the shader to our program if compiling successed ''' # a preprocessing to make the code compatible with python3. src = tuple(s.encode('ascii') for s in source_strings) # 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 compile 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) # 6. else attach the shader to our program else: gl.glAttachShader(self.program, 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 create_shader(self, source, shadertype): # get a char[] sbuffer = c.create_string_buffer(source) # get a char ** pointer = c.cast(c.pointer(c.pointer(sbuffer)), c.POINTER(c.POINTER(c.c_char))) # a long * NULL pointer nulll = c.POINTER(c.c_long)() shader = gl.glCreateShader(shadertype) gl.glShaderSource(shader, 1, pointer, None) gl.glCompileShader(shader) message = self.get_shader_log(shader) if message: raise ShaderException(message) return shader
def compile_and_attach_shader(self, shader_file, shader_type): """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 compile status. 5. glGetShaderInfoLog: print the error info if compiling failed. 6. glAttachShader: attach the shader to our program if compiling successed. """ with open(shader_file, 'r') as f: src = 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(src) gl.glShaderSource( shader, 1, ct.cast(ct.pointer(src_p), ct.POINTER(ct.POINTER(ct.c_char))), None) # 3. compile the shader gl.glCompileShader(shader) # 4. retrieve the compile 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) # 6. else attach the shader to our program else: gl.glAttachShader(self.program, shader)
def __init__(self, source): self.source = source self.shader_no = gl.glCreateShader(self.shader_type) if not self.shader_no: raise Exception("could not create shader") prog = (c_char_p * 1)(source + chr(0)) length = (c_int * 1)(0) gl.glShaderSource(self.shader_no, 1, cast(prog, POINTER(POINTER(c_char))), cast(0, POINTER(c_int))) gl.glCompileShader(self.shader_no) self.program_no = gl.glCreateProgram() if not self.program_no: raise Exception("could not create program") gl.glAttachShader(self.program_no, self.shader_no) gl.glLinkProgram(self.program_no)
def __init__(self, source_file: str = None, source: str = None): self.name = gl.glCreateShader(self.kind) if source_file: self.source = open(source_file, "rb").read() else: self.source = source src_buffer = create_string_buffer(self.source) buf_pointer = cast(pointer(pointer(src_buffer)), POINTER(POINTER(c_char))) gl.glShaderSource(self.name, 1, buf_pointer, None) gl.glCompileShader(self.name) success = gl.GLint(0) gl.glGetShaderiv(self.name, gl.GL_COMPILE_STATUS, byref(success)) if not success.value: self._log_error() raise RuntimeError('Compiling of the shader failed.')
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 compile_and_attach_shader(self, shader_file, shader_type): """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 compile status. 5. glGetShaderInfoLog: print the error info if compiling failed. 6. glAttachShader: attach the shader to our program if compiling successed. """ with open(shader_file, 'r') as f: src = 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(src) gl.glShaderSource(shader, 1, ct.cast(ct.pointer(src_p), ct.POINTER(ct.POINTER(ct.c_char))), None) # 3. compile the shader gl.glCompileShader(shader) # 4. retrieve the compile 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) # 6. else attach the shader to our program else: gl.glAttachShader(self.program, shader)
def compile_shader(type_, src): shader = gl.glCreateShader(type_) gl.glShaderSource( shader, 1, ctypes.cast( ctypes.pointer(ctypes.pointer(ctypes.create_string_buffer(src))), ctypes.POINTER(ctypes.POINTER(ctypes.c_char)), ), ctypes.byref(ctypes.c_int(len(src) + 1)), ) gl.glCompileShader(shader) status = ctypes.c_int(0) gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, ctypes.byref(status)) if not status.value: log = ctypes.create_string_buffer(4096) gl.glGetShaderInfoLog(shader, len(log), None, log) raise Exception('Error compiling shader: ' + log.value.decode('utf8')) return shader
def _compile(self, source, kind): """Compile a shader from its source code. :param source: Source code of the shader to be compiled. :type source: str :param kind: The kind of shader we are compiling. :type kind: int :returns: The shader id of the compiled shader. :rtype: int """ shader_id = gl.glCreateShader(kind) _src = ct.c_char_p(source.encode('utf-8')) src = ct.cast(ct.pointer(_src), ct.POINTER(ct.POINTER(ct.c_char))) gl.glShaderSource(shader_id, 1, src, None) gl.glCompileShader(shader_id) status_code = ct.c_int(0) status_code_pointer = ct.pointer(status_code) gl.glGetShaderiv(shader_id, gl.GL_COMPILE_STATUS, status_code_pointer) log_size = ct.c_int(0) log_size_pointer = ct.pointer(log_size) gl.glGetShaderiv(shader_id, gl.GL_INFO_LOG_LENGTH, log_size_pointer) log_message = ct.create_string_buffer(log_size.value) gl.glGetShaderInfoLog(shader_id, log_size, None, log_message) log_message = log_message.value.decode('utf-8') if len(log_message) > 0: print(source) print(log_message) # In Windows (OpenGL 3.3 + intel card) the log_message # is set to "No errors" on a successful compilation # and the code raises the Exception even though it # shouldn't. There should be a proper fix, but getting # rid of this line for now, will fix it. # # raise Exception(log_message) return shader_id
def shader(stype, src): handle = gl.glCreateShader(stype) buffer = ctypes.create_string_buffer(src) buf_pointer = ctypes.cast(ctypes.pointer(ctypes.pointer(buffer)), POINTER(POINTER(ctypes.c_char))) length = ctypes.c_int(len(src) + 1) gl.glShaderSource(handle, 1, buf_pointer, byref(length)) gl.glCompileShader(handle) success = gl.GLint(0) gl.glGetShaderiv(handle, gl.GL_COMPILE_STATUS, pointer(success)) length = gl.GLint(0) gl.glGetShaderiv(handle, gl.GL_INFO_LOG_LENGTH, pointer(length)) buffer = ctypes.create_string_buffer(length.value) gl.glGetShaderInfoLog(handle, length, None, buffer) log = buffer.value[:length.value].decode('ascii') for line in log.splitlines(): logging.debug('GLSL: ' + line) if not success: raise Exception('Compiling of the shader failed.') return handle
def create_shader(self, strings, shader_type): count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = glCreateShader(shader_type) shaderstrings = [] for string in strings: shaderstrings.append(bytes(string, 'ascii')) # convert the source strings into a ctypes pointer-to-char array, and # upload them this is deep, dark, dangerous black magic - don't try # stuff like this at home! src = (c_char_p * count)(*shaderstrings) glShaderSource(shader, count, cast( pointer(src), POINTER(POINTER(c_char))), None) # compile the shader glCompileShader(shader) temp = c_int(0) # retrieve the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(temp)) # create a buffer for the log buffer = create_string_buffer(temp.value) # retrieve the log text glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console print(buffer.value) else: # all is well, so attach the shader to the program glAttachShader(self.handle, shader)
def create_shader(self, strings, t): count = len(strings) # if we have no source code, ignore this shader if count <= 0: self.log.info("Source string was empty. Not doing anything") return shader = glCreateShader(t) string_buffers = [ create_string_buffer(bytes(s, "utf-8")) for s in strings ] src = (c_char_p * count)(*map(addressof, string_buffers)) glShaderSource(shader, count, cast(pointer(src), POINTER(POINTER(c_char))), None) glCompileShader(shader) if self.was_compile_successful(shader): glAttachShader(self.handle, shader) else: self.log.warn("Could not compile shader")
def createShader(self, strings, type): count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = GL.glCreateShader(type) # convert the source strings into a ctypes pointer-to-char array, # and upload them. This is deep, dark, dangerous black magick - # don't try stuff like this at home! """ Next line added """ strings = [s.encode("ascii") for s in strings] src = (ctypes.c_char_p * count)(*strings) GL.glShaderSource( shader, count, ctypes.cast(ctypes.pointer(src), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))), None) # compile the shader GL.glCompileShader(shader) temp = ctypes.c_int(0) # retrieve the compile status GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS, ctypes.byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length GL.glGetShaderiv(shader, GL.GL_INFO_LOG_LENGTH, ctypes.byref(temp)) # create a buffer for the log buffer = ctypes.create_string_buffer(temp.value) # retrieve the log text GL.glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console self.logError(buffer.value) else: # all is well, so attach the shader to the program GL.glAttachShader(self.handle, shader)
def load_shader(name, shader_type): """load_shader(name, shader_type) -> compiled shader Exits the program if the shader doesn't compile.""" # Check that the shader type specifier is correct if shader_type not in SHADER_TYPES: raise ValueError("%s is not a shader type specifier!" % shader_type) # Look for the shader file and when found -- read it's contents source, err = None, None for shader_dir in shader_path: filename = os.path.join(shader_dir, '%s.%s.glsl' % (name, shader_type)) try: with open(filename) as source_file: source = source_file.read() break except IOError as io_err: err = io_err if source is None and err is not None: raise err # Perform ctypes enchantments source_buf = c.create_string_buffer(source) c_source = c.cast(source_buf, c.POINTER(gl.GLchar)) # Create and compile the shader shader = gl.glCreateShader(SHADER_TYPES[shader_type]) gl.glShaderSource(shader, 1, c.pointer(c_source), None) gl.glCompileShader(shader) # If everything is ok -- return the shader check_shader(shader, filename) return shader
def _build_shader(self, strings, stype): ''' Actual building of the shader ''' count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = gl.glCreateShader(stype) # convert the source strings into a ctypes pointer-to-char array, and upload them # this is deep, dark, dangerous black magick - don't try stuff like this at home! src = (ctypes.c_char_p * count)(*strings) gl.glShaderSource(shader, count, ctypes.cast(ctypes.pointer(src), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))), None) # compile the shader gl.glCompileShader(shader) temp = ctypes.c_int(0) # retrieve the compile status gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, ctypes.byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length gl.glGetShaderiv(shader, gl.GL_INFO_LOG_LENGTH, ctypes.byref(temp)) # create a buffer for the log buffer = ctypes.create_string_buffer(temp.value) # retrieve the log text gl.glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console print buffer.value else: # all is well, so attach the shader to the program gl.glAttachShader(self.handle, shader)
def createShader(self, strings, type): count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = GL.glCreateShader(type) # convert the source strings into a ctypes pointer-to-char array, # and upload them. This is deep, dark, dangerous black magick - # don't try stuff like this at home! """ Next line added """ strings = [s.encode("ascii") for s in strings] src = (ctypes.c_char_p * count)(*strings) GL.glShaderSource(shader, count, ctypes.cast(ctypes.pointer(src), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))), None) # compile the shader GL.glCompileShader(shader) temp = ctypes.c_int(0) # retrieve the compile status GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS, ctypes.byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length GL.glGetShaderiv(shader, GL.GL_INFO_LOG_LENGTH, ctypes.byref(temp)) # create a buffer for the log buffer = ctypes.create_string_buffer(temp.value) # retrieve the log text GL.glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console self.logError(buffer.value) else: # all is well, so attach the shader to the program GL.glAttachShader(self.handle, shader);
def create_shader(self, strings, t): count = len(strings) # if we have no source code, ignore this shader if count < 1: return # create the shader handle shader = glCreateShader(t) # convert the source strings into a ctypes pointer-to-char array, and upload them string_buffers = [ self.process_and_convert_to_string_buffer(s) for s in strings] # noinspection PyTypeChecker, PyCallingNonCallable src = (c_char_p * count)(*map(addressof, string_buffers)) glShaderSource(shader, count, cast( pointer(src), POINTER(POINTER(c_char))), None) # compile the shader glCompileShader(shader) temp = c_int(0) # retrieve the compile status glGetShaderiv(shader, GL_COMPILE_STATUS, byref(temp)) # if compilation failed, print the log if not temp: # retrieve the log length glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(temp)) # create a buffer for the log buffer = create_string_buffer(temp.value) # retrieve the log text glGetShaderInfoLog(shader, temp, None, buffer) # print the log to the console self.log.error(f"{buffer.value}") else: # all is well, so attach the shader to the program glAttachShader(self.handle, shader)
def _shaderSource(text, shader_type=gl.GL_VERTEX_SHADER): buff = c.create_string_buffer(text) c_text = c.cast(c.pointer(c.pointer(buff)), c.POINTER(c.POINTER(gl.GLchar))) shader = gl.glCreateShader(shader_type) gl.glShaderSource(shader, 1, c_text, None) return shader
def __alloc(cls, shader_type): sobj = super().__new__(cls) sobj.sid = c_uint(glCreateShader(shader_type)) sobj.owned = True return sobj
def __init__(self, shaders, attributes, uniforms): vertex_shader = shaders[0] fragment_shader = shaders[1] vertex_handle = glCreateShader(GL_VERTEX_SHADER) glShaderSource( vertex_handle, 1, cast(pointer(pointer(create_string_buffer(vertex_shader))), POINTER(POINTER(GLchar))), None) glCompileShader(vertex_handle) fragment_handle = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource( fragment_handle, 1, cast(pointer(pointer(create_string_buffer(fragment_shader))), POINTER(POINTER(GLchar))), None) glCompileShader(fragment_handle) # Create attributes. attribute_mapping = [] for attribute in attributes: attribute_mapping.append(create_string_buffer(attribute)) try: # Create program. program_handle = glCreateProgram() glAttachShader(program_handle, vertex_handle) glAttachShader(program_handle, fragment_handle) for index, name in enumerate(attributes): # CHANGED glBindAttribLocation(program_handle, index, name) glLinkProgram(program_handle) glValidateProgram(program_handle) glUseProgram(program_handle) except GLException: # Print errors. status = GLint() glGetShaderiv(vertex_handle, GL_INFO_LOG_LENGTH, byref(status)) output = create_string_buffer(status.value) glGetShaderInfoLog(vertex_handle, status, None, output) print(output.value.decode('utf-8')) status = GLint() glGetShaderiv(fragment_handle, GL_INFO_LOG_LENGTH, byref(status)) output = create_string_buffer(status.value) glGetShaderInfoLog(fragment_handle, status, None, output) print(output.value.decode('utf-8')) status = GLint() glGetProgramiv(program_handle, GL_INFO_LOG_LENGTH, byref( status)) # Getting the number of char in info log to 'status' output = create_string_buffer(status.value) # status.value) glGetProgramInfoLog(program_handle, status, None, output) print(output.value.decode('utf-8')) # # Get uniform location. # uniform_mapping = {} # for uniform in uniforms: # name = create_string_buffer(uniform) # location = glGetUniformLocation(program_handle, cast(pointer(name), POINTER(GLchar))) # uniform_mapping[uniform] = location active_shaders = GLint() glGetProgramiv(program_handle, GL_ACTIVE_UNIFORMS, active_shaders) buffer_size = GLsizei(255) data_type = GLenum(0) string_buffer = create_string_buffer(buffer_size.value) name = c_char_p(addressof(string_buffer)) uniform_mapping = {} for index in range(active_shaders.value): glGetActiveUniform(program_handle, index, buffer_size, None, None, byref(data_type), name) if name.value in uniforms: location = glGetUniformLocation( program_handle, cast(pointer(name), POINTER(GLchar))) uniform = Uniform(name.value, location, data_type.value) uniform_mapping[name.value] = uniform super().__init__(program_handle) self.uniforms = uniform_mapping self.attributes = attribute_mapping