私のゲームで2人のプレーヤーがフラグメントシェーダーを使用すると画面がちらつくという問題が発生していますが、これはR9 380 GPUを使用するプレーヤーでのみ発生しているようです。これは、ゲームでは次のようになります。
プレーヤーの1つを操作した後、シェーダーを使用するように絞り込みましたが、呼び出し元のコードで適切に行われていない可能性があります。シェーダーは次のようになります(まだGLSLを学習しています)。
uniform sampler2D lightTexture;
uniform sampler2D targetTexture;
uniform sampler2D backgroundTexture;
uniform vec2 tileSize;
vec3 SaturationBrightness(vec3 color, float brt, float sat)
{
// Increase or decrease theese values to adjust r, g and b color channels seperately
const float AvgLumR = 0.5;
const float AvgLumG = 0.5;
const float AvgLumB = 0.5;
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
vec3 brtColor = color * brt;
vec3 intensity = vec3(dot(brtColor, LumCoeff));
vec3 satColor = mix(intensity, brtColor, sat);
return satColor;
}
void main(void)
{
vec2 position;
position.s = gl_TexCoord[0].s;
position.t = gl_TexCoord[0].t;
vec4 lightColor = texture2D(lightTexture, position);
//Return the lighting if the light is pure dark since the tile behind it was not rendered
if (lightColor.r == 0.0 && lightColor.g == 0.0 && lightColor.b == 0.0) {
gl_FragColor = lightColor;
return;
}
//Get the average of the the nearby light
position.t -= tileSize.t;
vec4 lightColorUp = texture2D(lightTexture, position);
position.t += tileSize.t*2.0;
vec4 lightColorDown = texture2D(lightTexture, position);
position -= tileSize;
vec4 lightColorLeft = texture2D(lightTexture, position);
position.s += tileSize.s*2.0;
vec4 lightColorRight = texture2D(lightTexture, position);
position.s += tileSize.s;
vec4 lightColorFarRight = texture2D(lightTexture, position);
position.s -= tileSize.s*4.0;
vec4 lightColorFarLeft = texture2D(lightTexture, position);
position.s += tileSize.s*2.0;
position.t -= tileSize.t*2.0;
vec4 lightColorFarUp = texture2D(lightTexture, position);
position.t += tileSize.t*4.0;
vec4 lightColorFarDown = texture2D(lightTexture, position);
lightColor = lightColorRight + lightColorUp + lightColorDown + lightColorLeft + lightColorFarRight + lightColorFarUp + lightColorFarDown + lightColorFarLeft;
lightColor.r /= 8.0;
lightColor.g /= 8.0;
lightColor.b /= 8.0;
lightColor.a /= 8.0;
//Get the target (foreground) that we apply the light to
vec4 targetColor = texture2D(targetTexture, gl_TexCoord[0].st);
if (targetColor.a == 0.0) {
//Foreground is transparent meaning that we never rendered to it so instead render the background without light
gl_FragColor = texture2D(backgroundTexture, gl_TexCoord[0].st);
} else {
//Apply averaged light to target
gl_FragColor = vec4(SaturationBrightness(lightColor.rgb, 1.15, 1.1), lightColor.a) * targetColor;
}
}
SFMLを使用したバックエンドコード(c ++)を以下に示します。
SpecialRenderTexturePtr targetTexture = boost::static_pointer_cast<SpecialRenderTexture>(target);
targetTexture->display();
m_texture->setView(m_view);
m_texture->clear(Color(0, 0, 0, 255));
m_texture->draw(m_vertices);
m_texture->display();
m_shader.setParameter("lightTexture", m_texture->getTexture());
m_shader.setParameter("targetTexture", targetTexture->getTexture());
m_shader.setParameter("backgroundTexture", m_render->getBackgroundTexture()->getTexture());
Vector tileSize(Sizes::SUBTILE / 2.0 / m_texture->getSize().x, Sizes::SUBTILE / 2.0 / m_texture->getSize().y);
m_shader.setParameter("tileSize", tileSize.toSfml());
sf::Sprite lightSprite(m_texture->getTexture());
Vector viewPosition = m_view.getCenter();
const Vector& viewSize = m_view.getSize();
viewPosition.x = ceil(viewPosition.x - (viewSize.x / 2.0f));
viewPosition.y = ceil(viewPosition.y - (viewSize.y / 2.0f));
lightSprite.setPosition(viewPosition.toSfml());
target->draw(lightSprite, &m_shader);
私が行方不明であることを私が見逃していることは明らかです。R9 380ドライバーの問題を知っている人はいますか?私が推測することからの裂け目を見ると、ターゲットテクスチャから誤ってサンプリングしているが、その方法や理由がわかりません。
ウィキペディアから直接:「画面のティアリングは、ビデオディスプレイにおける視覚的なアーティファクトであり、ディスプレイデバイスは単一の画面描画で複数のフレームからの情報を表示します。」Nvidiaドライバーは通常モニターをフレームレートに同期するのに優れているため、これはおそらく友人がAMDベースのgpuを使用しているという事実に基づいています。それほど多くない場合は申し訳ありませんが、AMDアーキテクチャに向けて調査をリダイレクトしてください。
—
Java Man Tea Man
彼らが最新のドライバーを使用していることを確認しましたか?また、これはうまくまとめられた質問ですが、このような特定のデバッグタイプの問題に答えるのはかなり難しいため、運が悪い場合があります。また、ご存知のように、プロファイルにゲームへのリンクを含めることもできます。
—
MichaelHouse
ドットの対角線が画面の中央から右上隅に向かっていることを意味している場合、それは画面のちぎれではありません。ティアリングは、スクリーンショットでキャプチャできるものではありません。
—
ロス・リッジ
その配置から、それは画面全体の三角形のエッジのように見えます。
—
MichaelHouse
ええ、私はこれを何と呼べばいいかわからなかったし、引き裂くことは思いつくことができる最高のものでした。個々のラインについて話している。テクスチャから正しくサンプリングされていないようです。どうしてそうなるのかわかりません。私はリードに感謝し、もっと提案してください。乾杯!(更新されたプロファイル)
—
jmcmorris 2016