1 /* 2 Copyright © 2020, Inochi2D Project 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: Luna Nielsen 6 */ 7 module inochi2d.core.shader; 8 import inochi2d.math; 9 import std.string; 10 import bindbc.opengl; 11 12 /** 13 A shader 14 */ 15 class Shader { 16 private: 17 GLuint shaderProgram; 18 GLuint fragShader; 19 GLuint vertShader; 20 21 void compileShaders(string vertex, string fragment) { 22 23 // Compile vertex shader 24 vertShader = glCreateShader(GL_VERTEX_SHADER); 25 auto c_vert = vertex.toStringz; 26 glShaderSource(vertShader, 1, &c_vert, null); 27 glCompileShader(vertShader); 28 verifyShader(vertShader); 29 30 // Compile fragment shader 31 fragShader = glCreateShader(GL_FRAGMENT_SHADER); 32 auto c_frag = fragment.toStringz; 33 glShaderSource(fragShader, 1, &c_frag, null); 34 glCompileShader(fragShader); 35 verifyShader(fragShader); 36 37 // Attach and link them 38 shaderProgram = glCreateProgram(); 39 glAttachShader(shaderProgram, vertShader); 40 glAttachShader(shaderProgram, fragShader); 41 glLinkProgram(shaderProgram); 42 verifyProgram(); 43 } 44 45 void verifyShader(GLuint shader) { 46 47 int compileStatus; 48 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); 49 if (compileStatus == GL_FALSE) { 50 51 // Get the length of the error log 52 GLint logLength; 53 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); 54 if (logLength > 0) { 55 56 // Fetch the error log 57 char[] log = new char[logLength]; 58 glGetShaderInfoLog(shader, logLength, null, log.ptr); 59 60 throw new Exception(cast(string)log); 61 } 62 } 63 } 64 65 void verifyProgram() { 66 67 int linkStatus; 68 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkStatus); 69 if (linkStatus == GL_FALSE) { 70 71 // Get the length of the error log 72 GLint logLength; 73 glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &logLength); 74 if (logLength > 0) { 75 76 // Fetch the error log 77 char[] log = new char[logLength]; 78 glGetProgramInfoLog(shaderProgram, logLength, null, log.ptr); 79 80 throw new Exception(cast(string)log); 81 } 82 } 83 } 84 85 public: 86 87 /** 88 Destructor 89 */ 90 ~this() { 91 glDetachShader(shaderProgram, vertShader); 92 glDetachShader(shaderProgram, fragShader); 93 glDeleteProgram(shaderProgram); 94 95 glDeleteShader(fragShader); 96 glDeleteShader(vertShader); 97 } 98 99 /** 100 Creates a new shader object from source 101 */ 102 this(string vertex, string fragment) { 103 compileShaders(vertex, fragment); 104 } 105 106 /** 107 Use the shader 108 */ 109 void use() { 110 glUseProgram(shaderProgram); 111 } 112 113 GLint getUniformLocation(string name) { 114 return glGetUniformLocation(shaderProgram, name.ptr); 115 } 116 117 void setUniform(GLint uniform, bool value) { 118 glUniform1i(uniform, cast(int)value); 119 } 120 121 void setUniform(GLint uniform, int value) { 122 glUniform1i(uniform, value); 123 } 124 125 void setUniform(GLint uniform, float value) { 126 glUniform1f(uniform, value); 127 } 128 129 void setUniform(GLint uniform, vec2 value) { 130 glUniform2f(uniform, value.x, value.y); 131 } 132 133 void setUniform(GLint uniform, vec3 value) { 134 glUniform3f(uniform, value.x, value.y, value.z); 135 } 136 137 void setUniform(GLint uniform, vec4 value) { 138 glUniform4f(uniform, value.x, value.y, value.z, value.w); 139 } 140 141 void setUniform(GLint uniform, mat4 value) { 142 glUniformMatrix4fv(uniform, 1, GL_TRUE, value.ptr); 143 } 144 }