├── .gitignore ├── README.md ├── dub.sdl └── source └── dglsl ├── gspl.d ├── package.d ├── program.d ├── sampler.d ├── shader.d ├── translator.d └── type.d /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | *.o 5 | *.obj 6 | *.a 7 | dub.selections.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dglsl 2 | 3 | **このライブラリはα版であり、ほとんどの機能が未実装です。** 4 | 5 | GLSL3.3のシェーダをD言語から使いやすくするためのライブラリです。 6 | 7 | ## インストール 8 | 9 | dub.jsonに以下のように書いてください。 10 | 11 | ```json 12 | ... 13 | "stringImportPaths": ["./"], 14 | "dependencies": { 15 | "dglsl": "~>0.6.0" 16 | } 17 | ... 18 | ``` 19 | 20 | `stringImportPaths`の指定を忘れないようにしてください。 21 | 22 | ## 使い方 23 | 24 | 次のようにクラスとしてシェーダプログラムを定義します。 25 | ```dlang 26 | import dglsl; 27 | 28 | class VertShader : Shader!Vertex { 29 | @layout(location = 0) 30 | @input vec3 position; 31 | 32 | @layout(location = 1) 33 | @input vec3 color; 34 | 35 | @output vec3 vertColor; 36 | 37 | @uniform mat4 projectionMatrix; 38 | 39 | void main() { 40 | vertColor = color; 41 | gl_Position = projectionMatrix * vec4(position, 1.0); 42 | } 43 | } 44 | 45 | class FragShader : Shader!Fragment { 46 | @input vec3 vertColor; 47 | @output vec3 fragColor; 48 | 49 | void main() { 50 | fragColor = vec3(vertColor); 51 | } 52 | } 53 | ``` 54 | 55 | 次に、シェーダをコンパイルしてプログラムを作成します。 56 | 57 | ```dlang 58 | auto shader = new VertShader(); 59 | shader.compile(); 60 | 61 | auto frag = new FragShader(); 62 | frag.compile(); 63 | 64 | auto p = makeProgram(shader, frag); 65 | glUseProgram(p.id); 66 | p.projectionMatrix = mat4.identity; 67 | ``` 68 | 69 | あとは標準のOpenGL3の機能を使って描画を行うことができます。 70 | -------------------------------------------------------------------------------- /dub.sdl: -------------------------------------------------------------------------------- 1 | name "dglsl" 2 | description "A GLSL bridge for D." 3 | copyright "Copyright © 2016, Taichi Tomioka" 4 | authors "Taichi Tomioka" 5 | license "MIT" 6 | 7 | targetName "D-GLSL" 8 | targetType "staticLibrary" 9 | 10 | dependency "gl3n" version="~>1.3.1" 11 | dependency "derelict-gl3" version="~>1.0.17" -------------------------------------------------------------------------------- /source/dglsl/gspl.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl.gspl; 3 | 4 | import derelict.opengl3.gl3; 5 | 6 | import std.string; 7 | 8 | import dglsl.type; 9 | 10 | /// glUniform 11 | void glUniform(GLint location, GLfloat v0) { 12 | glUniform1f(location, v0); 13 | } 14 | 15 | void glUniform(GLint location, GLfloat v0, GLfloat v1) { 16 | glUniform2f(location, v0, v1); 17 | } 18 | 19 | void glUniform(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { 20 | glUniform3f(location, v0, v1, v2); 21 | } 22 | 23 | void glUniform(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { 24 | glUniform4f(location, v0, v1, v2, v3); 25 | } 26 | 27 | void glUniform(GLint location, GLint v0) { 28 | glUniform1i(location, v0); 29 | } 30 | 31 | void glUniform(GLint location, GLint v0, GLint v1) { 32 | glUniform2i(location, v0, v1); 33 | } 34 | 35 | void glUniform(GLint location, GLint v0, GLint v1, GLint v2) { 36 | glUniform3i(location, v0, v1, v2); 37 | } 38 | 39 | void glUniform(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { 40 | glUniform4i(location, v0, v1, v2, v3); 41 | } 42 | 43 | void glUniform1v(GLint location, GLsizei count, const GLfloat[] value) { 44 | glUniform1fv(location, count, value.ptr); 45 | } 46 | 47 | void glUniform2v(GLint location, GLsizei count, const GLfloat[] value) { 48 | glUniform2fv(location, count, value.ptr); 49 | } 50 | 51 | void glUniform3v(GLint location, GLsizei count, const GLfloat[] value) { 52 | glUniform3fv(location, count, value.ptr); 53 | } 54 | 55 | void glUniform4v(GLint location, GLsizei count, const GLfloat[] value) { 56 | glUniform4fv(location, count, value.ptr); 57 | } 58 | 59 | void glUniform1v(GLint location, GLsizei count, const GLint[] value) { 60 | glUniform1iv(location, count, value.ptr); 61 | } 62 | 63 | void glUniform2v(GLint location, GLsizei count, const GLint[] value) { 64 | glUniform2iv(location, count, value.ptr); 65 | } 66 | 67 | void glUniform3v(GLint location, GLsizei count, const GLint[] value) { 68 | glUniform3iv(location, count, value.ptr); 69 | } 70 | 71 | void glUniform4v(GLint location, GLsizei count, const GLint[] value) { 72 | glUniform4iv(location, count, value.ptr); 73 | } 74 | 75 | void glUniformMatrix(GLint location, GLboolean transpose, const GLfloat[4] value) { 76 | glUniformMatrix2fv(location, 1, transpose, value.ptr); 77 | } 78 | 79 | void glUniformMatrix(GLint location, GLboolean transpose, const GLfloat[9] value) { 80 | glUniformMatrix3fv(location, 1, transpose, value.ptr); 81 | } 82 | 83 | void glUniformMatrix(GLint location, GLboolean transpose, const GLfloat[16] value) { 84 | glUniformMatrix4fv(location, 1, transpose, value.ptr); 85 | } 86 | 87 | void glUniform(int dim)(GLint location, Vector!(float, dim) v) { 88 | mixin(`glUniform%dfv(location, 1, v.value_ptr);`.format(dim)); 89 | } 90 | 91 | void glUniform(int dim)(GLint location, Matrix!(float, dim, dim) m, GLboolean transpose = false) { 92 | mixin(`glUniformMatrix%dfv(location, 1, transpose, m.value_ptr);`.format(dim)); 93 | } 94 | 95 | void glUniform(int column, int row)(GLint location, Matrix!(float, column, row) m, GLboolean transpose = false) if (column != row) { 96 | import std.string; 97 | mixin(`glUniformMatrix%dx%dfv(location, 1, transpose, m.value_ptr);`.format(column, row)); 98 | } 99 | 100 | 101 | enum GLErrorCode { 102 | noError = GL_NO_ERROR, 103 | invalidEnum = GL_INVALID_ENUM, 104 | invalidValue = GL_INVALID_VALUE, 105 | invalidOperation = GL_INVALID_OPERATION, 106 | invalidFramebufferOperation = GL_INVALID_FRAMEBUFFER_OPERATION, 107 | outOfMemory = GL_OUT_OF_MEMORY, 108 | } 109 | 110 | 111 | // glGetError 112 | void glCheckError(string file = __FILE__, int line = __LINE__) { 113 | debug final switch (cast(GLErrorCode)(glGetError())) { 114 | case GLErrorCode.noError: 115 | break; 116 | case GLErrorCode.invalidEnum: 117 | throw new Exception("Invalid enum error: An unacceptable value is specified for an enumerated argument.", file, line); 118 | case GLErrorCode.invalidValue: 119 | throw new Exception("Invalid value error: A numeric argument is out of range.", file, line); 120 | case GLErrorCode.invalidOperation: 121 | throw new Exception("Invalid operation error: The specified operation is not allowed in the current state.", file, line); 122 | case GLErrorCode.invalidFramebufferOperation: 123 | throw new Exception("Invalid framebuffer operation error: The framebuffer object is not complete.", file, line); 124 | case GLErrorCode.outOfMemory: 125 | throw new Exception("Out of memory error: There is not enough memory left to execute the command.", file, line); 126 | } 127 | } 128 | 129 | 130 | // opengl device information 131 | void glShowInfo() { 132 | import std.stdio; 133 | import std.conv; 134 | GLint i; 135 | 136 | writefln("Version: %s", glGetString(GL_VERSION).to!string); 137 | writefln("Vendor: %s", glGetString(GL_VENDOR).to!string); 138 | writefln("Renderer: %s", glGetString(GL_RENDERER).to!string); 139 | writefln("GLSL Version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION).to!string); 140 | 141 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i); 142 | writefln("Max texture size (RGBA32): %d * %d", i / 4, i / 4); 143 | 144 | stdout.flush(); 145 | } 146 | -------------------------------------------------------------------------------- /source/dglsl/package.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl; 3 | 4 | public import dglsl.type; 5 | public import dglsl.sampler; 6 | public import dglsl.translator; 7 | public import dglsl.shader; 8 | public import dglsl.program; 9 | -------------------------------------------------------------------------------- /source/dglsl/program.d: -------------------------------------------------------------------------------- 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 | } 109 | -------------------------------------------------------------------------------- /source/dglsl/sampler.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl.sampler; 3 | 4 | import dglsl.type; 5 | 6 | struct Sampler1D(Type) { alias type = Type; } 7 | struct Sampler2D(Type) { alias type = Type; } 8 | struct Sampler3D(Type) { alias type = Type; } 9 | struct SamplerCube(Type) { alias type = Type; } 10 | struct Sampler2DRect(Type) { alias type = Type; } 11 | struct Sampler1DShadow(Type) { alias type = Type; } 12 | struct Sampler2DShadow(Type) { alias type = Type; } 13 | struct SamplerCubeShadow(Type) { alias type = Type; } 14 | struct Sampler2DRectShadow(Type) { alias type = Type; } 15 | struct Sampler1DArray(Type) { alias type = Type; } 16 | struct Sampler2DArray(Type) { alias type = Type; } 17 | struct Sampler1DArrayShadow(Type) { alias type = Type; } 18 | struct Sampler2DArrayShadow(Type) { alias type = Type; } 19 | struct SamplerBuffer(Type) { alias type = Type; } 20 | struct Sampler2DMS(Type) { alias type = Type; } 21 | struct Sampler2DMSArray(Type) { alias type = Type; } 22 | 23 | alias sampler1D = Sampler1D!(float); 24 | alias sampler2D = Sampler2D!(float); 25 | alias sampler3D = Sampler3D!(float); 26 | alias samplerCube = SamplerCube!(float); 27 | alias sampler2DRect = Sampler2DRect!(float); 28 | alias sampler1DShadow = Sampler1DShadow!(float); 29 | alias sampler2DShadow = Sampler2DShadow!(float); 30 | alias samplerCubeShadow = SamplerCubeShadow!(float); 31 | alias sampler2DRectShadow = Sampler2DRectShadow!(float); 32 | alias sampler1DArray = Sampler1DArray!(float); 33 | alias sampler2DArray = Sampler2DArray!(float); 34 | alias sampler1DArrayShadow = Sampler1DArrayShadow!(float); 35 | alias sampler2DArrayShadow = Sampler2DArrayShadow!(float); 36 | alias samplerBuffer = SamplerBuffer!(float); 37 | alias sampler2DMS = Sampler2DMS!(float); 38 | alias sampler2DMSArray = Sampler2DMSArray!(float); 39 | 40 | alias isampler1D = Sampler1D!(int); 41 | alias isampler2D = Sampler2D!(int); 42 | alias isampler3D = Sampler3D!(int); 43 | alias isamplerCube = SamplerCube!(int); 44 | alias isampler2DRect = Sampler2DRect!(int); 45 | alias isampler1DArray = Sampler1DArray!(int); 46 | alias isampler2DArray = Sampler2DArray!(int); 47 | alias isamplerBuffer = SamplerBuffer!(int); 48 | alias isampler2DMS = Sampler2DMS!(int); 49 | alias isampler2DMSArray = Sampler2DMSArray!(int); 50 | 51 | alias usampler1D = Sampler1D!(uint); 52 | alias usampler2D = Sampler2D!(uint); 53 | alias usampler3D = Sampler3D!(uint); 54 | alias usamplerCube = SamplerCube!(uint); 55 | alias usampler2DRect = Sampler2DRect!(uint); 56 | alias usampler1DArray = Sampler1DArray!(uint); 57 | alias usampler2DArray = Sampler2DArray!(uint); 58 | alias usamplerBuffer = SamplerBuffer!(uint); 59 | alias usampler2DMS = Sampler2DMS!(uint); 60 | alias usampler2DMSArray = Sampler2DMSArray!(uint); 61 | 62 | import std.string; 63 | import std.algorithm; 64 | import std.array; 65 | string specialize(string source) { 66 | return source.lineSplitter 67 | .map!((l) { 68 | if (l.canFind('g')) return l.replace("g", "") ~ "\n" ~ l.replace("g", "i") ~ "\n" ~ l.replace("g", "u"); 69 | else return l.strip; 70 | }) 71 | .filter!(l => !l.empty) 72 | .join("\n") 73 | .lineSplitter 74 | .map!(l => l.chomp(";") ~ ` { throw new Error(__FUNCTION__ ~ "is not implemented."); }`) 75 | .join("\n"); 76 | } 77 | 78 | mixin template TextureLookupFunctions() { 79 | mixin(q{ 80 | int textureSize(gsampler1D sampler, int lod); 81 | ivec2 textureSize(gsampler2D sampler, int lod); 82 | ivec3 textureSize(gsampler3D sampler, int lod); 83 | ivec2 textureSize(gsamplerCube sampler, int lod); 84 | int textureSize(sampler1DShadow sampler, int lod); 85 | ivec2 textureSize(sampler2DShadow sampler, int lod); 86 | ivec2 textureSize(samplerCubeShadow sampler, int lod); 87 | ivec2 textureSize(gsampler2DRect sampler); 88 | ivec2 textureSize(sampler2DRectShadow sampler); 89 | ivec2 textureSize(gsampler1DArray sampler, int lod); 90 | ivec3 textureSize(gsampler2DArray sampler, int lod); 91 | ivec2 textureSize(sampler1DArrayShadow sampler, int lod); 92 | ivec3 textureSize(sampler2DArrayShadow sampler, int lod); 93 | int textureSize(gsamplerBuffer sampler); 94 | ivec2 textureSize(gsampler2DMS sampler); 95 | ivec2 textureSize(gsampler2DMSArray sampler); 96 | }.specialize); 97 | mixin(q{ 98 | gvec4 texture(gsampler1D sampler, float P, float bias = float.nan); 99 | gvec4 texture(gsampler2D sampler, vec2 P, float bias = float.nan); 100 | gvec4 texture(gsampler3D sampler, vec3 P, float bias = float.nan); 101 | gvec4 texture(gsamplerCube sampler, vec3 P, float bias = float.nan); 102 | float texture(sampler1DShadow sampler, vec3 P, float bias = float.nan); 103 | float texture(sampler2DShadow sampler, vec3 P, float bias = float.nan); 104 | float texture(samplerCubeShadow sampler, vec4 P, float bias = float.nan); 105 | gvec4 texture(gsampler1DArray sampler, vec2 P, float bias = float.nan); 106 | gvec4 texture(gsampler2DArray sampler, vec3 P, float bias = float.nan); 107 | float texture(sampler1DArrayShadow sampler, vec3 P, float bias = float.nan); 108 | float texture(sampler2DArrayShadow sampler, vec4 P); 109 | gvec4 texture(gsampler2DRect sampler, vec2 P); 110 | float texture(sampler2DRectShadow sampler, vec3 P); 111 | }.specialize); 112 | mixin(q{ 113 | gvec4 textureProj(gsampler1D sampler, vec2 P, float bias = float.nan); 114 | gvec4 textureProj(gsampler1D sampler, vec4 P, float bias = float.nan); 115 | gvec4 textureProj(gsampler2D sampler, vec3 P, float bias = float.nan); 116 | gvec4 textureProj(gsampler2D sampler, vec4 P, float bias = float.nan); 117 | gvec4 textureProj(gsampler3D sampler, vec4 P, float bias = float.nan); 118 | float textureProj(sampler1DShadow sampler, vec4 P, float bias = float.nan); 119 | float textureProj(sampler2DShadow sampler, vec4 P, float bias = float.nan); 120 | gvec4 textureProj(gsampler2DRect sampler, vec3 P); 121 | gvec4 textureProj(gsampler2DRect sampler, vec4 P); 122 | float textureProj(sampler2DRectShadow sampler, vec4 P); 123 | }.specialize); 124 | mixin(q{ 125 | gvec4 textureLod(gsampler1D sampler, float P, float lod); 126 | gvec4 textureLod(gsampler2D sampler, vec2 P, float lod); 127 | gvec4 textureLod(gsampler3D sampler, vec3 P, float lod); 128 | gvec4 textureLod(gsamplerCube sampler, vec3 P, float lod); 129 | float textureLod(sampler1DShadow sampler, vec3 P, float lod); 130 | float textureLod(sampler2DShadow sampler, vec3 P, float lod); 131 | gvec4 textureLod(gsampler1DArray sampler, vec2 P, float lod); 132 | gvec4 textureLod(gsampler2DArray sampler, vec3 P, float lod); 133 | float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod); 134 | }.specialize); 135 | mixin(q{ 136 | gvec4 textureOffset(gsampler1D sampler, float P, int offset, float bias = float.nan); 137 | gvec4 textureOffset(gsampler2D sampler, vec2 P, ivec2 offset, float bias = float.nan); 138 | gvec4 textureOffset(gsampler3D sampler, vec3 P, ivec3 offset, float bias = float.nan); 139 | gvec4 textureOffset(gsampler2DRect sampler, vec2 P, ivec2 offset); 140 | float textureOffset(sampler2DRectShadow sampler, vec3 P, ivec2 offset); 141 | float textureOffset(sampler1DShadow sampler, vec3 P, int offset, float bias = float.nan); 142 | float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset, float bias = float.nan); 143 | gvec4 textureOffset(gsampler1DArray sampler, vec2 P, int offset, float bias = float.nan); 144 | gvec4 textureOffset(gsampler2DArray sampler, vec3 P, ivec2 offset, float bias = float.nan); 145 | float textureOffset(sampler1DArrayShadow sampler, vec3 P, int offset, float bias = float.nan); 146 | }.specialize); 147 | mixin(q{ 148 | gvec4 texelFetch(gsampler1D sampler, int P, int lod); 149 | gvec4 texelFetch(gsampler2D sampler, ivec2 P, int lod); 150 | gvec4 texelFetch(gsampler3D sampler, ivec3 P, int lod); 151 | gvec4 texelFetch(gsampler2DRect sampler, ivec2 P); 152 | gvec4 texelFetch(gsampler1DArray sampler, ivec2 P, int lod); 153 | gvec4 texelFetch(gsampler2DArray sampler, ivec3 P, int lod); 154 | gvec4 texelFetch(gsamplerBuffer sampler, int P); 155 | gvec4 texelFetch(gsampler2DMS sampler, ivec2 P, int sample); 156 | gvec4 texelFetch(gsampler2DMSArray sampler, ivec3 P, int sample); 157 | }.specialize); 158 | mixin(q{ 159 | gvec4 texelFetchOffset(gsampler1D sampler, int P, int lod, int offset); 160 | gvec4 texelFetchOffset(gsampler2D sampler, ivec2 P, int lod, ivec2 offset); 161 | gvec4 texelFetchOffset(gsampler3D sampler, ivec3 P, int lod, ivec3 offset); 162 | gvec4 texelFetchOffset(gsampler2DRect sampler, ivec2 P, ivec2 offset); 163 | gvec4 texelFetchOffset(gsampler1DArray sampler, ivec2 P, int lod, int offset); 164 | gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod,ivec2 offset); 165 | }.specialize); 166 | mixin(q{ 167 | gvec4 textureProjOffset(gsampler1D sampler, vec2 P, int offset, float bias = float.nan); 168 | gvec4 textureProjOffset(gsampler1D sampler, vec4 P, int offset, float bias = float.nan); 169 | gvec4 textureProjOffset(gsampler2D sampler, vec3 P, ivec2 offset, float bias = float.nan); 170 | gvec4 textureProjOffset(gsampler2D sampler, vec4 P, ivec2 offset, float bias = float.nan); 171 | gvec4 textureProjOffset(gsampler3D sampler, vec4 P, ivec3 offset, float bias = float.nan); 172 | gvec4 textureProjOffset(gsampler2DRect sampler, vec3 P, ivec2 offset); 173 | gvec4 textureProjOffset(gsampler2DRect sampler, vec4 P, ivec2 offset); 174 | float textureProjOffset(sampler2DRectShadow sampler, vec4 P, ivec2 offset); 175 | float textureProjOffset(sampler1DShadow sampler, vec4 P, int offset, float bias = float.nan); 176 | float textureProjOffset(sampler2DShadow sampler, vec4 P, ivec2 offset, float bias = float.nan); 177 | }.specialize); 178 | mixin(q{ 179 | gvec4 textureLodOffset(gsampler1D sampler, float P, float lod, int offset); 180 | gvec4 textureLodOffset(gsampler2D sampler, vec2 P, float lod, ivec2 offset); 181 | gvec4 textureLodOffset(gsampler3D sampler, vec3 P, float lod, ivec3 offset); 182 | float textureLodOffset(sampler1DShadow sampler, vec3 P, float lod, int offset); 183 | float textureLodOffset(sampler2DShadow sampler, vec3 P, float lod, ivec2 offset); 184 | gvec4 textureLodOffset(gsampler1DArray sampler, vec2 P, float lod, int offset); 185 | gvec4 textureLodOffset(gsampler2DArray sampler, vec3 P, float lod, ivec2 offset); 186 | float textureLodOffset(sampler1DArrayShadow sampler, vec3 P, float lod, int offset); 187 | }.specialize); 188 | mixin(q{ 189 | gvec4 textureProjLod (gsampler1D sampler, vec2 P, float lod); 190 | gvec4 textureProjLod (gsampler1D sampler, vec4 P, float lod); 191 | gvec4 textureProjLod (gsampler2D sampler, vec3 P, float lod); 192 | gvec4 textureProjLod (gsampler2D sampler, vec4 P, float lod); 193 | gvec4 textureProjLod (gsampler3D sampler, vec4 P, float lod); 194 | float textureProjLod (sampler1DShadow sampler, vec4 P, float lod); 195 | float textureProjLod (sampler2DShadow sampler, vec4 P, float lod); 196 | }.specialize); 197 | mixin(q{ 198 | gvec4 textureProjLodOffset(gsampler1D sampler, vec2 P, float lod, int offset); 199 | gvec4 textureProjLodOffset(gsampler1D sampler, vec4 P, float lod, int offset); 200 | gvec4 textureProjLodOffset(gsampler2D sampler, vec3 P, float lod, ivec2 offset); 201 | gvec4 textureProjLodOffset(gsampler2D sampler, vec4 P, float lod, ivec2 offset); 202 | gvec4 textureProjLodOffset(gsampler3D sampler, vec4 P, float lod, ivec3 offset); 203 | float textureProjLodOffset(sampler1DShadow sampler, vec4 P, float lod, int offset); 204 | float textureProjLodOffset(sampler2DShadow sampler, vec4 P, float lod, ivec2 offset); 205 | }.specialize); 206 | mixin(q{ 207 | gvec4 textureGrad(gsampler1D sampler, float P, float dPdx, float dPdy); 208 | gvec4 textureGrad(gsampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy); 209 | gvec4 textureGrad(gsampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy); 210 | gvec4 textureGrad(gsamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy); 211 | gvec4 textureGrad(gsampler2DRect sampler, vec2 P, vec2 dPdx, vec2 dPdy); 212 | float textureGrad(sampler2DRectShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy); 213 | float textureGrad(sampler1DShadow sampler, vec3 P, float dPdx, float dPdy); 214 | float textureGrad(sampler2DShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy); 215 | float textureGrad(samplerCubeShadow sampler, vec4 P, vec3 dPdx, vec3 dPdy); 216 | gvec4 textureGrad(gsampler1DArray sampler, vec2 P, float dPdx, float dPdy); 217 | gvec4 textureGrad(gsampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy); 218 | float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy); 219 | float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); 220 | }.specialize); 221 | mixin(q{ 222 | gvec4 textureGradOffset(gsampler1D sampler, float P, float dPdx, float dPdy, int offset); 223 | gvec4 textureGradOffset(gsampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 224 | gvec4 textureGradOffset(gsampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy, ivec3 offset); 225 | gvec4 textureGradOffset(gsampler2DRect sampler, vec2 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 226 | float textureGradOffset(sampler2DRectShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 227 | float textureGradOffset(sampler1DShadow sampler, vec3 P, float dPdx, float dPdy, int offset ); 228 | float textureGradOffset(sampler2DShadow sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 229 | gvec4 textureGradOffset(gsampler1DArray sampler, vec2 P, float dPdx, float dPdy, int offset); 230 | gvec4 textureGradOffset(gsampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 231 | float textureGradOffset(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy, int offset); 232 | float textureGradOffset(sampler2DArrayShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 233 | }.specialize); 234 | mixin(q{ 235 | gvec4 textureProjGrad(gsampler1D sampler, vec2 P, float dPdx, float dPdy); 236 | gvec4 textureProjGrad(gsampler1D sampler, vec4 P, float dPdx, float dPdy); 237 | gvec4 textureProjGrad(gsampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy); 238 | gvec4 textureProjGrad(gsampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy); 239 | gvec4 textureProjGrad(gsampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy); 240 | gvec4 textureProjGrad(gsampler2DRect sampler, vec3 P, vec2 dPdx, vec2 dPdy); 241 | gvec4 textureProjGrad(gsampler2DRect sampler, vec4 P, vec2 dPdx, vec2 dPdy); 242 | float textureProjGrad(sampler2DRectShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); 243 | float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy); 244 | float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy); 245 | }.specialize); 246 | mixin(q{ 247 | gvec4 textureProjGradOffset(gsampler1D sampler, vec2 P, float dPdx, float dPdy, int offset); 248 | gvec4 textureProjGradOffset(gsampler1D sampler, vec4 P, float dPdx, float dPdy, int offset); 249 | gvec4 textureProjGradOffset(gsampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy, vec2 offset); 250 | gvec4 textureProjGradOffset(gsampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy, vec2 offset); 251 | gvec4 textureProjGradOffset(gsampler2DRect sampler, vec3 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 252 | gvec4 textureProjGradOffset(gsampler2DRect sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 253 | float textureProjGradOffset(sampler2DRectShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, ivec2 offset); 254 | gvec4 textureProjGradOffset(gsampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy, vec3 offset); 255 | float textureProjGradOffset(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy, int offset); 256 | float textureProjGradOffset(sampler2DShadow sampler, vec4 P, vec2 dPdx, vec2 dPdy, vec2 offset); 257 | }.specialize); 258 | } 259 | -------------------------------------------------------------------------------- /source/dglsl/shader.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl.shader; 3 | 4 | import std.string; 5 | import std.conv; 6 | 7 | import derelict.opengl3.gl3; 8 | 9 | import dglsl.type; 10 | import dglsl.sampler; 11 | import dglsl.translator; 12 | 13 | class ShaderBase { 14 | mixin TextureLookupFunctions; 15 | 16 | protected GLuint _shaderid; 17 | @property auto id() const { return _shaderid; } 18 | } 19 | 20 | enum input; 21 | enum output; 22 | enum uniform; 23 | enum ignore; 24 | 25 | private struct MaxVertices { 26 | int value = -1; 27 | } 28 | private struct Location { 29 | int value = -1; 30 | } 31 | private struct Primitive { 32 | string value; 33 | } 34 | struct Layout { 35 | Primitive qualifier; 36 | MaxVertices maxVertices; 37 | Location location; 38 | 39 | string glsl() { 40 | import std.conv; 41 | import std.array; 42 | string[] lst; 43 | if (qualifier != Primitive.init) lst ~= qualifier.value; 44 | if (maxVertices != MaxVertices.init) lst ~= "max_vertices = " ~ maxVertices.value.to!string; 45 | if (location != Location.init) lst ~= "location = " ~ location.value.to!string; 46 | return "layout(" ~ lst.join(", ") ~ ")"; 47 | } 48 | } 49 | 50 | string layout_attributes(T...)() { 51 | string[] lst; 52 | foreach (int i, immutable s; T) { 53 | static if (is(s == Primitive)) lst ~= "qualifier: args[%d]".format(i); 54 | else static if (is(s == MaxVertices)) lst ~= "maxVertices: args[%d]".format(i); 55 | else static if (is(s == Location)) lst ~= "location: args[%d]".format(i); 56 | } 57 | return lst.join(","); 58 | } 59 | auto layout(T...)(T args) { 60 | mixin("Layout l = {" ~ layout_attributes!T ~ "};"); 61 | return l; 62 | } 63 | @property auto max_vertices(int i) { return MaxVertices(i); } 64 | @property auto location(int i) { return Location(i); } 65 | 66 | 67 | class Shader(alias Type, int _version = 330, string file = __FILE__, int line = __LINE__) : ShaderBase { 68 | static immutable glslVersion = _version; 69 | static immutable filepath = file; 70 | static immutable lineno = line; 71 | mixin Type; 72 | } 73 | 74 | mixin template Vertex() { 75 | static assert(glslVersion >= 330, "You need at least GLSL version 330 for vertex shaders!"); 76 | static immutable type = "vertex"; 77 | vec4 gl_Position; 78 | } 79 | 80 | mixin template Fragment() { 81 | static assert(glslVersion >= 330, "You need at least GLSL version 330 for fragment shaders!"); 82 | static immutable type = "fragment"; 83 | } 84 | 85 | mixin template Geometry() { 86 | static assert(glslVersion >= 330, "You need at least GLSL version 330 for geometry shaders!"); 87 | static immutable type = "geometry"; 88 | void EmitVertex() {}; 89 | void EndPrimitive() {}; 90 | 91 | struct PerVertex { 92 | vec4 gl_Position; 93 | float gl_PointSize; 94 | float[] gl_ClipDistance; 95 | } 96 | PerVertex[] gl_in; 97 | 98 | vec4 gl_Position; 99 | float gl_PointSize; 100 | float[] gl_ClipDistance; 101 | 102 | struct of {} 103 | 104 | enum { 105 | points = Primitive("points"), 106 | lines = Primitive("lines"), 107 | lines_adjacency = Primitive("lines_adjacency"), 108 | triangles = Primitive("triangles"), 109 | triangles_adjacency = Primitive("triangles_adjacency"), 110 | triangle_strip = Primitive("triangle_strip"), 111 | line_strip = Primitive("line_strip") 112 | } 113 | } 114 | 115 | mixin template TessellationControl() { 116 | static assert(glslVersion >= 400, "You need at least GLSL version 400 for tessellation control shaders!"); 117 | static immutable type = "tessellationControl"; 118 | } 119 | 120 | mixin template TessellationEvaluation() { 121 | static assert(glslVersion >= 400, "You need at least GLSL version 400 for tessellation evaluation shaders!"); 122 | static immutable type = "tessellationEvaluation"; 123 | } 124 | 125 | mixin template Compute() { 126 | static assert(glslVersion >= 430, "You need at least GLSL version 430 for compute shaders!"); 127 | static immutable type = "compute"; 128 | } 129 | 130 | 131 | void compile(T : ShaderBase)(T shader) { 132 | static if (T.type == "vertex") 133 | GLuint id = glCreateShader(GL_VERTEX_SHADER); 134 | static if (T.type == "fragment") 135 | GLuint id = glCreateShader(GL_FRAGMENT_SHADER); 136 | static if (T.type == "geometry") 137 | GLuint id = glCreateShader(GL_GEOMETRY_SHADER); 138 | static if (T.type == "tessellationControl") 139 | GLuint id = glCreateShader(GL_GEOMETRY_SHADER); 140 | static if (T.type == "tessellationEvaluation") 141 | GLuint id = glCreateShader(GL_GEOMETRY_SHADER); 142 | static if (T.type == "compute") 143 | GLuint id = glCreateShader(GL_GEOMETRY_SHADER); 144 | 145 | auto src = dtoglsl!(T).toStringz; 146 | shader._shaderid = id; 147 | glShaderSource(id, 1, &src, null); 148 | glCompileShader(id); 149 | 150 | GLint compiled; 151 | glGetShaderiv(shader._shaderid, GL_COMPILE_STATUS, &compiled); 152 | if (compiled == GL_FALSE) { 153 | throw new Exception(infoLog(shader)); 154 | } 155 | } 156 | 157 | /* 158 | ** プログラムの情報を表示する 159 | ** ref: http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090827 160 | */ 161 | string infoLog(T : ShaderBase)(T shader) { 162 | GLsizei bufSize; 163 | 164 | /* シェーダのコンパイル時のログの長さを取得する */ 165 | glGetShaderiv(shader._shaderid, GL_INFO_LOG_LENGTH , &bufSize); 166 | 167 | if (bufSize == 0) return ""; 168 | 169 | GLchar[] infoLog = new GLchar[](bufSize); 170 | GLsizei length; 171 | 172 | /* シェーダのコンパイル時のログの内容を取得する */ 173 | glGetShaderInfoLog(shader._shaderid, bufSize, &length, infoLog.ptr); 174 | return format("InfoLog:\n%s\n", infoLog); 175 | } 176 | -------------------------------------------------------------------------------- /source/dglsl/translator.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl.translator; 3 | 4 | import std.range; 5 | import std.string; 6 | import std.traits; 7 | import std.algorithm; 8 | 9 | import dglsl.type; 10 | import dglsl.sampler; 11 | import dglsl.shader; 12 | 13 | 14 | string dtoglsl(Shader)() if (Shader.type == "vertex") { 15 | string result = "#version %s\n".format(Shader.glslVersion); 16 | string[] functions; 17 | 18 | foreach (immutable s; __traits(derivedMembers, Shader)) { 19 | static if (!hasUDA!(__traits(getMember, Shader, s), ignore)) { 20 | static if(is(typeof(__traits(getMember, Shader, s)) == function)) { 21 | functions ~= s; 22 | } else { 23 | static if (hasUDA!(__traits(getMember, Shader, s), input)) { 24 | static if (Shader.type == "vertex" && hasUDA!(__traits(getMember, Shader, s), Layout)) { 25 | auto l = getUDAs!(__traits(getMember, Shader, s), Layout)[0]; 26 | result ~= l.glsl ~ " "; 27 | } 28 | result ~= "in "; 29 | } 30 | 31 | static if (hasUDA!(__traits(getMember, Shader, s), output)) { 32 | result ~= "out "; 33 | } 34 | 35 | static if (hasUDA!(__traits(getMember, Shader, s), uniform)) { 36 | result ~= "uniform "; 37 | } 38 | 39 | result ~= "%s %s;\n".format(glslType!(typeof(__traits(getMember, Shader, s))), s); 40 | } 41 | } 42 | } 43 | 44 | result ~= copyFunctions!(Shader.filepath, Shader.lineno)(functions); 45 | 46 | return result; 47 | } 48 | 49 | string dtoglsl(Shader)() if (Shader.type == "fragment") { 50 | string result = "#version %s\n".format(Shader.glslVersion); 51 | string[] functions; 52 | 53 | foreach (immutable s; __traits(derivedMembers, Shader)) { 54 | static if (!hasUDA!(__traits(getMember, Shader, s), ignore)) { 55 | static if(is(typeof(__traits(getMember, Shader, s)) == function)) { 56 | functions ~= s; 57 | } else { 58 | static if (hasUDA!(__traits(getMember, Shader, s), input)) { 59 | static if (Shader.type == "vertex" && hasUDA!(__traits(getMember, Shader, s), Layout)) { 60 | auto l = getUDAs!(__traits(getMember, Shader, s), Layout)[0]; 61 | result ~= l.glsl ~ " "; 62 | } 63 | result ~= "in "; 64 | } 65 | 66 | static if (hasUDA!(__traits(getMember, Shader, s), output)) { 67 | result ~= "out "; 68 | } 69 | 70 | static if (hasUDA!(__traits(getMember, Shader, s), uniform)) { 71 | result ~= "uniform "; 72 | } 73 | 74 | result ~= "%s %s;\n".format(glslType!(typeof(__traits(getMember, Shader, s))), s); 75 | } 76 | } 77 | } 78 | 79 | 80 | result ~= copyFunctions!(Shader.filepath, Shader.lineno)(functions); 81 | 82 | return result; 83 | } 84 | 85 | string dtoglsl(Shader)() if (Shader.type == "geometry") { 86 | string result = "#version %s\n".format(Shader.glslVersion); 87 | string[] functions; 88 | 89 | static assert(__traits(hasMember, Shader, "_input"), "Geometry shaders need an '_input' member!"); 90 | static assert(__traits(hasMember, Shader, "_output"), "Geometry shaders need an '_output' member!"); 91 | static assert(__traits(hasMember, Shader, "gl_in"), "Geometry shaders need an 'gl_in' member!"); 92 | 93 | auto input = getUDAs!(Shader._input, Layout)[0]; 94 | result ~= input.glsl ~ " in;\n"; 95 | auto o = getUDAs!(Shader._output, Layout)[0]; 96 | result ~= o.glsl ~ " out;\n"; 97 | 98 | foreach (immutable s; __traits(derivedMembers, Shader)) { 99 | static if (s != typeof(Shader.gl_in[0]).stringof && !hasUDA!(__traits(getMember, Shader, s), ignore)) { 100 | alias t = typeof(__traits(getMember, Shader, s)); 101 | static if(is(t == function)) { 102 | functions ~= s; 103 | } else static if (s != "_input" && s != "_output") { 104 | static if (hasUDA!(__traits(getMember, Shader, s), uniform)) { 105 | result ~= "uniform "; 106 | } 107 | 108 | static if (hasUDA!(__traits(getMember, Shader, s), output)) { 109 | result ~= "out "; 110 | } 111 | 112 | result ~= "%s %s;\n".format(glslType!(typeof(__traits(getMember, Shader, s))), s); 113 | } 114 | } 115 | } 116 | 117 | result ~= copyFunctions!(Shader.filepath, Shader.lineno)(functions); 118 | 119 | return result; 120 | } 121 | 122 | string dtoglsl(Shader)() if (Shader.type == "tessellationControl") { 123 | string result = "#version %s\n".format(Shader.glslVersion); 124 | // TODO: 125 | return result; 126 | } 127 | 128 | string dtoglsl(Shader)() if (Shader.type == "tessellationEvaluation") { 129 | string result = "#version %s\n".format(Shader.glslVersion); 130 | // TODO: 131 | return result; 132 | } 133 | 134 | string dtoglsl(Shader)() if (Shader.type == "compute") { 135 | string result = "#version %s\n".format(Shader.glslVersion); 136 | // TODO: 137 | return result; 138 | } 139 | 140 | private string copyFunctions(string filepath, int lineno)(string[] functions) { 141 | import std.ascii; 142 | auto source = import(filepath).lineSplitter.drop(lineno - 1); 143 | string result; 144 | int level = 0; 145 | while (!source.empty && level >= 0) { 146 | string line = source.front; 147 | 148 | if (functions.any!((s) { 149 | auto r = line.findSplit(s); 150 | return !r[1].empty && !isAlphaNum(r[0][$ - 1]) && !isAlphaNum(r[2][0]); 151 | })) { 152 | int lvl = level; 153 | while (!source.empty) { 154 | if (source.front.canFind('{')) level++; 155 | if (source.front.canFind('}')) { 156 | level--; 157 | if (level < lvl) break; 158 | } 159 | result ~= source.front ~ "\n"; 160 | source.popFront(); 161 | } 162 | 163 | continue; 164 | } 165 | 166 | if (line.canFind('{')) level++; 167 | if (line.canFind('}')) level--; 168 | 169 | source.popFront(); 170 | } 171 | 172 | return result; 173 | } 174 | -------------------------------------------------------------------------------- /source/dglsl/type.d: -------------------------------------------------------------------------------- 1 | 2 | module dglsl.type; 3 | 4 | import std.traits; 5 | 6 | public import gl3n.linalg : Vector, Matrix; 7 | 8 | import dglsl.sampler; 9 | 10 | 11 | alias vec2 = Vector!(float, 2); 12 | alias ivec2 = Vector!(int, 2); 13 | alias uvec2 = Vector!(uint, 2); 14 | alias bvec2 = Vector!(ubyte, 2); // this should be bool? 15 | alias vec3 = Vector!(float, 3); 16 | alias ivec3 = Vector!(int, 3); 17 | alias uvec3 = Vector!(uint, 3); 18 | alias bvec3 = Vector!(ubyte, 3); // this should be bool? 19 | alias vec4 = Vector!(float, 4); 20 | alias ivec4 = Vector!(int, 4); 21 | alias uvec4 = Vector!(uint, 4); 22 | alias bvec4 = Vector!(ubyte, 4); // this should be bool? 23 | 24 | alias mat2x2 = Matrix!(float, 2, 2); 25 | alias mat2x3 = Matrix!(float, 2, 3); 26 | alias mat2x4 = Matrix!(float, 2, 4); 27 | alias mat3x2 = Matrix!(float, 3, 2); 28 | alias mat3x3 = Matrix!(float, 3, 3); 29 | alias mat3x4 = Matrix!(float, 3, 4); 30 | alias mat4x2 = Matrix!(float, 4, 2); 31 | alias mat4x3 = Matrix!(float, 4, 3); 32 | alias mat4x4 = Matrix!(float, 4, 4); 33 | alias mat2 = mat2x2; 34 | alias mat3 = mat3x3; 35 | alias mat4 = mat4x4; 36 | 37 | string glslType(T)() { 38 | static if (is(T == vec2)) return "vec2"; 39 | else static if (is(T == vec3)) return "vec3"; 40 | else static if (is(T == vec4)) return "vec4"; 41 | else static if (is(T == ivec2)) return "ivec2"; 42 | else static if (is(T == ivec3)) return "ivec3"; 43 | else static if (is(T == ivec4)) return "ivec4"; 44 | else static if (is(T == uvec2)) return "uvec2"; 45 | else static if (is(T == uvec3)) return "uvec3"; 46 | else static if (is(T == uvec4)) return "uvec4"; 47 | else static if (is(T == bvec2)) return "bvec2"; 48 | else static if (is(T == bvec3)) return "bvec3"; 49 | else static if (is(T == bvec4)) return "bvec4"; 50 | else static if (is(T == mat2x2)) return "mat2x2"; 51 | else static if (is(T == mat2x3)) return "mat2x3"; 52 | else static if (is(T == mat2x4)) return "mat2x4"; 53 | else static if (is(T == mat3x2)) return "mat3x2"; 54 | else static if (is(T == mat3x3)) return "mat3x3"; 55 | else static if (is(T == mat3x4)) return "mat3x4"; 56 | else static if (is(T == mat4x2)) return "mat4x2"; 57 | else static if (is(T == mat4x3)) return "mat4x3"; 58 | else static if (is(T == mat4x4)) return "mat4x4"; 59 | else static if (is(T == sampler1D)) return "sampler1D"; 60 | else static if (is(T == sampler2D)) return "sampler2D"; 61 | else static if (is(T == sampler3D)) return "sampler3D"; 62 | else static if (is(T == samplerCube)) return "samplerCube"; 63 | else static if (is(T == sampler2DRect)) return "sampler2DRect"; 64 | else static if (is(T == sampler1DShadow)) return "sampler1DShadow"; 65 | else static if (is(T == sampler2DShadow)) return "sampler2DShadow"; 66 | else static if (is(T == samplerCubeShadow)) return "samplerCubeShadow"; 67 | else static if (is(T == sampler2DRectShadow)) return "sampler2DRectShadow"; 68 | else static if (is(T == sampler1DArray)) return "sampler1DArray"; 69 | else static if (is(T == sampler2DArray)) return "sampler2DArray"; 70 | else static if (is(T == sampler1DArrayShadow)) return "sampler1DArrayShadow"; 71 | else static if (is(T == sampler2DArrayShadow)) return "sampler2DArrayShadow"; 72 | else static if (is(T == samplerBuffer)) return "samplerBuffer"; 73 | else static if (is(T == sampler2DMS)) return "sampler2DMS"; 74 | else static if (is(T == sampler2DMSArray)) return "sampler2DMSArray"; 75 | else static if (is(T == isampler1D)) return "isampler1D"; 76 | else static if (is(T == isampler2D)) return "isampler2D"; 77 | else static if (is(T == isampler3D)) return "isampler3D"; 78 | else static if (is(T == isamplerCube)) return "isamplerCube"; 79 | else static if (is(T == isampler2DRect)) return "isampler2DRect"; 80 | else static if (is(T == isampler1DArray)) return "isampler1DArray"; 81 | else static if (is(T == isampler2DArray)) return "isampler2DArray"; 82 | else static if (is(T == isamplerBuffer)) return "isamplerBuffer"; 83 | else static if (is(T == isampler2DMS)) return "isampler2DMS"; 84 | else static if (is(T == isampler2DMSArray)) return "isampler2DMSArray"; 85 | else static if (is(T == usampler1D)) return "usampler1D"; 86 | else static if (is(T == usampler2D)) return "usampler2D"; 87 | else static if (is(T == usampler3D)) return "usampler3D"; 88 | else static if (is(T == usamplerCube)) return "usamplerCube"; 89 | else static if (is(T == usampler2DRect)) return "usampler2DRect"; 90 | else static if (is(T == usampler1DArray)) return "usampler1DArray"; 91 | else static if (is(T == usampler2DArray)) return "usampler2DArray"; 92 | else static if (is(T == usamplerBuffer)) return "usamplerBuffer"; 93 | else static if (is(T == usampler2DMS)) return "usampler2DMS"; 94 | else static if (is(T == usampler2DMSArray)) return "usampler2DMSArray"; 95 | else return T.stringof; 96 | } 97 | 98 | unittest { 99 | assert(glslType!vec2 == "vec2"); 100 | assert(glslType!vec3 == "vec3"); 101 | assert(glslType!vec4 == "vec4"); 102 | assert(glslType!ivec2 == "ivec2"); 103 | assert(glslType!bvec3 == "bvec3"); 104 | assert(glslType!uvec4 == "uvec4"); 105 | 106 | assert(glslType!mat2 == "mat2x2"); 107 | assert(glslType!mat3 == "mat3x3"); 108 | assert(glslType!mat4 == "mat4x4"); 109 | assert(glslType!mat2x2 == "mat2x2"); 110 | assert(glslType!mat2x3 == "mat2x3"); 111 | assert(glslType!mat2x4 == "mat2x4"); 112 | assert(glslType!mat2x3 == "mat2x3"); 113 | assert(glslType!mat3x3 == "mat3x3"); 114 | assert(glslType!mat4x3 == "mat4x3"); 115 | 116 | assert(glslType!int == "int"); 117 | assert(glslType!uint == "uint"); 118 | assert(glslType!bool == "bool"); 119 | } 120 | 121 | --------------------------------------------------------------------------------