1 2 module dglsl.program; 3 4 import std.string; 5 6 import derelict.opengl3.gl3; 7 import gl3n.linalg : Vector, Matrix; 8 9 import dglsl.gspl; 10 import dglsl.shader; 11 12 13 class Program(T...) { 14 private GLuint _programid; 15 @property auto id() const { return _programid; } 16 17 mixin(shader_uniform!T); 18 19 this(T shaders) { 20 _programid = glCreateProgram(); 21 22 foreach (s; shaders) { 23 glAttachShader(_programid, s.id); 24 } 25 26 glLinkProgram(_programid); 27 28 GLint linked; 29 glGetProgramiv(_programid, GL_LINK_STATUS, &linked); 30 31 if (linked == GL_FALSE) { 32 throw new Exception(infoLog(this)); 33 } 34 35 setUniformLocations(); 36 } 37 } 38 39 /* 40 ** プログラムの情報を表示する 41 ** from: http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090827 42 */ 43 string infoLog(T...)(Program!T p) 44 { 45 GLsizei bufSize; 46 47 /* シェーダのリンク時のログの長さを取得する */ 48 glGetProgramiv(p.id, GL_INFO_LOG_LENGTH , &bufSize); 49 50 if (bufSize == 0) return ""; 51 52 GLchar[] infoLog = new GLchar[](bufSize); 53 GLsizei length; 54 55 /* シェーダのリンク時のログの内容を取得する */ 56 glGetProgramInfoLog(p.id, bufSize, &length, infoLog.ptr); 57 return format("InfoLog:\n%s\n", infoLog); 58 } 59 60 auto makeProgram(T...)(T shaders) { 61 return new Program!T(shaders); 62 } 63 64 import std.typecons; 65 66 Tuple!(string, string)[] shader_uniform_list(T: ShaderBase)() { 67 import std.traits; 68 Tuple!(string, string)[] lst; 69 foreach (immutable s; __traits(derivedMembers, T)) { 70 static if (!hasUDA!(__traits(getMember, T, s), ignore) && hasUDA!(__traits(getMember, T, s), uniform)) { 71 immutable type = typeof(__traits(getMember, T, s)).stringof; 72 lst ~= Tuple!(string, string)(s, (type.startsWith("Sampler")) ? "int" : type); 73 } 74 } 75 return lst; 76 } 77 78 Tuple!(string, string)[] shader_uniform_list(T...)() if (T.length > 1) { 79 import std.algorithm; 80 auto ls = shader_uniform_list!(T[0]); 81 auto ls2 = shader_uniform_list!(T[1 .. $]); 82 83 foreach (s; ls) { 84 if (!ls2.canFind(s)) ls2 ~= s; 85 } 86 87 return ls2; 88 } 89 90 91 string shader_uniform(T...)() { 92 import std.algorithm; 93 string result = ""; 94 auto lst = shader_uniform_list!T; 95 96 foreach (sym; lst) { 97 result ~= "GLint %sLoc;\n".format(sym[0]); 98 result ~= "@property void %s(%s v) { glUniform(%sLoc, v); }\n".format(sym[0], sym[1], sym[0]); 99 } 100 101 auto locs = lst 102 .map!(sym => "\t%sLoc = glGetUniformLocation(_programid, `%s`.toStringz);".format(sym[0], sym[0])) 103 .join("\n"); 104 105 result ~= "void setUniformLocations() {\n" ~ locs ~ "\n}\n"; 106 107 return result; 108 }