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