1

私は c++、opengl 4.0、および glsh シェーダー言語を使用しています。

拡散テクスチャとライトマップ テクスチャを正しくブレンドする方法を知りたいです。

部屋があるとしましょう。すべてのオブジェクトには拡散テクスチャとライトマップがあります。gamedev.net や stackoverflow などのすべてのフォーラムで、人々はこれらのテクスチャを乗算する必要があると言っています。ほとんどの場合、良い結果が得られますが、一部のオブジェクトが光源に非常に近い場合があります (たとえば、白い電球)。この近接オブジェクト用の光源は、白いライトマップを生成します。しかし、ディフューズ テクスチャに白いライトマップを乗算すると、元のディフューズ テクスチャ カラーが得られます。

ただし、光源がオブジェクトの近くにある場合は、光の色が支配的である必要があります

つまり、白い強い光が赤い壁の近くにある場合、この壁の一部は赤ではなく白になるはずです。

1 つのライトマップ以上のものが必要だと思います。ライトマップには、光の強度に関する情報がありません。つまり、最も光沢のある色は最大の拡散色です。

たぶん、シャドウマップとライトマップの 2 つのテクスチャが必要ですか? 次に、方程式は次のようになります。

vec3 color = shadowmapColor * diffuseTextureColor + lightmapColor;

それは良いアプローチですか?

4

2 に答える 2

3

一般的に言えば、まだライトマップを使用している場合は、HDR レンダリングも使用していない可能性があります。そしてそれがなければ、あなたが望むものは特に合理的ではありません. ライト マップがライトの強度を HDR 浮動小数点値 (おそらくGL_R11F_G11F_B10FまたはGL_RGBA16F形式) として提供しない限り、これはうまく機能しません。

そしてもちろん、トーン マッピングなど、HDR で行う通常の操作を行う必要があります。

最後に、加法的方程式は意味がありません。ライト マップの色がライトとサーフェス間の拡散相互作用を表す場合、単にライト マップの色を追加しても意味がありません。標準的な拡散照明の方程式は ですC * (dot(N, L) * I * D)。ここIで、 は光の強度、Dは距離減衰係数、Cは拡散色です。ライトマップからの値は、おそらく括弧で囲まれた量です。したがって、追加しても意味がありません。

サーフェスのディフューズ カラーで乗算する必要があります。過剰な明るさは、 の関数としての光の実効強度によるものですD

于 2013-09-04T14:23:40.307 に答える
0

必要なのは、光源から照らされているフラグメントまでの距離 (または、平方距離を保存するために平方距離) です。次に、最も単純なケースでは、ライト マップと光源の寄与の間を線形に補間できます。

距離は、頂点シェーダーの頂点ごとに実行できる単純な計算です。

in      vec4  VertexPosition; // let's assume world space for simplicity
uniform vec4  LightPosisiton; // world-space - might also be part of a uniform block etc.
out     float LightDistance;  // pass the distance to the fragment shader

// other stuff you need here ....

void main()
{
  // do stuff 
  LightDistance = length(VertexPosition - LightPosisiton);
}

フラグメント シェーダーでは、距離を使用して、光源とライトマップの寄与の間の補間係数を計算します。

in      float     LightDistance;
const   float     MAX_DISTANCE = 10.0;
uniform sampler2D LightMap;

// other stuff ...

out vec4 FragColor;

void main()
{
  vec4 LightContribution;
  // calculate illumination (including shadow map evaluation) here
  // store in LightContribution

  vec4 LightMapConstribution = texture(LightMap, /* tex coords here */);

  // The following DistanceFactor will map distances in the range [0, MAX_DISTANCE] to
  // [0,1]. The idea is that at LightDistance >= MAX_DISTANCE, the light source
  // doesn't contribute anymore.
  float DistanceFactor  = min(1.0, LightDistance / MAX_DISTANCE); 

  // linearly interpolat between LightContribution and LightMapConstribution 
  vec4 FinalContribution = mix(LightContribution, LightMapConstribution, DistanceFactor);

  FragColor = WhatEverColor * vec4(FinalContribution.xyz, 1.0);
}

HTH。

編集: Nicol Bolas の発言を考慮に入れるために、LightMap は RGB カラーとしてエンコードされた寄与を格納し、各チャネルの寄与を格納すると仮定します。実際に単色の寄与のみを格納する単一チャネルのライトマップがある場合は、表面の色を使用するか、光源の色を使用するか、光源の寄与を単一のチャネルに減らす必要があります。

EDIT2 : これは数学的には機能しますが、物理的に健全ではありません。少なくとも物理的にもっともらしいものにするために、最終的な寄与を修正する必要があるかもしれません。効果のみを目的とする場合は、結果に満足するまで補正係数をいじることができます。

于 2013-09-04T14:22:30.190 に答える