1 /** 2 Copyright: Copyright (c) 2013-2017 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module anchovy.shaderprogram; 8 9 import std.exception; 10 import std.stdio; 11 import std..string; 12 import std.variant; 13 import derelict.opengl3.gl3; 14 import anchovy.glerrors; 15 16 final class ShaderProgram 17 { 18 bool isInited; 19 GLuint handle = 0; 20 string errorLog; 21 22 this(in string vertShaderSource, in string fragShaderSource) 23 { 24 handle = checkgl!glCreateProgram(); 25 attachShader(GL_VERTEX_SHADER, vertShaderSource); 26 attachShader(GL_FRAGMENT_SHADER, fragShaderSource); 27 isInited = true; 28 } 29 30 void close() 31 { 32 if (isInited) { 33 checkgl!glDeleteProgram(handle); 34 isInited = false; 35 } 36 } 37 38 void bind() 39 { 40 checkgl!glUseProgram(handle); 41 } 42 43 static void unbind() 44 { 45 checkgl!glUseProgram(0); 46 } 47 48 void attachShader(in GLenum shaderType, in string shaderSource) 49 { 50 GLuint shader = checkgl!glCreateShader(shaderType); 51 52 const char* fileData = toStringz(shaderSource); 53 checkgl!glShaderSource(shader, 1, &fileData, null); 54 checkgl!glCompileShader(shader); 55 56 int status; 57 checkgl!glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 58 if (status == GL_FALSE) 59 { 60 int length; 61 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); 62 63 char[] error = new char[length]; 64 checkgl!glGetShaderInfoLog(shader, length, null, cast(char*)error); 65 66 string shaderTypeString; 67 switch(shaderType) 68 { 69 case GL_VERTEX_SHADER: shaderTypeString = "vertex"; break; 70 case GL_GEOMETRY_SHADER: shaderTypeString = "geometry"; break; 71 case GL_FRAGMENT_SHADER: shaderTypeString = "fragment"; break; 72 default: break; 73 } 74 75 errorLog ~= "Compile failure in " ~ shaderTypeString ~ " shader:\n" ~ error~"\n"; 76 } 77 checkgl!glAttachShader(handle, shader); 78 } 79 80 // if ( !myShaderProgram.compile() ) 81 // writeln( myShaderProgram.errorLog ); 82 bool compile() 83 { 84 checkgl!glLinkProgram(handle); 85 86 GLint linkStatus; 87 checkgl!glGetProgramiv(handle, GL_LINK_STATUS, &linkStatus); 88 89 scope(exit) // Detach all shaders after compilation 90 { 91 GLuint[3] shaders; 92 GLsizei count; 93 94 checkgl!glGetAttachedShaders(handle, cast(int)shaders.length, &count, cast(uint*)shaders); 95 96 for( uint i=0; i<count; ++i ) 97 { 98 checkgl!glDetachShader(handle, shaders[i]); 99 checkgl!glDeleteShader(shaders[i]); 100 } 101 } 102 103 if ( linkStatus == GL_FALSE ) 104 { 105 GLint infoLogLength; 106 checkgl!glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &infoLogLength); 107 108 char[] strInfoLog = new char[infoLogLength]; 109 checkgl!glGetProgramInfoLog(handle, infoLogLength, null, cast(char*)strInfoLog); 110 errorLog ~= "Linker failure: " ~ strInfoLog ~ "\n"; 111 112 return false; 113 } 114 return true; 115 } 116 }