Robek layar dalam fragmen shader pada GPU R9 380

8

dua pemain menghadapi masalah dengan permainan saya di mana layar sobek ketika menggunakan fragmen shader tetapi sepertinya hanya melakukan ini untuk pemain dengan GPU R9 380. Berikut ini tampilannya dalam game:

masukkan deskripsi gambar di sini

Setelah bekerja dengan salah satu pemain saya mempersempitnya untuk menggunakan shader tetapi itu bisa menjadi sesuatu yang tidak dilakukan dengan benar dalam kode panggilan. Inilah yang tampak seperti shader (perhatikan saya masih belajar 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;
    }
}

Berikut adalah kode backend (c ++) menggunakan 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);

Apakah ada sesuatu yang jelas di sini yang saya lewatkan yang seharusnya tidak saya lakukan. Adakah yang tahu masalah dengan driver R9 380? Melihat robekan dari apa yang saya duga adalah bahwa kita mengambil sampel dari tekstur target secara tidak benar tetapi saya tidak melihat bagaimana atau mengapa.

jmcmorris
sumber
Langsung dari Wikipedia: "Kerusakan layar adalah artefak visual dalam tampilan video di mana perangkat tampilan menampilkan informasi dari beberapa frame dalam satu gambar layar." Ini kemungkinan besar didasarkan pada kenyataan bahwa teman-teman Anda memiliki GPU berbasis AMD, karena driver Nvidia biasanya pandai menyinkronkan monitor ke frame rate. Maaf jika tidak banyak, tetapi arahkan penelitian Anda ke arsitektur AMD.
Java Man Tea Man
1
Sudahkah Anda memastikan mereka menggunakan driver terbaru? Selain itu, ini adalah pertanyaan yang disatukan dengan baik, tetapi masalah jenis debugging khusus seperti ini cukup sulit untuk dijawab, jadi Anda mungkin tidak beruntung. Selain itu, agar Anda tahu, tidak ada masalah untuk memiliki tautan ke game di profil Anda.
MichaelHouse
1
Jika maksud Anda adalah garis titik-titik diagonal yang bergerak dari tengah layar ke sudut kanan atas, maka itu bukan sobekan layar. Merobek bukanlah sesuatu yang dapat Anda tangkap dalam tangkapan layar.
Ross Ridge
1
Dari penempatannya tampak seperti tepi segitiga seluruh layar.
MichaelHouse
Ya, saya tidak tahu harus memanggil apa dan merobek adalah yang terbaik yang bisa saya dapatkan. Saya berbicara tentang garis individual. Sepertinya itu pengambilan sampel dari tekstur yang salah atau semacamnya. Saya tidak melihat bagaimana itu bisa terjadi. Saya menghargai petunjuk dan merasa bebas untuk menyarankan lebih banyak. Bersulang! (Profil diperbarui)
jmcmorris

Jawaban:

8

Saya kembali ke sini hari ini dan setelah beberapa penyelidikan dan coba-coba lagi saya menemukan bahwa pelakunya adalah targetTexture. Dengan beberapa penyelidikan lebih lanjut saya belajar bahwa membaca dan menulis dengan tekstur yang sama dalam shader adalah praktik yang buruk (tidak mengherankan) dan akan menyebabkan perilaku yang tidak terdefinisi pada GPU.

Solusinya adalah menyalin tekstur target ke tekstur baru dan kemudian membaca dari salinan sambil tetap menulis ke tekstur target asli.

jmcmorris
sumber
1
Itu tidak terdefinisi pada semua GPU.
Andreas