Bei zwei Spielern tritt bei meinem Spiel ein Problem auf, bei dem der Bildschirm bei Verwendung eines Fragment-Shaders reißt. Dies scheint jedoch nur für Spieler mit einer R9 380-GPU der Fall zu sein. So sieht es im Spiel aus:
Nachdem ich mit einem der Spieler gearbeitet hatte, beschränkte ich mich auf die Verwendung des Shaders, aber es könnte etwas sein, das im aufrufenden Code nicht richtig gemacht wurde. So sieht der Shader aus (beachten Sie, dass ich noch GLSL lerne).
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;
}
}
Hier ist der Backend-Code (c ++) mit SFML.
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);
Gibt es hier etwas Offensichtliches, das mir fehlt, was ich nicht tun sollte? Kennt jemand Probleme mit R9 380-Treibern? Wenn ich mir das Zerreißen anschaue, würde ich vermuten, dass wir falsch von der Zieltextur abtasten, aber ich verstehe nicht, wie oder warum.
Antworten:
Ich bin heute darauf zurückgekommen und nach einigen weiteren Untersuchungen und Versuchen habe ich festgestellt, dass der Schuldige targetTexture war. Mit einigen weiteren Untersuchungen habe ich gelernt, dass das Lesen und Schreiben in derselben Textur in einem Shader eine schlechte Praxis ist (nicht überraschend) und undefiniertes Verhalten auf GPUs verursacht.
Die Lösung bestand darin, die Zieltextur in eine neue Textur zu kopieren und dann aus der Kopie zu lesen, während noch auf die ursprüngliche Zieltextur geschrieben wurde.
quelle