у двух игроков возникла проблема с моей игрой, когда экран использует разрыв, когда он использует фрагментный шейдер, но, похоже, он делает это только для игроков с графическим процессором R9 380. Вот как это выглядит в игре:
После работы с одним из игроков я сузил его до использования шейдера, но это может быть что-то неправильно в вызывающем коде. Вот как выглядит шейдер (обратите внимание, я все еще изучаю 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;
}
}
Вот код бэкэнда (c ++) с использованием 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);
Здесь есть что-то очевидное, чего мне не хватает, чего я не должен делать. Кто-нибудь знает какие-либо проблемы с драйверами R9 380? Глядя на разрыв от того, что я предполагаю, это то, что мы неправильно выбираем целевую текстуру, но я не понимаю, как и почему.
Ответы:
Я вернулся к этому сегодня, и после еще нескольких исследований, проб и ошибок я обнаружил, что виновником была targetTexture. Проведя дополнительные исследования, я узнал, что чтение и запись в одну и ту же текстуру в шейдере - это плохая практика (что неудивительно) и приведет к неопределенному поведению на графических процессорах.
Решение состояло в том, чтобы скопировать целевую текстуру в новую текстуру и затем прочитать из копии, продолжая запись в исходную целевую текстуру.
источник