1 2 3 module glwt.program; 4 5 import std.conv : to; 6 7 import cst_ ; 8 9 import derelict.opengl ; 10 11 import glwt.shader; 12 13 14 15 16 17 18 19 20 /** A wrapper for a program.*/ 21 struct Program { 22 uint id = 0; 23 } 24 25 26 27 28 29 /** glCreateShader wrapper. 30 */ 31 void 32 create(ref Program program) 33 { 34 import std.stdio; 35 program.id = glCreateProgram(); 36 } 37 /** glDeleteProgram wrapper. 38 */ 39 void 40 del(ref Program program) 41 { 42 glDeleteProgram(program.id); 43 } 44 45 46 47 48 49 50 51 52 53 54 55 enum string program_ensureGen_m = "version(assert){assert(program.id!=0, \"Program not created. Call `program.create` before using this function.\");}"; 56 enum string program_ensureBound_m = program_ensureGen_m~"version(assert){ 57 uint bp;//bound program 58 glGetIntegerv(GL_CURRENT_PROGRAM, cast(int*)&bp); 59 assert(program.id==bp, \"Program not in use (bound). Call `program.use` before using this function.\"); 60 }"; 61 62 63 64 65 66 void checkError(T)(T id) { 67 import std.stdio; 68 auto glErr = glGetError(); 69 if (glErr != GL_NO_ERROR) { 70 id.writeln; 71 writeln(glErr); 72 if (glErr==GL_INVALID_VALUE ) {writeln("glErrGL_INVALID_VALUE" );} 73 if (glErr==GL_INVALID_OPERATION ) {writeln("glErrGL_INVALID_OPERATION" );} 74 if (glErr==GL_INVALID_FRAMEBUFFER_OPERATION ) {writeln("glErrGL_INVALID_FRAMEBUFFER_OPERATION" );} 75 if (glErr==GL_OUT_OF_MEMORY ) {writeln("glErrGL_OUT_OF_MEMORY" );} 76 ////if (glErr==GL_STACK_UNDERFLOW ) {writeln("glErrGL_STACK_UNDERFLOW ");} 77 ////if (glErr==GL_STACK_OVERFLOW ) {writeln("glErrGL_STACK_OVERFLOW ");} 78 } 79 } 80 81 82 83 /** glUseProgram wrapper. 84 Binds program to be used by future calls. 85 */ 86 void 87 use(Program program) 88 { 89 "a".checkError; 90 mixin(program_ensureGen_m); 91 "b".checkError; 92 glUseProgram(program.id); 93 "c".checkError; 94 uint bp;//bound program 95 glGetIntegerv(GL_CURRENT_PROGRAM, cast(int*)&bp); 96 "d".checkError; 97 } 98 /**ditto*/ 99 alias bind=use; 100 101 102 103 104 105 106 107 108 109 110 111 112 /** glAttachShader wrapper 113 */ 114 void 115 attach(ShaderType shaderType)(Program program, Shader!shaderType shader) 116 { 117 mixin(program_ensureGen_m); 118 mixin(shader_ensureGen_m); 119 glAttachShader(program.id, shader.id); 120 } 121 122 123 /** glLinkProgram wrapper 124 */ 125 void 126 link(Program program) 127 { 128 mixin(program_ensureGen_m); 129 glLinkProgram(program.id); 130 } 131 132 133 134 135 136 137 138 139 /** glGetAttribLocation wrapper 140 */ 141 int getAttribute(Program program, string name) { 142 mixin(program_ensureGen_m); 143 import std.string : toStringz; 144 return glGetAttribLocation(program.id, name.toStringz); 145 } 146 ///ditto 147 alias getAttributeLocation = getAttribute; 148 ///ditto 149 alias getAttribLocation = getAttribute; 150 /** glGetUniformLocation 151 */ 152 int getUniform(Program program, string name) { 153 mixin(program_ensureBound_m); 154 import std.string : toStringz; 155 return glGetUniformLocation(program.id, name.toStringz); 156 } 157 ///ditto 158 alias getUniformLocation = getUniform; 159 160 161 162 163 164 165 /** glUniform wrapper 166 */ 167 void uniform (Type) (Program program, int uniform, Type value ) if (mixin(constrainTypeWBool_m)) { mixin(program_ensureBound_m); mixin("glUniform1"~mixin(typeToLetterWBool_m)) (uniform, value); } 168 void uniformVector (Type, int size:1) (Program program, int uniform, Type[size] value ) if (mixin(constrainTypeWBool_m) && size>0) { mixin(program_ensureBound_m); mixin("glUniform"~size.to!string~mixin(typeToLetterWBool_m)) (uniform, value[0]); } 169 void uniformVector (Type, int size:2) (Program program, int uniform, Type[size] value ) if (mixin(constrainTypeWBool_m) && size>0) { mixin(program_ensureBound_m); mixin("glUniform"~size.to!string~mixin(typeToLetterWBool_m)) (uniform, value[0],value[1]); } 170 void uniformVector (Type, int size:3) (Program program, int uniform, Type[size] value ) if (mixin(constrainTypeWBool_m) && size>0) { mixin(program_ensureBound_m); mixin("glUniform"~size.to!string~mixin(typeToLetterWBool_m)) (uniform, value[0],value[1],value[2]); } 171 void uniformVector (Type, int size:4) (Program program, int uniform, Type[size] value ) if (mixin(constrainTypeWBool_m) && size>0) { mixin(program_ensureBound_m); mixin("glUniform"~size.to!string~mixin(typeToLetterWBool_m)) (uniform, value[0],value[1],value[2],value[3]); } 172 void uniformArray (Type, int size, int length) (Program program, int uniform, Type[size][length] value ) if (mixin(constrainTypeWOBool_m) && size>0&&size<=4 && length>0) { mixin(program_ensureBound_m); mixin("glUniform"~size.to!string~mixin(typeToLetterWOBool_m)~"v") (uniform, length, value.ptr.cst!(Type*)); } 173 void uniformMatrix (Type, int width, int height) (Program program, int uniform, Type[width][height] value, bool transpose=false ) if (mixin(constrainTypeWOBool_m) && width>1&&width<=4 && height>1&&height<=4) { static if (width==height) { 174 mixin(program_ensureBound_m); mixin("glUniformMatrix"~width.to!string~mixin(typeToLetterWOBool_m)~"v") (uniform, 1, transpose, value.ptr.cst!(Type*)); 175 } else { 176 mixin(program_ensureBound_m); mixin("glUniformMatrix"~width.to!string~"x"~height.to!string~mixin(typeToLetterWOBool_m)~"v") (uniform, 1, transpose, value.ptr.cst!(Type*)); 177 } 178 } 179 void uniformMatrices (int width, int height, int length, Type) (Program program, int uniform, Type[width][height][amount] value, bool transpose=false ) if (mixin(constrainTypeWOBool_m) && width>1&&width<=4 && height>1&&height<=4 && amount>0) { static if (width==height) { 180 mixin(program_ensureBound_m); mixin("glUniformMatrix"~width.to!string~mixin(typeToLetterWOBool_m)~"v") (uniform, length, transpose, value.ptr.cst!(Type*)); 181 } else { 182 mixin(program_ensureBound_m); mixin("glUniformMatrix"~width.to!string~"x"~height.to!string~mixin(typeToLetterWOBool_m)~"v") (uniform, length, transpose, value.ptr.cst!(Type*)); 183 } 184 } 185 186 alias setUniform = uniform ; 187 alias setUniformVector = uniformVector ; 188 alias setUniformArray = uniformArray ; 189 alias setUniformMatrix = uniformMatrix ; 190 alias setUniformMatrices = uniformMatrices ; 191 192 private enum string typeToLetterWBool_m = "((is(Type:int)||is(Type:bool))?\"i\":(is(Type:float)?\"f\":\"ui\"))"; 193 private enum string typeToLetterWOBool_m = "(is(Type:int)?\"i\":(is(Type:float)?\"f\":\"ui\"))"; 194 private enum string constrainTypeWBool_m = "(is(Type:int)||is(Type:float)||is(Type:uint)||is(Type:bool))"; 195 private enum string constrainTypeWOBool_m = "(is(Type:int)||is(Type:float)||is(Type:uint))"; 196 197 198 199 200 201