GLSLデフォルトシェーダー


7

エラーチェックコードでエンジンを準備しています。私はこの状況を最善の能力で説明するつもりです。シェーダーをロードしてエラーが発生したときはいつでも(ファイルが存在しない、コンパイルエラー、問題が発生する可能性があるすべて)シェーダーを削除し、ポインターを0に設定します(これを確認する別の方法は考えられません)誤ってゴミを添付または削除しようとした場合)。これが発生した場合、プログラムを停止したくありません。誰かが誤ってゲームフォルダー内の1つのファイルを削除または変更し、そのためにゲーム全体を使用不可にしたくないからです。

さて、ポインタが0であるプログラムにシェーダをアタッチする場合、デフォルトの動作はありますか?

私のプログラムでは、頂点シェーダーが0に、フラグメントシェーダーが0に接続されている場合、OpenGLはデフォルトのプログラムを使用します(すべてが白で表示されます)。

ここに画像の説明を入力してください

これは、ディメンションが既にクリップスペースにある回転した立方体であり、透視投影や深度チェックなしでレンダリングされます。.objファイルから読み込まれます。

ここで、適切なフラグメントシェーダーをアタッチしたが、頂点シェーダーが0になると、次のようになります。

ここに画像の説明を入力してください

これは私が期待することです。フラグメントシェーダーはすべてvec4(1.0、0.3、0.7、1.0)を出力します。頂点シェーダーがないため、OpenGLはデフォルトのシェーダーを使用します(これは正しい仮定ですか?)。

ただし、正しい頂点シェーダーをアタッチしたが、フラグメントシェーダーを0にアタッチした場合(または、フラグメントシェーダーをまったくアタッチしない場合)、次のようになります。

ここに画像の説明を入力してください

目に見えないのは、このモデルが絶えずさまざまな色でペイントされていることです。そのため、私の画面では、黒い水平線が通る酸性の旅行のように見えます。

私は少し混乱しています。なぜなら、私は立方体がちょうど白いことを期待しているからです。私のシェーダーコードは最低限の骨であり、頂点シェーダーとフラグメントシェーダーの間で変数を交換していないことを指摘しておきます。ポインターが0に等しくないかどうかを確認しても何も変更されません。リンクされたプログラムは、ポインターに0を指定した場合と同じように動作します。私にとって最も奇妙なのは、常にゴミ箱ではなく、適切に網掛けされていることです。

編集:おそらくデフォルトのフラグメントシェーダーは、設定を省略している頂点からのgl_値を期待していますか?これは、表面が適切にシェーディングされる理由を説明するものであり、フラグメントシェーダーはスムーズなインを期待していますが、その値は単なるゴミです。

これは「未定義の振る舞い」ですか、それともどのように機能すると思われますか?


「誰かがファイルを削除する可能性がある」のを防ぐことは非常に生産的ではないことに注意したいです。.exeを削除したり、ファイルを完全に互換性のないファイルに置き換えたりする可能性もあります。デフォルトのシェーダー、マテリアル、メッシュなどはデバッグとテストに役立ちます。これらは絶対に必要ですが、必要なデータが愚かなエンドユーザーによってばかばかしく破壊されている場合でも、完全に機能することを強調してください。
Sean Middleditch、2012年

@seanmiddleditchそれはそれを見る1つの方法です。エラーチェックコードを#ifdef _DEBUGに移動できると思いますか?
dreta

私のポイントは、たくさんの派手な自己保存コードを書くことではなく、そのようなコードはデバッグモードでのみあるべきだということではありませんでした。ゲームのエラーを処理するbitsquid.seブログには、3つのシリーズの素晴らしい記事があります。bitsquid.blogspot.com / 2012/01 /…
Sean Middleditch

回答:


5

OpenGL 4.2仕様のセクション2.11を確認します

個々のシェーダーステージの実行可能コードは、そのステージの現在のプログラムから取得されます。UseProgramによって確立された現在のプログラムオブジェクトがある場合、そのプログラムはすべてのステージで最新と見なされます。それ以外の場合、バインドされたプログラムパイプラインオブジェクトがある場合(セクション2.11.4を参照)、パイプラインオブジェクトの適切なステージにバインドされたプログラムは最新と見なされます。現在のプログラムオブジェクトまたはバインドされたプログラムパイプラインオブジェクトがない場合、どのステージのプログラムも最新ではありません。ステージの現在のプログラムは、そのステージの実行可能コードが含まれている場合、アクティブと見なされます。それ以外の場合、そのステージではアクティブと見なされるプログラムはありません。頂点シェーダーステージまたはフラグメントシェーダーステージのアクティブなプログラムがない場合、頂点および/またはフラグメント処理の結果は未定義になります。ただし、これはエラーではありません。テッセレーション制御、テッセレーション評価、またはジオメトリシェーダーステージのアクティブなプログラムがない場合、これらのステージは無視されます。

これは、実装ごとに異なる動作をする「未定義の動作」です。

シェーダーが見つからない場合の解決策としては、頂点シェーダーとフラグメントシェーダーの両方をハードコードし、それらを何よりも先にロードしてから、不足しているシェーダーの代わりに使用するのが最善の方法です。そうすれば、私が定義する多くのユニフォーム(変換行列)が引き続き通過し、結果は半分ほどに見えます。たとえば、次はその方法です(C#)。

string defaultVertShaderText = 
    @"#version 120

    attribute vec4 in_vertex;

    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;

    void main()
    {
        gl_Position = projection * view * model * in_vertex;
    }";

string defaultFragShaderText =
    @"#version 120

    void main()
    {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }";

また、デフォルトのテクスチャをハードコーディングすることもお勧めします。


答えてくれてありがとう。そして、私は空のシェーダーを処理する同じ方法を考えていました、それは私がプログラムマネージャーレベルでそれを行うだけです(プログラムが間違っている場合、デフォルトプログラムを使用します)。コンパイルの段階でうまくいくよ。再度、感謝します。
dreta、2012年

@Robert:-1:このような文字列の配列をOpenGLに渡さないでください。glShaderSourceは配列を取りますが、これはその機能の使用方法ではありません。各文字列は、個別の行であることを意味していません
Nicol Bolas 2013

@NicolBolasこれは、C#のゲームでこれを行う方法です。OpenTKは、通常のGL呼び出しのオーバーロードを提供して、自然に予想される方法でC#型とやり取りします。私がテストした限り(ATI、AMD、NVIDIA、Intel、Apple、およびWindows、Linux、OS X間のMesa)、シェーダーはコンパイル、リンク、およびエラーなしで適切に動作します。あなたが望むなら、私は「ここに私がそれをやる方法があります(C#)」を削除し、同じことのためにC sytnaxで置き換えることができると思います。
Robert Rouhani 2013

@RobertRouhani:これは「C構文」とは関係ありません。アレイを構築しているという事実についてです。文字列の配列(または1つの文字列の配列)ではなく、単一の文字列である必要があります。はい、それは「コンパイル、リンク、および適切にエラーなしで動作」します。しかしglShaderSource、文字列の配列をとるという事実を使用するのは依然として間違った方法です。
Nicol Bolas 2013

2
@RobertRouhani:配列の目的ではないので間違っています。相互に参照し合う部分からコンパイルされたシェーダーを効果的に構築できるように、文字列の配列を取ります。また、シェーダーのヘッダープレフィックスをまとめて、を使用して異なるバージョンで動作できるようにし#ifdefます。それはだではない、あなたが別の文字列として各行を送ることができるようにそこに。はい、機能しますが、恐ろしいコーディングスタイルです。これは、各行を個別に #includeして.cppファイルを作成するようなものです。はい、コンパイルされますが、#includeを使用する方法ではありません。
Nicol Bolas 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.