現実逃避的にWebGLのGLSLでレイマーチングをやってみました。
下記のstartを押すとJavascriptからWebGLが作動します。 Chomium 40.0 とFirefox 34.0 で動作確認しています。 3D対応のグラフィックカードが必要です。
fragment shader
#line 1 0
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
uniform vec2 resolution;
uniform vec2 mouse;
uniform float time;
// =============================================================================
mat4 invertFrustum(float near, float far,
float focus, float aspect) {
float C = 1.0 / (2.0 * far * near);
return mat4(1.0 / focus, 0.0, 0.0, 0.0,
0.0, aspect / focus, 0.0, 0.0,
0.0, 0.0, 0.0, -1.0,
0.0, 0.0, (near - far) * C, (near + far) * C);
}
// =============================================================================
vec4 screen2camera(vec2 p,
float near, float far,
float focus, float aspect) {
return invertFrustum(near, far, focus, aspect) *
vec4(p, (far+near)/(far-near)*near - 1.0, 2.0*near*far/(far-near)*near);
}
// =============================================================================
float distance(vec3 pos) {
pos -= vec3(0.0, sin(time), -5.0 - sin(time));
pos = mod(pos, 4.0) - 2.0;
return length(pos) - 1.0;
}
// =============================================================================
vec3 normal(vec3 pos) {
const float d = 0.0001;
const float z = 0.0;
return normalize(vec3(
distance(pos+vec3( d, z, z)) - distance(pos+vec3(-d, z, z)),
distance(pos+vec3( z, d, z)) - distance(pos+vec3( z, -d, z)),
distance(pos+vec3( z, z, d)) - distance(pos+vec3( z, z, -d))));
}
// =============================================================================
vec3 HSV2RGB(float h, float s, float v) {
if (1.0 <= h || 1.0 < s || 1.0 < v) { return vec3(1.0, 1.0, 1.0); }
if (0.0 > h || 0.0 > s || 0.0 > v) { return vec3(0.0, 0.0, 0.0); }
h *= 6.0;
int i = int(h);
float f = h - float(i);
float m = v * (1.0 - s);
if (0 == i) { return vec3(v, v * (1.0 - s * (1.0 - f)), m); }
else if (1 == i) { return vec3(v * (1.0 - s * f), v, m); }
else if (2 == i) { return vec3(m, v, v * (1.0 - s * (1.0 - f))); }
else if (3 == i) { return vec3(m, v * (1.0 - s * f), v); }
else if (4 == i) { return vec3(v * (1.0 - s * (1.0 - f)), m, v); }
else if (5 == i) { return vec3(v, m, v * (1.0 - s * f)); }
else { return vec3(0.0, 0.0, 0.0); }
}
// -----------------------------------------------------------------------------
vec3 HSV2RGB(vec3 hsv) {
return HSV2RGB(hsv.x, hsv.y, hsv.z);
}
// =============================================================================
const int loop = 64;
// =============================================================================
void main(void) {
vec2 uv = (2.0 * gl_FragCoord.xy / resolution - 1.0);
vec3 ray = screen2camera(uv, 1.0, 40001.0,
2.1875, resolution.y / resolution.x).xyz;
ray = normalize(ray);
float t = 0.0;
float d = 0.0;
vec3 pos;
for(int i = 0; i < loop; ++i) {
pos = t * ray;
d = distance(pos);
t += d;
}
if (abs(d) < 0.001) {
vec3 n = normal(pos);
vec3 h = normalize(n - ray);
gl_FragColor = vec4(HSV2RGB(smoothstep(-1.0, 1.0, h)),
pow(1.0 - max(0.0, dot(-ray, n)), 2.0));
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
}
下記サイトを参考にさせていただきました。
0 件のコメント:
コメントを投稿