PowerVRGPUのGLSLコンパイルの最適化に関連していると思われる問題が発生しました。AdrenoおよびTegraGPUでは、フラグメントシェーダーは問題なく機能しますが、PowerVR(Motorola Droid)では、条件付きステートメントで誤った結果が生成されます。フラグメントシェーダーコードの条件ステートメントを変更することで問題を修正しました。ステートメントreturn
のブロックを呼び出す代わりに、ブロックを追加しました。これで、PowerVRで問題なく動作します。if
else
両方のシェーダーのロジックは完全に同一でgl_FragColor
あり、どちらの場合も設定されます。今後問題を回避できるように、PowerVROpenGLドライバーのこの動作について説明してください。なぜこのように条件文を処理するのですか?
これは、PowerVRGPUで正しく機能しない古いフラグメントシェーダーです。
precision mediump float;
varying vec3 vNormal;
varying vec3 vViewVec;
varying vec2 vTextureCoord;
uniform sampler2D sTexturePumpkin;
void main(void)
{
const float sheen = 0.68;
const float noiseScale = 0.05;
const float furriness = 10.0;
const vec4 lightDir = vec4(0.267260, 0.267260, -0.925820, 0.0);
vec4 color = texture2D(sTexturePumpkin, vTextureCoord/*vec2(0.0,0.0)*/);
if(vTextureCoord.y > 0.7) { // in this case PowerVR displays incorrect color
gl_FragColor = color;
return;
}
float diffuse = 0.5 * (1.0 + dot(vNormal, vec3(lightDir.x, lightDir.y, -lightDir.z)));
float cosView = clamp(dot(normalize(vViewVec), vNormal), 0.0, 1.0);
float shine = pow(1.0 - cosView * cosView, furriness);
gl_FragColor = (color + sheen * shine) * diffuse; // in this case PowerVR works correctly
}
AdrenoとPowerVRGPUの両方で正常に機能する新しいフラグメントシェーダーコード:
precision mediump float;
varying vec3 vNormal;
varying vec3 vViewVec;
varying vec2 vTextureCoord;
uniform sampler2D sTexturePumpkin;
void main(void)
{
const float sheen = 0.68;
const float noiseScale = 0.05;
const float furriness = 10.0;
const vec4 lightDir = vec4(0.267260, 0.267260, -0.925820, 0.0);
vec4 color = texture2D(sTexturePumpkin, vTextureCoord/*vec2(0.0,0.0)*/);
if(vTextureCoord.y > 0.7) {
gl_FragColor = color;
}
else {
float diffuse = 0.5 * (1.0 + dot(vNormal, vec3(lightDir.x, lightDir.y, -lightDir.z)));
float cosView = clamp(dot(normalize(vViewVec), vNormal), 0.0, 1.0);
float shine = pow(1.0 - cosView * cosView, furriness);
gl_FragColor = (color + sheen * shine) * diffuse;
}
}