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