3

だから私はC ++で(将来的にゲームを学び、作成するために)プロジェクトに取り組んでおり、レンダリングのためにOpenGL 3.3を選択しました。デフォルトの新しいアプリを開き、すべてがうまくいったので、プロセッサーに組み込まれた Intel HD 4000 に取り組んできました。しかし、その後、2番目のGPUであるnVidia GTX660mで開こうとしましたが、これははるかに高速であり、より多くのFPSが期待されていました。しかし、いいえ、何十ものバグがあっただけではありません(たとえば、フラグメントシェーダーで色としてvec3を出力した場合、Intelは問題ありませんでしたが、vec4を出力しなかった場合、nVidiaは完全にクレイジーなスタイルになりました...)。もちろん、コンパイル時にエラーが発生するわけではないので、修正するのは非常に困難です...

しかし今、私はそれのほとんどを修正したとき、私が望むように修正できない1つの問題に苦労しています(いくつかの汚い方法があるかもしれませんが...それはポイントではありません)。

簡単に言えば、両方の GPU で有効な深度マップを生成しますが、nVidia GPU ではグレースケールではなく、バーの赤から黒へのスケールです。同じ API!)。そのため、私のフラグメント シェーダーはそれに追いつかない可能性が高く、nVidia では、照らされた領域と完全に暗い領域を検出しません (少なくともスポットライトでは、ディレクショナル ライトは機能しません)。

写真: Intel HD4000 を使用した場合の画像 (i5 ivy-bridge cpu から取得) RMB メニューからアプリを実行し、nVidia GTX660m を使用した場合のイメージ。 ソフト シャドウなし

重要 - GTX660m の深度マップは、Intel GPU のようなグレースケールではなく、redToBlack スケールであることに注意してください。上はディレクショナル ライト、下はもちろんポイント ライトです。

マイ FragmentShader: #version 330 コア

in vec2 UV;                         //Coords for standard texture (model)
in vec4 ShadowCoord;                //Coords for directional light (pos)
in vec4 POVShadowCoord;             //Coords for spot light (flashlight) (pos)

out vec4 color;                     //Output color

uniform sampler2D myTextureSampler; //Standard texture with data for models
uniform sampler2D shadowMap;        //Shadowmap for directional light
uniform sampler2D POVshadowMap;     //Shadowmap for spot light (flashlight)

void main(){
    vec3 tex_data = texture2D( myTextureSampler, UV ).rgb;

    float bias = 0.005;
    float visibility = 0.7;
    float decrease = 0.002;

    int early_bailing = 0;
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(0,0)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(-2,-2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(-2, 2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2( 2,-2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if ( texture2D( shadowMap, ShadowCoord.xy + vec2( 2, 2)/1850.0 ).z  <  ShadowCoord.z-bias ) {
        visibility -= decrease; early_bailing++;
    }
    if(early_bailing < 5) {
        if(early_bailing > 0) {
            for (int i=-2; i < 2; i++) {
                for(int j = -2; j < 2; j++) {
                    if(i ==  0 && j ==  0) continue;
                    if(i == -2 && j == -2) continue;
                    if ( texture2D( shadowMap, ShadowCoord.xy + vec2(i,j)/850.0 ).z  <  ShadowCoord.z-bias )
                        visibility -= decrease;
                }
            }
        }
    } else {
        visibility -= 14 * decrease;
    }

    float x = POVShadowCoord.x/POVShadowCoord.w;
    float y = POVShadowCoord.y/POVShadowCoord.w;
    bias = 0.0004;
    if(x < 0 || x > 1 || y < 0 || y > 1) {
        visibility -= 0.6;
    } else {
        float min_visibility = visibility - 0.6;
        if ( textureProj( POVshadowMap, POVShadowCoord.xyw).z < (POVShadowCoord.z - bias)/POVShadowCoord.w) {
            visibility = min_visibility;
        } else {
            //Flashlight effect
            float dx = 0.5 - x;
            float dy = 0.5 - y;
            visibility -= sqrt(dx*dx + dy*dy);
            if(visibility < min_visibility)
                visibility = min_visibility;
        }
    }

    color = vec4(visibility * tex_data, 1);
}

最初の部分はディレクショナル ライト用です - 5 つのポイントで深度マップを事前にサンプリングします。すべてが同じである場合は、それ以上サンプリングしません (早期ベイリング - パフォーマンスの最適化が大幅に向上します!)。または、一部が異なる場合は、すべてをサンプリングし、現在のフラグメントの影の強度を計算します。 .

2 番目の部分は、ポイント ライトの深度マップから単純にサンプリングしたものです。次に、レイの中心からの距離をチェックして、懐中電灯の効果 (中心が強い) をシミュレートします。

これ以上何も必要ないと思いますが、必要な場合は書いてください。必要なコードを投稿します。

また、シャドウマップの精度は 16 ビットのみ (GL_DEPTH_COMPONENT16) です。Intel HD4000 は私の GTX660m よりも高速です (これはより強力です)。これは非常に奇妙です。ハイポリを描いていないからだと思いますが、非常にローポリが多いだけです。私は正しいですか?

4

1 に答える 1

1

別のところに答えがあります。将来の参考のために-サンプリング深度マップは、私が持っていた.b(/ .z)ではなく、sample.r(/ sample.x)のような赤チャンネル(または.x値)を使用します。

于 2013-07-19T08:22:48.367 に答える