1 module gfmod.opengl.shader; 2 3 import std..string, 4 std.exception, 5 std.conv; 6 7 import derelict.opengl3.gl3; 8 9 import gfmod.core.text, 10 gfmod.opengl.opengl; 11 12 /// OpenGL Shader wrapper. 13 struct GLShader 14 { 15 public: 16 @disable this(); 17 18 /// Creates a shader with source code and compiles it. 19 /// Throws: $(D OpenGLException) on error. 20 this(OpenGL gl, GLenum shaderType, string[] lines) @trusted 21 { 22 _gl = gl; 23 _shader = glCreateShader(shaderType); 24 if(_shader == 0) { throw new OpenGLException("glCreateShader failed"); } 25 26 load(lines); 27 if(!compile()) { throw new OpenGLException("Shader failed to compile"); } 28 } 29 30 private: 31 /// Load source code for this shader. 32 void load(string[] lines) nothrow 33 { 34 size_t lineCount = lines.length; 35 36 auto lengths = new GLint[lineCount]; 37 auto addresses = new immutable(GLchar)*[lineCount]; 38 auto localLines = new string[lineCount]; 39 40 foreach(i; 0 .. lineCount) 41 { 42 localLines[i] = lines[i] ~ "\n"; 43 lengths[i] = cast(GLint)(localLines[i].length); 44 addresses[i] = localLines[i].ptr; 45 } 46 47 glShaderSource(_shader, cast(GLint)lineCount, cast(const(char)**)addresses.ptr, 48 lengths.ptr); 49 } 50 51 /// Compile this OpenGL shader. 52 /// 53 /// Returns: true on success, false on failure. 54 bool compile() nothrow 55 { 56 glCompileShader(_shader); 57 _gl.runtimeCheck(); 58 59 // print info log 60 char[4096] logBuffer; 61 string infoLog = getInfoLog(logBuffer[]); 62 if(infoLog != null) { _gl._logger.info(infoLog).assumeWontThrow; } 63 64 GLint compiled; 65 glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled); 66 67 return compiled == GL_TRUE ? true : false; 68 } 69 70 71 /// Gets the compiling report. 72 /// Returns: Log output of the GLSL compiler. Can return null! 73 string getInfoLog(char[] logBuffer) nothrow const @nogc 74 { 75 GLint length; 76 glGetShaderInfoLog(_shader, cast(int)logBuffer.length, &length, logBuffer.ptr); 77 char[] log = logBuffer[0 .. length]; 78 log.sanitizeASCIIInPlace(); 79 return log.assumeUnique(); 80 } 81 82 package: 83 // Handle to the GL shader. 84 GLuint _shader; 85 86 private: 87 // OpenGL info, logging, etc. 88 OpenGL _gl; 89 }