1 module gfm.opengl.shader; 2 3 import std..string, 4 std.conv; 5 6 import derelict.opengl3.gl3; 7 8 import gfm.core.log, 9 gfm.core.text, 10 gfm.opengl.opengl; 11 12 13 /// OpenGL Shader wrapper. 14 final class GLShader 15 { 16 public 17 { 18 /// Creates a shader devoid of source code. 19 /// Throws: $(D OpenGLException) on error. 20 this(OpenGL gl, GLenum shaderType) 21 { 22 _gl = gl; 23 _shader = glCreateShader(shaderType); 24 if (_shader == 0) 25 throw new OpenGLException("glCreateShader failed"); 26 _initialized = true; 27 } 28 29 /// Creates a shader with source code and compiles it. 30 /// Throws: $(D OpenGLException) on error. 31 this(OpenGL gl, GLenum shaderType, string[] lines) 32 { 33 this(gl, shaderType); 34 load(lines); 35 compile(); 36 } 37 38 ~this() 39 { 40 close(); 41 } 42 43 /// Releases the OpenGL shader resource. 44 void close() 45 { 46 if (_initialized) 47 { 48 glDeleteShader(_shader); 49 _initialized = false; 50 } 51 } 52 53 /// Load source code for this shader. 54 /// Throws: $(D OpenGLException) on error. 55 void load(string[] lines) 56 { 57 size_t lineCount = lines.length; 58 59 auto lengths = new GLint[lineCount]; 60 auto addresses = new immutable(GLchar)*[lineCount]; 61 auto localLines = new string[lineCount]; 62 63 for (size_t i = 0; i < lineCount; ++i) 64 { 65 localLines[i] = lines[i] ~ "\n"; 66 lengths[i] = cast(GLint)(localLines[i].length); 67 addresses[i] = localLines[i].ptr; 68 } 69 70 glShaderSource(_shader, 71 cast(GLint)lineCount, 72 cast(const(char)**)addresses.ptr, 73 cast(const(int)*)(lengths.ptr)); 74 _gl.runtimeCheck(); 75 } 76 77 /// Compile this OpenGL shader. 78 /// Throws: $(D OpenGLException) on compilation error. 79 void compile() 80 { 81 glCompileShader(_shader); 82 _gl.runtimeCheck(); 83 84 // print info log 85 string infoLog = getInfoLog(); 86 if (infoLog != null) 87 _gl._logger.info(infoLog); 88 89 GLint compiled; 90 glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled); 91 92 if (compiled != GL_TRUE) 93 throw new OpenGLException("shader did not compile"); 94 } 95 96 /// Gets the compiling report. 97 /// Returns: Log output of the GLSL compiler. Can return null! 98 /// Throws: $(D OpenGLException) on error. 99 string getInfoLog() 100 { 101 GLint logLength; 102 glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &logLength); 103 if (logLength <= 0) // "If shader has no information log, a value of 0 is returned." 104 return null; 105 106 char[] log = new char[logLength]; 107 GLint dummy; 108 glGetShaderInfoLog(_shader, logLength, &dummy, log.ptr); 109 _gl.runtimeCheck(); 110 return sanitizeUTF8(log.ptr); 111 } 112 } 113 114 package 115 { 116 GLuint _shader; 117 } 118 119 private 120 { 121 OpenGL _gl; 122 bool _initialized; 123 } 124 } 125 126