glslシェーダー(GL 2.0)の厄介なバグをまだ取り除くことができませんでした...この問題の解決策を3週間以上探しましたが、何も見つかりませんでした。グーグルには多くの例と説明がありますが、どれも実際には機能しません。
まず、これが私のfragmentshaderコードです。その後、問題が正確に何であるかを説明します。
//fragmentshader
const int MAX_POINT_LIGHTS = LL.MAX_POINT_LIGHTS;
const int MAX_DIR_LIGHTS = LL.MAX_DIR_LIGHTS;
const int MAX_TEXTURES = LL.MAX_TEXTURES;
//float-precision
precision mediump float;
//varyings
varying vec2 texcoord;
varying vec3 normal;
varying vec3 position;
varying float depth;
//pointlights
uniform float pl_range[MAX_POINT_LIGHTS];
uniform vec3 pl_position[MAX_POINT_LIGHTS];
uniform vec3 pl_color[MAX_POINT_LIGHTS];
uniform vec3 pl_specular[MAX_POINT_LIGHTS];
//dirlights
uniform vec3 dl_direction[MAX_DIR_LIGHTS];
uniform vec3 dl_position[MAX_DIR_LIGHTS];
uniform vec3 dl_color[MAX_DIR_LIGHTS];
uniform vec3 dl_specular[MAX_POINT_LIGHTS];
//cameras
uniform vec3 camera;
//fog
uniform vec4 uVecFog;
uniform float uFogNear;
uniform float uFogFar;
//material
uniform vec3 mat_diff;
uniform vec3 mat_spec;
uniform float mat_shine;
uniform float mat_elum;
//texture
uniform sampler2D uTexture;
//ambientlight
vec4 ambient = vec4(0.0,0.0,0.0,0.0);
void main() {
vec3 N = normalize(normal);
vec3 V = normalize(camera - position);
vec4 diff = vec4(0.0,0.0,0.0,0.0);
vec4 spec = vec4(0.0,0.0,0.0,0.0);
//dirlights
for(int i=0;i<MAX_DIR_LIGHTS;i++) {
vec3 L = -normalize(dl_direction[i]);
vec3 R = -normalize(reflect(L,N));
float RV = max(dot(R,V),0.0);
float S = pow(max(dot(R,V),0.0),mat_shine);
float F = clamp(dot(L,N),0.0,1.0);
diff += vec4(F * mat_diff * dl_color[i],1.0);
spec = vec4(S * mat_spec * dl_specular[i],1.0);
}
//pointlights
for(int i=0;i<MAX_POINT_LIGHTS;i++) {
vec3 L = normalize(pl_position[i] - position);
vec3 R = -normalize(reflect(L,N));
float D = distance(pl_position[i],position);
float DF = clamp(1.0 - D/pl_range[i],0.0,1.0);
float S = pow(max(dot(R,V),0.0),mat_shine);
float F = clamp(DF * max(dot(L,N),0.0),0.0,1.0);
diff += vec4(F * mat_diff * pl_color[i],1.0);
spec += vec4(DF * S * mat_spec * pl_specular[i],1.0);
}
//fog
float fogDensity = 0.0;
if (depth > uFogFar) {
fogDensity = 1.0;
} else if(depth > uFogNear) {
float newDepth = depth-uFogNear;
fogDensity = newDepth/(uFogFar-uFogNear);
} else if (depth < uFogNear) {
fogDensity = 0.0;
}
vec4 vecFog = uVecFog * fogDensity;
//texturecolor
vec4 colortex = texture2D(uTexture,vec2(texcoord.x,-texcoord.y));
//final fragmentcolor
gl_FragColor = mix((ambient + colortex * (diff + vec4(mat_diff * mat_elum,1.0)) + spec),vecFog,fogDensity);
}
次の変数値があります。ここで、
- pl_はpointlightvaluesであり、
- dl_は方向性のある光の値であり、
- mat_diffは、マテリアルの拡散値です。
- また、mat_spec、mat_elum、mat_shineは、マテリアルスペキュラー、エリミネーション、シャイニーネス用です。
- N =通常、
- V =ビュー-ベクトルから頂点、
- L =光-ベクトルから頂点、
- R =反射ベクトル、
- D =光距離、
- DF =光をブレンドするための距離係数、
- S =計算された鏡面反射率、
- F = L、Nからの内積
- およびdiff、計算されたdiffuse/spec-vectorsのspecvectorsum。
ここで、次の問題が発生します。ポイントライト自体が完全に実行されます。ディレクショナルライト自体も完璧に動作します。しかし、一緒にそれらはあまりうまく機能しません。問題を正確に説明します。最大で4つのポイントライトと4つのディレクショナルライトがあります。テストには、4つのポイントライトと1つのディレクショナルライトを使用しました。
- forループの計算で指向性ライトをコメントアウトすると、次の結果が得られます。
- ポイントライトのforループをコメントアウトすると、次の結果が得られます。
- 両方のforループを有効にした場合、次のようになります。
指向性ライトは完全に無視されているようです。代わりに、車はポイントライトだけで照らされます。
だから、私が見つけたもの:forループ、ポイントライト->指向性ライトの順序を、dirlights->ポイントライトの代わりに変更すると、効果が入れ替わります:ポイントライトは無視され、指向性ライトが計算されます。
私もわかったことですが、この問題は次の問題である必要があります:pow()関数またはゼロ除算ですが、次のコード行をコメントアウトすると、次のようになります。
spec = vec4(S * mat_spec * dl_specular[i],1.0);
spec += vec4(DF * S * mat_spec * pl_specular[i],1.0);
私は次の結果を得ることができます:
->拡散色は、ポイントライトと指向性ライトに対して通常どおり計算されます。
そこで、この問題を解決する方法を考えました。なぜなら、0を0で表すと、数学エラーが発生するからです。ゼロ除算も....未定義の値を回避するにはどうすればよいですか?
isnan()またはisinf()関数はandroid-glslに存在しないようです。
アンディの解決策または私がもっとうまくできることを教えてください、これはうまくいくでしょうか?少しでもお役に立てれば幸いです。これは私を3週間から怒らせます。ヘルパーに感謝します!:)
コードの詳細: https ://github.com/Chrise55/Llama3D
クリス