はじめに
前の記事でマンデルブロ集合を Canvas要素に書く方法をご紹介しました。imageData を使う方法で、ms オーダーまで高速化できましたが、それでもまだリアルタイムな描画とはいえませんでした。また処理時間が画素数に比例するので、大きなエリアでは描画されるまでにタイムラグが生じていました。
前の記事の描画部分を WebGL に取り替えて高速化を図るのが本校の目的です。
実際に使えるようにしたサイトを作りました。
見たい場所をマウスで選択してズームしていけるようになっています。よかったら参考にしてください。
プログラム
バーテックスシェーダー
ほぼ何もやることがありません。ソースは以下のようになります。
attribute vec3 position;
void
main() {
gl_Position = vec4( position, 1.0 );
}
フラグメントシェーダー
理論については前の記事を参考にしてください。
precision highp float;
precision highp int;
uniform vec2 min;
uniform vec2 max;
uniform vec2 resolution;
uniform int iterations;
int
Mandelbrot( vec2 c ) {
vec2 z = c;
for( int i = 1; i < 1000; ++i ) {
if ( i >= iterations ) break;
vec2 z2 = z * z;
if ( z2.x + z2.y > 4.0 ) return i;
z = vec2(
( z2.x - z2.y )
, ( z.y * z.x * 2.0 )
) + c;
}
return 0;
}
void
main( void ) {
int i = Mandelbrot(
vec2(
min.x + ( max.x - min.x ) * gl_FragCoord.x / resolution.x
, min.y + ( max.y - min.y ) * gl_FragCoord.y / resolution.y
)
);
gl_FragColor = vec4( float( i ) / float( iterations ), 0.0, 0.0, 1.0 );
}
呼び出し側(JavaScript)
- min, max には実部と虚部の最小値と最大値を入れて渡します。
- resolution にはキャンバスの大きさを入れて渡します。
- iterations には繰り返し回数を入れて渡します。
const minLocation = gl.getUniformLocation( program, 'min' )
const maxLocation = gl.getUniformLocation( program, 'max' )
const resolutionLocation = gl.getUniformLocation( program, 'resolution' )
const iterationLocation = gl.getUniformLocation( program, 'iterations' )
const
Draw = () => {
gl.viewport( 0, 0, CANVAS.width, CANVAS.height )
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT )
gl.useProgram( program )
gl.uniform2f( minLocation , Number( R_MIN.value ), Number( I_MIN.value ) )
gl.uniform2f( maxLocation , Number( R_MAX.value ), Number( I_MAX.value ) )
gl.uniform2f( resolutionLocation , CANVAS.width, CANVAS.height )
gl.uniform1i( iterationLocation , Number( NUM_I.value ) )
gl.vertexAttribPointer ( 0, 2, gl.FLOAT, false, 0, 0 )
gl.enableVertexAttribArray ( 0 )
gl.drawArrays ( gl.TRIANGLES, 0, 6 )
gl.disableVertexAttribArray ( 0 )
}
最後に
実際のソースは彩色の部分とかが付け加わっています。ペラ1で以下の場所にありますので、よかったら参考にしてください。