Last active
December 9, 2015 07:56
-
-
Save Pentan/fed56373255311241c6f to your computer and use it in GitHub Desktop.
http://www.vertexshaderart.com/art/HW98dGDbChYw2FjpS に投稿したものに日本語でコメントをつけたもの
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define PI05 1.570796326795 | |
#define PI 3.1415926535898 | |
// 適当なハッシュ関数.よくあるやつですが投稿したバージョンではカッコの位置を間違えているので注意 | |
vec3 hash3(vec3 v) { | |
return fract(sin(v) * vec3(43758.5453123, 12345.6789012,76543.2109876)); | |
} | |
// 回転関連 | |
vec3 rotX(vec3 p, float rad) { | |
vec2 sc = sin(vec2(rad, rad + PI05)); | |
vec3 rp = p; | |
rp.y = p.y * sc.y + p.z * -sc.x; | |
rp.z = p.y * sc.x + p.z * sc.y; | |
return rp; | |
} | |
vec3 rotY(vec3 p, float rad) { | |
vec2 sc = sin(vec2(rad, rad + PI05)); | |
vec3 rp = p; | |
rp.x = p.x * sc.y + p.z * sc.x; | |
rp.z = p.x * -sc.x + p.z * sc.y; | |
return rp; | |
} | |
vec3 rotZ(vec3 p, float rad) { | |
vec2 sc = sin(vec2(rad, rad + PI05)); | |
vec3 rp = p; | |
rp.x = p.x * sc.x + p.y * sc.y; | |
rp.y = p.x * -sc.y + p.y * sc.x; | |
return rp; | |
} | |
// 透視変換 | |
vec4 perspective(vec3 p, float fov, float near, float far) { | |
vec4 pp = vec4(p, -p.z); | |
pp.xy *= vec2(resolution.y / resolution.x, 1.0) / tan(radians(fov * 0.5)); | |
pp.z = (-p.z * (far + near) - 2.0 * far * near) / (far - near); | |
return pp; | |
} | |
// おなじみLookAt | |
vec3 lookat(vec3 p, vec3 eye, vec3 look, vec3 up) { | |
vec3 z = normalize(eye - look); | |
vec3 x = normalize(cross(up, z)); | |
vec3 y = cross(z, x); | |
vec4 pp = mat4(x.x, y.x, z.x, 0.0, x.y, y.y, z.y, 0.0, x.z, y.z, z.z, 0.0, 0.0, 0.0, 0.0, 1.0) * | |
mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -eye.x, -eye.y, -eye.z, 1.0) | |
* vec4(p, 1.0); | |
return pp.xyz; | |
} | |
// リサジュー曲線 | |
vec3 lissajous(vec3 a, float t) { | |
return vec3(sin(t * a.x), sin(t * a.y), cos(t * a.z)); | |
} | |
// 立方体の頂点をつくる.入力は0から36を想定 | |
// 頂点を節約できるかとTRIANGLE_STRIPで描いて縮退ポリゴンで繋ぐようにしたが、立方体ではTRIANGLESと使う頂点数が変わらずあまり意味がない | |
// vid : 0 to 36 (6 faces * 6 vertices), ni: (normal.xyz, faceId) | |
#define kCubeVertexCount 36.0 | |
vec3 cubeVertex(float vid, out vec4 ni) { | |
// 6個の面で構成されているので面の番号 | |
float faceId = floor(vid / 6.0); | |
// 1つの面は6この頂点で構成されているのでその面の中での頂点番号 | |
float vtxId = mod(vid, 6.0); | |
vec2 fp; | |
vec3 p; | |
// TRIANGLE_STRIPで繋ぐため最初と最後の頂点を重複させる | |
if(vtxId <= 1.0) { | |
fp = vec2(1.0, 1.0); | |
} | |
else if(vtxId == 2.0) { | |
fp = vec2(-1.0, 1.0); | |
} | |
else if(vtxId == 3.0) { | |
fp = vec2(1.0, -1.0); | |
} | |
else { | |
fp = vec2(-1.0, -1.0); | |
} | |
if(faceId == 0.0) { | |
// front | |
p = vec3(fp.x, fp.y, 1.0); | |
ni = vec4(0.0, 0.0, 1.0, faceId); | |
} | |
else if(faceId == 1.0) { | |
// back | |
p = vec3(-fp.x, fp.y, -1.0); | |
ni = vec4(0.0, 0.0, -1.0, faceId); | |
} | |
else if(faceId == 2.0) { | |
// top | |
p = vec3(fp.x, 1.0, -fp.y); | |
ni = vec4(0.0, 1.0, 0.0, faceId); | |
} | |
else if(faceId == 3.0) { | |
// bottom | |
p = vec3(fp.x, -1.0, fp.y); | |
ni = vec4(0.0, 0.0, -1.0, faceId); | |
} | |
else if(faceId == 4.0) { | |
// right | |
p = vec3(-1.0, fp.y, -fp.x); | |
ni = vec4(-1.0, 0.0, 0.0, faceId); | |
} | |
else { | |
// left | |
p = vec3(1.0, fp.y, fp.x); | |
ni = vec4(1.0, 0.0, 0.0, faceId); | |
} | |
return p; | |
} | |
// シェーディング | |
vec3 shade(vec3 eye, vec3 p, vec3 n, vec3 dfscol, float amb, vec2 spec) { | |
vec3 rgb; | |
vec3 lit = normalize(vec3(1.0, 1.0, 4.0)); | |
float diffuse = max(0.0, dot(n, lit)) * (1.0 - amb) + amb; | |
vec3 h = normalize(normalize(eye - p) + lit); | |
float specular = 0.0; | |
if(diffuse > 0.0) { | |
specular = max(0.0, pow(dot(n, h), spec.x)); | |
} | |
rgb = diffuse * dfscol + specular * spec.y; | |
return rgb; | |
} | |
void main() { | |
// 頂点で構築できるシェイプ(立方体)の数 | |
float shapeCount = floor(vertexCount / kCubeVertexCount); | |
// シェイプのID | |
float shapeId = floor(vertexId / kCubeVertexCount); | |
// シェイプの中での頂点番号 | |
float shapeVertexId = mod(vertexId, kCubeVertexCount); | |
// リサジュー曲線の番号 | |
float lineId = mod(shapeId, 3.0); | |
// 曲線のパラメーター.ここでは3種類用意 | |
vec3 lineFactor; | |
vec3 color; | |
if(lineId == 0.0) { | |
lineFactor = vec3(4.1, 6.7, 2.3); | |
color = vec3(1.0, 0.0, 0.0); | |
} | |
else if(lineId == 1.0) { | |
lineFactor = vec3(4.8, 5.2, 8.3); | |
color = vec3(0.0, 1.0, 0.0); | |
} | |
else { | |
lineFactor = vec3(6.1, 1.2, 3.6); | |
color = vec3(0.0, 0.0, 1.0); | |
} | |
// 立方体としての頂点を求める | |
vec4 cubeni; | |
vec3 cubep = cubeVertex(shapeVertexId, cubeni) * 0.04; | |
// 乱数で適当にオフセットと回転 | |
vec3 cubeHash = hash3(vec3(log(shapeId))); | |
vec3 cubeOffset = (cubeHash * 2.0 - 1.0) * 0.1; | |
vec3 cubeRot = hash3(cubeHash) * time * 2.0; | |
// 位置と法線に回転を適用 | |
cubep = rotX(rotY(rotZ(cubep, cubeRot.z), cubeRot.y), cubeRot.z); | |
cubeni.xyz = rotX(rotY(rotZ(cubeni.xyz, cubeRot.z), cubeRot.y), cubeRot.z); | |
// リサジュー曲線上に移動 | |
float t = shapeId / shapeCount; | |
float aspect = resolution.x / resolution.y; | |
cubep = lissajous(lineFactor, (t + time * 0.1) * 2.0) * vec3(aspect, 1.0, aspect) + (cubep + cubeOffset); | |
/* | |
// 面毎に色を変えてみる | |
if(cubeni.w == 0.0) { | |
color = vec3(1.0, 0.0, 0.0); | |
} | |
else if(cubeni.w == 1.0) { | |
color = vec3(0.0, 1.0, 0.0); | |
} | |
else if(cubeni.w == 2.0) { | |
color = vec3(0.0, 0.0, 1.0); | |
} | |
else if(cubeni.w == 3.0) { | |
color = vec3(1.0, 1.0, 0.0); | |
} | |
else if(cubeni.w == 4.0) { | |
color = vec3(1.0, 0.0, 1.0); | |
} | |
else { | |
color = vec3(0.0, 1.0, 1.0); | |
} | |
*/ | |
// 視点の位置 | |
//vec3 eye = rotX(rotY(vec3(0.0, 0.0, 3.0), -mouse.x * 2.0), mouse.y); | |
vec3 eye = vec3(0.0, 0.0, 3.0); | |
// シェーディング | |
color = shade(eye, cubep, cubeni.xyz, vec3(0.5 + cubeHash * 0.05), 0.1, vec2(64.0, 0.8)); | |
// 最終的な変換 | |
vec3 p = lookat(cubep, eye, vec3(0.0), vec3(0.0, 1.0, 0.0)); | |
gl_Position = perspective(p, 60.0, 0.1, 10.0); | |
gl_PointSize = 20.0; | |
// 色 | |
v_color = vec4(color, 1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment