1

I'm having a little bit of trouble conceptualizing the workflow used in a shader-based OpenGL program. While I've never really done any major projects using either the fixed-function or shader-based pipelines, I've started learning and experimenting, and it's become quite clear to me that shaders are the way to go.

However, the fixed-function pipeline makes much more sense to me from an intuitive perspective. Rendering a scene with that method is simple and procedural—like painting a picture. If I want to draw a box, I tell the graphics card to draw a box. If I want a lot of boxes, I draw my box in a loop. The fixed-function pipeline fits well with my established programming tendencies.

These all seem to go out the window with shaders, and this is where I'm hitting a block. A lot of shader-based tutorials show how to, for example, draw a triangle or a cube on the screen, which works fine. However, they don't seem to go into at all how I would apply these concepts in, for example, a game. If I wanted to draw three procedurally generated triangles, would I need three shaders? Obviously not, since that would be infeasible. Still, it's clearly not as simple as just sticking the drawing code in a loop that runs three times.

Therefore, I'm wondering what the "best practices" are for using shaders in game development environments. How many shaders should I have for a simple game? How do I switch between them and use them to render a real scene?

I'm not looking for specifics, just a general understanding. For example, if I had a shader that rendered a circle, how would I reuse that shader to draw different sized circles at different points on the screen? If I want each circle to be a different color, how can I pass some information to the fragment shader for each individual circle?

4

2 に答える 2

1

円を描くシェーダーはありません (わかりました、正しいトリックを使用することはできますが、誤解を招きやすく、非常にまれで特定の用途があるため、今は忘れましょう)。シェーダーは、グラフィック パイプラインの特定の段階を処理するために作成する小さなプログラムであり、「円を描く」よりも具体的です。一般的に言えば、描画呼び出しを行うたびに、使用するシェーダーを openGL に伝える必要があります ( を呼び出してglUseProgram、少なくとも頂点シェーダーとフラグメント シェーダーを使用する必要があります。結果のパイプラインは次のようになります。

Vertex Shader: openGL に送信する各頂点に対して実行されるコード。要素配列で送信したインデックスごとに実行され、頂点位置、法線、UV 座標、タンジェントなどの対応する頂点属性を入力データとして使用します (法線マッピングを行っている場合)。 、またはあなたがそれに送っているものは何でも。通常、ここで幾何学的計算を行います。描画呼び出し用に設定した均一変数にアクセスすることもできます。これは、頂点ごとに変更されないグローバル変数です。頂点シェーダーで使用する可能性がある典型的な均一変数は、PVM マトリックスです。テッセレーションを使用しない場合、頂点シェーダーは、ラスタライザーがフラグメントを作成するために使用する位置である gl_Position を書き込みます。

Rasterization

Fragment Shader: 各フラグメントに対して実行されるコード (より明確な場合は各ピクセルに対して)。通常、ここでテクスチャ サンプリングとライト計算を行います。法線 (ディフューズとスペキュラーの項を評価するため) や UV 座標 (テクスチャから適切な色を取得するため) など、頂点シェーダーとラスタライザーからのデータを使用します。テクスチャは均一になり、おそらく評価しているライトのパラメータも均一になります。

深度テスト、ステンシル テスト。(初期のフラグメント最適化 ( http://www.opengl.org/wiki/Early_Fragment_Test )を使用して、フラグメント シェーダーの前に移動できます)

ブレンディング。

シンプルなシェーダーhttp://sourceforge.net/projects/quickshader/を開発するこの素敵なプログラムを見ることをお勧めします。これには非常に良い例があり、すべてのチュートリアルで見つけることができないより高度なものもあります。

于 2013-09-02T06:20:38.743 に答える