1 /** 2 * このモジュールをユーザーが直接使用することはありません。 3 */ 4 5 module grape.shader; 6 7 import derelict.opengl3.gl3; 8 9 import std.exception : enforce; 10 import std.stdio; 11 import std.traits : EnumMembers; 12 13 enum ShaderType { 14 Vertex = GL_VERTEX_SHADER, 15 Fragment = GL_FRAGMENT_SHADER 16 } 17 18 enum ShaderProgramType { 19 ClassicNormal = 0, 20 ClassicTexture = 1, 21 Font = 2, 22 Normal = 3, 23 Texture = 4, 24 Diffuse = 5, 25 ADS = 6, 26 GaussianX = 7, 27 GaussianY = 8, 28 } 29 30 mixin template ClassicNormalShaderSource() { 31 void delegate(out string, out string) ClassicNormalShader = (out string vShader, out string fShader) { 32 vShader = q{ 33 attribute vec3 pos; 34 attribute vec4 color; 35 varying vec4 vColor; 36 37 void main() { 38 vColor = color; 39 gl_Position = vec4(pos, 1.0); 40 } 41 }; 42 43 fShader = q{ 44 varying vec4 vColor; 45 46 void main() { 47 gl_FragColor = vColor; 48 } 49 }; 50 }; 51 } 52 53 mixin template ClassicTextureShaderSource() { 54 void delegate(out string, out string) ClassicTextureShader = (out string vShader, out string fShader) { 55 vShader = q{ 56 attribute vec3 pos; 57 attribute vec4 color; 58 attribute vec2 texCoord; 59 varying vec4 vColor; 60 varying vec2 vTexCoord; 61 62 void main() { 63 vColor = color; 64 vTexCoord = texCoord; 65 gl_Position = vec4(pos, 1.0); 66 } 67 }; 68 69 fShader = q{ 70 uniform sampler2D tex; 71 varying vec4 vColor; 72 varying vec2 vTexCoord; 73 74 void main() { 75 vec4 smpColor = texture2D(tex, vTexCoord); 76 // vec4 smpColor = texture2D(tex, vTexCoord); 77 gl_FragColor = smpColor; 78 //gl_FragColor = vColor * smpColor; 79 } 80 }; 81 }; 82 } 83 84 // pvmMatrixの設定をしていないのでデフォルト座標から見ている...はず 85 // eye: (0, 0, 0); 86 // center: (0, 0, -1); 87 // up: (0, 1, 0); 88 mixin template FontShaderSource() { 89 void delegate(out string, out string) FontShader = (out string vShader, out string fShader) { 90 vShader = q{ 91 attribute vec3 pos; 92 attribute vec2 texCoord; 93 varying vec2 vTexCoord; 94 95 void main() { 96 vTexCoord = texCoord; 97 gl_Position = vec4(pos, 1.0); 98 } 99 }; 100 101 fShader = q{ 102 uniform sampler2D tex; 103 varying vec2 vTexCoord; 104 105 void main() { 106 vec4 smpColor = texture2D(tex, vTexCoord); 107 gl_FragColor = smpColor; 108 } 109 }; 110 }; 111 } 112 113 mixin template NormalShaderSource() { 114 void delegate(out string, out string) NormalShader = (out string vShader, out string fShader) { 115 vShader = q{ 116 attribute vec3 pos; 117 attribute vec4 color; 118 uniform mat4 pvmMatrix; 119 varying vec4 vColor; 120 121 void main() { 122 vColor = color; 123 gl_Position = pvmMatrix * vec4(pos, 1.0); 124 } 125 }; 126 127 fShader = q{ 128 varying vec4 vColor; 129 130 void main() { 131 gl_FragColor = vColor; 132 } 133 }; 134 }; 135 } 136 137 mixin template TextureShaderSource() { 138 void delegate(out string, out string) TextureShader = (out string vShader, out string fShader) { 139 vShader = q{ 140 attribute vec3 pos; 141 attribute vec2 texCoord; 142 varying vec2 vTexCoord; 143 uniform mat4 pvmMatrix; 144 //attribute vec4 color; 145 //varying vec4 vColor; 146 147 void main() { 148 //vColor = color; 149 vTexCoord = texCoord; 150 gl_Position = pvmMatrix * vec4(pos, 1.0); 151 } 152 }; 153 154 fShader = q{ 155 uniform sampler2D tex; 156 varying vec2 vTexCoord; 157 //varying vec4 vColor; 158 159 void main() { 160 vec4 smpColor = texture2D(tex, vTexCoord); 161 //gl_FragColor = smpColor + vec4(1.0, 1.0, 1.0, 0.0);; 162 gl_FragColor = smpColor; 163 //gl_FragColor = smpColor + vec4(0.2, 0.2, 0.2, 0.0); 164 //gl_FragColor = vec4(0.2, 0.2, 0.2, 0.3); 165 /* 166 if (smpColor.a < 0.5) { 167 discard; 168 } else { 169 gl_FragColor = smpColor; 170 } 171 */ 172 //gl_FragColor = vColor; 173 //gl_FragColor = smpColor + vColor; 174 //gl_FragColor = vec4(smpColor.rgb, vColor.a * smpColor.a); 175 } 176 }; 177 }; 178 } 179 180 mixin template DiffuseShaderSource() { 181 void delegate(out string, out string) DiffuseShader = (out string vShader, out string fShader) { 182 vShader = q{ 183 attribute vec3 pos; 184 attribute vec3 normal; 185 attribute vec4 color; 186 187 uniform vec3 lightPos; 188 189 uniform mat4 pvmMatrix; 190 uniform mat4 invMatrix; 191 192 varying vec4 vColor; 193 194 void main() { 195 vec3 invLight = normalize(invMatrix * vec4(lightPos, 0.0)); 196 float diffuse = clamp(dot(normal, invLight), 0.1, 1.0); 197 vColor = color * vec4(vec3(diffuse), 1.0); 198 gl_Position = pvmMatrix * vec4(pos, 1.0); 199 } 200 }; 201 202 fShader = q{ 203 varying vec4 vColor; 204 205 void main() { 206 gl_FragColor = vColor; 207 } 208 }; 209 }; 210 } 211 212 mixin template ADSShaderSource() { 213 void delegate(out string, out string) ADSShader = (out string vShader, out string fShader) { 214 vShader = q{ 215 attribute vec3 pos; 216 attribute vec3 normal; 217 attribute vec4 color; 218 219 uniform vec3 lightPos; 220 uniform vec3 eyePos; 221 uniform vec4 ambientColor; 222 223 uniform mat4 pvmMatrix; 224 uniform mat4 invMatrix; 225 226 varying vec4 vColor; 227 228 void main() { 229 vec3 invLight = normalize(invMatrix * vec4(lightPos, 0.0)); 230 vec3 invEye = normalize(invMatrix * vec4(eyePos, 0.0)); 231 vec3 halfLE = normalize(invLight + invEye); 232 float diffuse = clamp(dot(normal, invLight), 0.0, 1.0); 233 float specular = pow(clamp(dot(normal, halfLE), 0.0, 1.0), 50.0); 234 vec4 light = color * vec4(vec3(diffuse), 1.0) + vec4(vec3(specular), 1.0); 235 vColor = light + ambientColor; 236 gl_Position = pvmMatrix * vec4(pos, 1.0); 237 } 238 }; 239 240 fShader = q{ 241 varying vec4 vColor; 242 243 void main() { 244 gl_FragColor = vColor; 245 } 246 }; 247 }; 248 } 249 250 mixin template GaussianShaderSource() { 251 void delegate(out string, out string) GaussianShader = (out string vShader, out string fShader) { 252 vShader = q{ 253 attribute vec2 pos; 254 attribute vec2 texCoord; 255 varying vec2 vTexCoord; 256 257 void main() { 258 gl_Position = vec4(pos, 0.0, 1.0); 259 vTexCoord = texCoord; 260 } 261 }; 262 263 fShader = q{ 264 uniform sampler2D tex; 265 uniform float weight[8]; 266 uniform int type; 267 uniform vec2 resolution; 268 varying vec2 vTexCoord; 269 270 void main() { 271 vec2 t = vec2(1.0) / resolution; 272 vec4 color = texture2D(tex, vTexCoord) * weight[0]; 273 274 if (type == 0) { 275 for (int i=1; i<8; ++i) { 276 color += texture2D(tex, (gl_FragCoord.xy + vec2(-1*i, 0)) * t) * weight[i]; 277 color += texture2D(tex, (gl_FragCoord.xy + vec2(1*i, 0)) * t) * weight[i]; 278 } 279 } else if (type == 1) { 280 for (int i=1; i<8; ++i) { 281 color += texture2D(tex, (gl_FragCoord.xy + vec2(0, -1*i)) * t) * weight[i]; 282 color += texture2D(tex, (gl_FragCoord.xy + vec2(0, 1*i)) * t) * weight[i]; 283 } 284 } 285 286 gl_FragColor = color; 287 } 288 }; 289 }; 290 } 291 292 mixin template FilterShaderSource() { 293 void delegate(out string, out string) FilterShader = (out string vShader, out string fShader) { 294 vShader = q{ 295 attribute vec3 pos; 296 attribute vec2 texCoord; 297 varying vec2 vTexCoord; 298 //uniform mat4 pvmMatrix; 299 300 void main() { 301 //gl_Position = pvmMatrix * vec4(pos, 0.0, 1.0); 302 gl_Position = vec4(pos, 1.0); 303 vTexCoord = texCoord; 304 } 305 }; 306 307 fShader = q{ 308 uniform sampler2D tex; 309 varying vec2 vTexCoord; 310 311 void main() { 312 vec4 smpColor = texture2D(tex, vTexCoord); 313 gl_FragColor = smpColor; 314 //gl_FragColor = (smpColor.rgb, 0.2); 315 //gl_FragColor = smpColor + vec4(0.2, 0.0, 0.0, 1.0); 316 } 317 }; 318 }; 319 } 320 321 class Shader { 322 public: 323 this(in ShaderType type) { 324 generate(type); 325 }; 326 327 this(in ShaderType type, in string shaderCode) { 328 this(type); 329 compile(shaderCode); 330 } 331 332 ~this() { 333 eliminate(); 334 } 335 336 void compile(in string shaderCode) { 337 auto fst = &shaderCode[0]; 338 int len = cast(int)shaderCode.length; // TODO 339 glShaderSource(_shader, 1, &fst, &len); 340 glCompileShader(_shader); 341 342 GLint result; 343 glGetShaderiv(_shader, GL_COMPILE_STATUS, &result); 344 enforce(result != GL_FALSE, "glCompileShader() faild"); 345 } 346 347 alias _shader this; // TODO 348 349 private: 350 void generate(in ShaderType type) { 351 _shader = glCreateShader(type); 352 enforce(_shader, "glCreateShader() faild"); 353 } 354 355 void eliminate() { 356 glDeleteShader(_shader); 357 } 358 359 GLuint _shader; 360 } 361 362 class ShaderProgram { 363 public: 364 this() { 365 generate(); 366 } 367 368 this(Shader vs, Shader fs) { 369 this(); 370 attach(vs, fs); 371 } 372 373 ~this() { 374 eliminate(); 375 } 376 377 void attach(T)(in T vs, in T fs) { 378 glAttachShader(_program, vs); 379 glAttachShader(_program, fs); 380 glLinkProgram(_program); 381 382 int linked; 383 glGetProgramiv(_program, GL_LINK_STATUS, &linked); 384 enforce(linked != GL_FALSE, "glLinkProgram() faild"); 385 } 386 387 void use() { 388 glUseProgram(_program); 389 } 390 391 alias _program this; 392 GLuint _program; 393 394 private: 395 void generate() { 396 _program = glCreateProgram(); 397 enforce(_program, "glCreateProgram() faild"); 398 } 399 400 void eliminate() { 401 glDeleteProgram(_program); 402 } 403 } 404