LoginSignup
0
0

More than 1 year has passed since last update.

マンデルブロ集合を JavaScript で高速に描く(WebGL編)

Last updated at Posted at 2022-08-26

はじめに

MiConv2022-08-26 22.32.49.gif

前の記事でマンデルブロ集合を 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で以下の場所にありますので、よかったら参考にしてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0