1 module unecht.gl.program; 2 3 import gl3n.linalg; 4 5 import derelict.opengl3.gl3; 6 7 import unecht.meta.misc; 8 import unecht.gl.shader; 9 10 /// 11 enum GLAtrribTypes 12 { 13 position, 14 normal, 15 color, 16 texcoord 17 } 18 19 /// 20 alias GLProgramAttribLocations = GLuint[EnumMemberCount!GLAtrribTypes]; 21 22 /// 23 final class GLProgram 24 { 25 GLuint program; 26 //TODO: use sorted array here: 27 GLint[string] uniforms; 28 private string _name; 29 30 GLProgramAttribLocations attribLocations; 31 32 void create(GLShader _vshader, GLShader _fshader, string _name="<unknown>") 33 { 34 this._name = _name; 35 36 program = glCreateProgram(); 37 38 glAttachShader(program, _vshader.shader); 39 glAttachShader(program, _fshader.shader); 40 41 glLinkProgram(program); 42 43 int success; 44 glGetProgramiv(program, GL_LINK_STATUS, &success); 45 if (success == 0) { 46 static GLchar[1024] logBuff; 47 static GLsizei logLen; 48 glGetProgramInfoLog(program, logBuff.sizeof, &logLen, logBuff.ptr); 49 import unecht.core.logger; 50 import std.conv; 51 log.errorf("Error: linking program: '%s': %s", _name, to!string(logBuff[0..logLen-1])); 52 return; 53 } 54 55 foreach(i, att; __traits(allMembers, GLAtrribTypes)) 56 { 57 import std.string:toStringz; 58 auto attrName = att.stringof[1..$-1]; 59 attribLocations[i] = glGetAttribLocation(program, toStringz(attrName)); 60 } 61 } 62 63 //TODO: 64 void destroy() 65 { 66 67 } 68 69 private GLint addUniform(string _name) 70 { 71 import unecht.core.logger:log; 72 import unecht.gl.vertexBufferObject:checkGLError; 73 import std.string:toStringz; 74 75 auto loc = glGetUniformLocation(program, toStringz(_name)); 76 77 checkGLError(); 78 79 if(loc != -1) 80 { 81 uniforms[_name] = loc; 82 log.infof("Program uniform location found: '%s' at %s", _name, loc); 83 return loc; 84 } 85 else 86 { 87 //TODO: implement a logging scheme 88 //writefln("Error: could not locate uniform: '%s' in '%s'", _name, this._name); 89 return -1; 90 } 91 } 92 93 /// 94 void setUniformVec3(string _name, in vec3 _val) 95 { 96 auto locPtr = _name in uniforms; 97 GLint loc; 98 99 if(!locPtr) 100 loc = addUniform(_name); 101 else 102 loc = *locPtr; 103 104 if(loc != -1) 105 glUniform3fv(loc, 1, _val.vector.ptr); 106 } 107 108 /// 109 void setUniformVec4(string _name, in vec4 _val) 110 { 111 auto locPtr = _name in uniforms; 112 GLint loc; 113 114 if(!locPtr) 115 loc = addUniform(_name); 116 else 117 loc = *locPtr; 118 119 if(loc != -1) 120 glUniform4fv(loc, 1, _val.vector.ptr); 121 } 122 123 /// 124 void setUniformMatrix(string _name, const ref mat4 _mat) 125 { 126 auto locPtr = _name in uniforms; 127 GLint loc; 128 129 if(!locPtr) 130 loc = addUniform(_name); 131 else 132 loc = *locPtr; 133 134 if(loc != -1) 135 glUniformMatrix4fv(loc, 1, GL_TRUE, _mat[0].ptr); 136 } 137 138 void bind() 139 { 140 glUseProgram(program); 141 } 142 143 void validate() 144 { 145 glValidateProgram(program); 146 147 GLint success; 148 glGetProgramiv(program, GL_VALIDATE_STATUS, &success); 149 if (!success) { 150 GLchar[1024] logBuff; 151 GLsizei logLen; 152 glGetProgramInfoLog(program, logBuff.sizeof, &logLen, logBuff.ptr); 153 import unecht.core.logger; 154 import std.conv; 155 log.errorf("Error validating program: '%s'", to!string(logBuff[0..logLen-1])); 156 } 157 } 158 159 void unbind() 160 { 161 glUseProgram(0); 162 } 163 }