Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
http://www.vertexshaderart.com/art/HW98dGDbChYw2FjpS に投稿したものに日本語でコメントをつけたもの
#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