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

Author Topic: Gradient banding  (Read 17608 times)

0 Members and 2 Guests are viewing this topic.

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Gradient banding
« on: January 15, 2012, 11:51:13 pm »
Hi all,

I'm attempting to draw a screen sized rectangle with a gradient that travels vertically. However, some banding is occurring, as seen below. Has anyone encountered this issue or knows how to deal with it. (I also seem to recall it happening when I did it in pure glsl.)

I've got a feeling its the OpenGL settings, but its not clear if I can change these for the core SFML drawing routines..

Code: [Select]

sf::VertexArray skyShape(sf::Quads, 4);
skyShape[0].Position = sf::Vector2f(0, h);
skyShape[0].Color = horizonColour;
skyShape[1].Position = sf::Vector2f(w, h);
skyShape[1].Color = horizonColour;
skyShape[2].Position = sf::Vector2f(w, 0);
skyShape[2].Color = zenithColour;
skyShape[3].Position = sf::Vector2f(0, 0);
skyShape[3].Color = zenithColour;
target->Draw(skyShape);



dydya-stepa

  • Jr. Member
  • **
  • Posts: 82
    • View Profile
Gradient banding
« Reply #1 on: January 16, 2012, 03:19:54 pm »
i see this with a shader - i'd like to know the answer by myself.

http://www.sfml-dev.org/forum/viewtopic.php?t=6628

It's time for SFML gurus maybe to unite and give us the answer ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Gradient banding
« Reply #2 on: January 16, 2012, 03:35:22 pm »
Quote
However, some banding is occurring

I checked your screenshot with an image editor, and each new line of pixels has an increased level of grey, as expected. There's no problem at all.
Laurent Gomila - SFML developer

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Gradient banding
« Reply #3 on: January 16, 2012, 05:55:43 pm »
Looks perfectly fine for me, too. Are you sure your desktop or your program aren't running in 16 bit colors for whatever reason?

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Gradient banding
« Reply #4 on: January 16, 2012, 06:07:27 pm »
My screen does this. Maybe it's the same for you?

dydya-stepa

  • Jr. Member
  • **
  • Posts: 82
    • View Profile
Gradient banding
« Reply #5 on: January 16, 2012, 09:24:18 pm »
has anyone checked my shader? try not pure colors - say 0.0, 0.5, 1.0 and 0.5, 1.0, 0.0

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Gradient banding
« Reply #6 on: January 16, 2012, 09:37:04 pm »
Haha, whoops. I should of checked the image values more closely I guess.
My desktop is 32bit, though I do have it at low contrast and brightness.

The GIMP gradient looks much smoother, so for comparison I did a gradient fill with GIMP (right) and then ramped up the contrast. The GIMP gradient has a bit of noise, so I might have to write a shader that does something similar.



Anyway, thanks for the replies!

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Gradient banding
« Reply #7 on: January 16, 2012, 09:49:52 pm »
Ha, GIMP dithers the gradient by default. Disabling it reveals the same banding as the other one. :|

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Gradient banding
« Reply #8 on: January 17, 2012, 12:17:18 am »
For those interested, I've solved my banding issue by adding some random dithering. The picture shows the extreme case of black to white. In my game I'm using much more subtler gradients; however the banding was still visible, but now looks good. :)



The method was trivial:
1. Make a 2048x2048 sf::Image and fill with random noise
2. In the gradient shader, use the random texture to perturb the y value of the lookup coord


setup ..
Code: [Select]

sf::Image randomImage;
randomImage.Create(2048,2048);
for(int x=0;x<2048;x++){
  for(int y=0;y<2048;y++){
      randomImage.SetPixel(x,y,sf::Color(random(255),random(255),random(255)));
  }
}
mRandomnessTexture = make_shared<sf::Texture>();
mRandomnessTexture->LoadFromImage(randomImage);
mRandomnessTexture->SetRepeated(false); // clamp to border pixels

// load mSkyGradientShader


rendering ..
Code: [Select]

if (mAllowShaders){
// Shader version
mSkyGradientShader->SetParameter("windowSize",TARGET_WIDTH,TARGET_HEIGHT);
mSkyGradientShader->SetParameter("horizonColour",horizonColour);
mSkyGradientShader->SetParameter("zenithColour",zenithColour);
mSkyGradientShader->SetParameter("randomTexture",*mRandomnessTexture);

const sf::RectangleShape bigRect(sf::Vector2f(TARGET_WIDTH,TARGET_HEIGHT));
target->Draw(bigRect,sf::RenderStates(mSkyGradientShader.get()));
}


shader ..

Code: [Select]

#version 120
uniform vec2 windowSize;
uniform vec4 horizonColour; // nB: colours must be vec4's for sfml's api
uniform vec4 zenithColour;
uniform sampler2D randomTexture;

void main(void)
{
const float MAX_PIXEL_MIX = 4; // how many pixels away can we mix
vec2 normalisedFragCoord = gl_FragCoord.xy/windowSize;
float inverseHeight = 1.0/windowSize.y;
// perturb the coordinate in y direction by a random amount
float randomValue = texture2D(randomTexture, normalisedFragCoord).r;
float perturbedFragCoordY = normalisedFragCoord.y + randomValue*inverseHeight*MAX_PIXEL_MIX;
gl_FragColor = mix(horizonColour,zenithColour,perturbedFragCoordY);
}


Also, I'd like to say that you've seemed to make some nice choices in the graphics API laurent, it's really growing on me. :)

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Gradient banding
« Reply #9 on: January 17, 2012, 07:08:17 am »
And here's the dithered sky in action...


model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
Gradient banding
« Reply #10 on: January 24, 2012, 04:35:27 pm »
Wow, neat trick - works really well!