私はWebGLを初めて使用しますが、JavascriptやCanvasは初めてです。基本的に、キャンバス上のピクセルの色を任意の座標で変更できる非常に高速な方法が必要です。これは、WebGLフラグメントシェーダーを使用して実行できると思います。これは可能ですか、そしてより良い方法はありますか?どうすればこれを行うことができますか?
3 に答える
これは、シェーダー管理に関するビットが含まれていないため、レンダリングの完全なガイドではありません。代わりに、WebGL プリミティブの描画が実際にどのように実行されるか、正投影を使用して画面上に頂点を正確に配置する方法に焦点を当てています。
詳細については、次のソースを強くお勧めします。
WebGL は頂点バッファー オブジェクト (VBO) を使用してすべての描画を行うため、すべてのデータを 3D 頂点にコンパイルし、(パフォーマンスを最大化するために) できるだけ少ない VBO でそれらをビデオ カードに送信する必要があります。
VBO は WebGL で次のように作成できます。
var vbo = gl.createBuffer();
次に、データをバッファに送信する必要があります。通常はFloat32Array
. データが通常の JavaScript 配列の形式で既にある場合は、 を使用しての内容からnew Float32Array(jsArray)
を初期化できます。ただし、これをめったに実行しないでください。型付き配列は非常に高速ですが、初期化は非常に遅くなります。一度作成して、可能な限り再利用することをお勧めします。Float32Array
jsArray
を取得したらFloat32Array
、次のようにデータをバッファに渡すことができます。
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
データが変更されるたびに、bufferData
または呼び出しを実行する必要があります。bufferSubData
この時点でデータはグラフィックス カード上にあるため、実際に描画するだけで済みます。
// bind the VBO to be drawn if you haven't already
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// send the vertex data to the shader program
gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// draw the buffer
gl.drawArrays(gl.POINTS, 0, float32Data.length / 3);
グラフィックス カードはかなりの数の VBO を保持できますが、使用する VBO はできるだけ少なくする必要があることに注意してください。drawArrays
実行する必要がある呼び出しが多いほど、処理が遅くなるからです。実際、特定の VBO で一度に 1 つのピクセルのみをレンダリングすると、実行するには遅すぎます。
の長さがFloat32Array
3 で除算される理由は、各単一データ要素が 3D (X、Y、Z) 座標であるため、各データ要素は 3 つの float コンポーネントで構成されるためです。への最初の引数は であることに注意してgl.drawArrays
くださいgl.POINTS
。これは、グラフィックス カードに、配列内の各項目に対して 1 つの点 (既定では 1 ピクセルのサイズ) を描画するように指示します。描画する方法は他にもあります。ピクセルのグループを塗りつぶす必要がある場合は、他の描画モードの 1 つ (例: gl.TRIANGLES
) の方が好みに合う場合があります。
特定のピクセルのライトアップに関しては、シェーダーの記述方法によって異なりますが、モデルビュー マトリックスとプロジェクション マトリックスを使用している可能性が最も高いです。モデルビュー マトリックスは、描画されるポイントに対するカメラの向きを表し、射影マトリックスは、カメラの寸法 (幅と高さ、視野、最も近い可視範囲と最も遠い可視範囲など) を表します。したがって、特定のピクセルを照らしたい場合は、正射投影を適用するのが最善の策です。キャンバスの幅と高さに等しい幅と高さを持つ射影行列。モデルビュー マトリックスは ID に設定されます (変換なし)。正射投影では、オブジェクトがカメラから離れても縮小しないため、画面に対する正確な位置を指定するのに非常に役立ちます。また、適切な寸法を指定すると、頂点を非常に正確に(必要に応じて特定のピクセルに) 配置できます。
異なる行列ライブラリは異なる方法で動作しますが、たとえば、 gl-matrixで正射行列を設定するには、次のように行うことができます。
var ortho = mat4.ortho(left, right, bottom, top, near, far);
正確な数は好みによって異なります。原点 (0, 0) をキャンバスの左下に配置する場合は、次のようにします。
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
ただし、レンダリングするためには、各ポイントの Z 値が と の間near
にある必要があり、値を に設定できないことに注意してください。far
near
0
これについて明確にする必要がある場合はお知らせください。
単一のピクセルを描画したいだけの場合は、canvas2dを使用したほうがよいでしょう。
それ以外の場合は、ピクセル単位で長方形を描画するこのチュートリアルからおそらく理解できるので、幅と高さを1x1に設定すると、単一のピクセルが得られます。
描画時に GL_POINTS を使用できます。基本的に、ポイントの配列を色と位置とともに GPU に渡します。次に、適切なデータを使用して drawArrays を呼び出します。
これは他のものと結びつきすぎているかもしれませんが、これはあなたを助けるかもしれません:
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L126
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L260
これが、chesterGL のプリミティブ ブロックでいくつかのポイントをレンダリングする方法です。