Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [GLSL] Post processing artifacts  (Read 1713 times)

0 Members and 1 Guest are viewing this topic.

jamesk

  • Guest
[GLSL] Post processing artifacts
« on: June 05, 2018, 02:19:03 am »


There are two purple tiles generating heat. The heat shader is working fine but the entire screen now has unwanted artifacts. I've taken the entire windows RenderTexture and applied the shader on a small sub section of the bitmap per tile.

Does anyone recognize these symptoms? Shader and code below:

#version 130

uniform sampler2D currentTexture; // Our render texture
uniform sampler2D distortionMapTexture; // Our heat distortion map texture

uniform float time; // Time used to scroll the distortion map
uniform float distortionFactor; // Factor used to control severity of the effect
uniform float riseFactor; // Factor used to control how fast air rises

uniform float x;
uniform float y;
uniform float w;
uniform float h;

void main()
{
    vec4 alpha = vec4(0.0f,0.0f,0.0f,0.0f);

    vec2 distortionMapCoordinate = gl_TexCoord[0].st;
    //distortionMapCoordinate.y = 1.0f - distortionMapCoordinate.y;

    vec2 size = textureSize(currentTexture,0);
    vec2 screenCoord = vec2(gl_TexCoord[0].s, (1.0f-gl_TexCoord[0].t)) * size;

    if(!(screenCoord.x >= x && screenCoord.x <= x + w && screenCoord.y >= y && screenCoord.y <= y + h)) {
      gl_FragColor = gl_Color * texture2D(currentTexture, gl_TexCoord[0].st);
return;
    } else {
   
    // We use the time value to scroll our distortion texture upwards
    // Since we enabled texture repeating, OpenGL takes care of
    // coordinates that lie outside of [0, 1] by discarding
    // the integer part and keeping the fractional part
    // Basically performing a "floating point modulo 1"
    // 1.1 = 0.1, 2.4 = 0.4, 10.3 = 0.3 etc.
    distortionMapCoordinate.t -= time * riseFactor;
   
    vec4 distortionMapValue = texture2D(distortionMapTexture, distortionMapCoordinate);

    // The values are normalized by OpenGL to lie in the range [0, 1]
    // We want negative offsets too, so we subtract 0.5 and multiply by 2
    // We end up with values in the range [-1, 1]
    vec2 distortionPositionOffset = distortionMapValue.xy;
    distortionPositionOffset -= vec2(0.5f, 0.5f);
    distortionPositionOffset *= 2.f;

    // The factor scales the offset and thus controls the severity
    distortionPositionOffset *= distortionFactor;

    // The latter 2 channels of the texture are unused... be creative
    vec2 distortionUnused = distortionMapValue.zw;

    // Since we all know that hot air rises and cools,
    // the effect loses its severity the higher up we get
    // We use the t (a.k.a. y) texture coordinate of the original texture
    // to tell us how "high up" we are and damp accordingly
    // Remember, OpenGL 0 is at the bottom
    distortionPositionOffset *= ((y+h)-screenCoord.y )/ (y+h);
   
    vec2 distortedTextureCoordinate = gl_TexCoord[0].st + distortionPositionOffset;

    gl_FragColor = gl_Color * texture2D(currentTexture, distortedTextureCoordinate);
  }
}

engine:

/*
      Post processing shaders
    */

    sf::RenderTexture &postprocessing = *ENGINE.GetPostProcessingBuffer();

    sf::Sprite distortionPost;
    distortionPost.setTexture(postprocessing.getTexture());

    heatShader.setUniform("time", totalTime);
    heatShader.setUniform("distortionFactor", 0.1f);
    heatShader.setUniform("riseFactor", 0.2f);

    heatShader.setUniform("w", tile->GetWidth()-8.f);
    heatShader.setUniform("h", tile->GetHeight()-8.f);

    while (field->GetNextTile(tile)) {
      if (tile->GetState() == TileState::PURPLE) {
        heatShader.setUniform("x", tile->getPosition().x+4.f);
        heatShader.setUniform("y", tile->getPosition().y);

        LayeredDrawable* bake = new LayeredDrawable(sf::Sprite(distortionPost));
        bake->SetShader(&heatShader);

        ENGINE.Draw(bake);
        delete bake;
      }
    }

Where post processing buffer is just an sf::RenderTexture I've been baking the scene into. Add the end of the call the window Displays() this texture.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: [GLSL] Post processing artifacts
« Reply #1 on: June 05, 2018, 07:22:58 am »
As not everyone knows your expected behavior, it might be useful to point out what exactly is unwanted in the posted picture. ;)
« Last Edit: June 05, 2018, 03:32:13 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

jamesk

  • Guest
Re: [GLSL] Post processing artifacts
« Reply #2 on: June 05, 2018, 03:12:25 pm »
do you not see the missing sprite chunks at the top and inside the screen? Like things are half-way drawn and then stopped.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: [GLSL] Post processing artifacts
« Reply #3 on: June 05, 2018, 05:55:42 pm »
Well if I don't know what to look for, I also won't know what's intended and what isn't. :D

So what does ENGINE.draw do exactly?

To me, it kind of seems like you maybe using VRAM that is no longer marked as "valid", but I can only guess without a complete and minimal example.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

jamesk

  • Guest
Re: [GLSL] Post processing artifacts
« Reply #4 on: June 06, 2018, 01:32:03 am »
I figured it out. I was using a reference to render texture and drawing to it. I got a copy of RenderTexture's internal Texture by using sf::RenderTexture.getTexture() and drew to that copy before the next loop instead. Must have been drawing to a texture across threads...