The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
I noticed something odd when using RENDER_SCALE_QUALITY of linear or best.
There are certain artifacts that appear on some images and around rendered text.

If you check the screens included here you can see what I mean:

This image uses the best option:

http://i.imgur.com/UCLLJpO.png

In this image you can see at the top of the cloud box there is some extra lines that are not in the actual image.


This image also uses the best option:

http://i.imgur.com/jAUVsvf.png

In this image you can clearly see the corners of the smaller boxes have lines extending off them. Also and the biggest flaw is in the background.
A giant line runs across the image. The background is made of three images (top, middle, and bottom) as the middle portion is an animation that plays. Right where the seams are the line separates the two.

Also there are extra lines around text, for example see the blue line above "large"

Check this image for what it looks like using nearest at the same window size:

http://i.imgur.com/YlNOHJC.png


It seems that some of the image might be clipping and rendered at the top instead. Like it went below its bounds and wrapped around to the top. If you notice the line in the text large seems to be line right up with the bottom of the "G" that's what seems to be happening where all of the text anomaly's are.


I can use nearest neighbor option when rendering on PC and that's fine. But for android I'd like to use best because it looks much better on smaller screens, but when its on a larger screen like a tablet you can clearly see these artifacts.

There is some more artifacts going on that I can only see on tablets where in the corners of rounded images (like that cloud box) there is garbage pixels data and just random colors there. I wasn't able to get a screen shot of this yet.

Is it possible this has to due with the image type I am saving as or maybe another option I am missing?


Also, as a bonus... When trying this app out on a kindle some of the text is mirrored!
Yeah, some, not all of it is... strange... And only on a kindle. I have tested my app on PC, an android phone, and a kindle. The text is fine on the PC and android phone.
ronkrepps


Joined: 25 Aug 2013
Posts: 35
Hmm yeah now that I think about it more the image is wrapping at its edges. You can see the lines on the top of the cloud box are from the bottom of the image, but were rendered above it instead.
Graphic artifacts when using RENDER_SCALE_QUALITY
R Manard
Guest

Hiyya, looks like a mismatch of data exception handled differently on different platforms. Could I see some code that loads and displays the cloud texture and the font? When I get something weird like that I find that my code was good but with a little clarification here or there it starts popping. I'm glad to see you going with png files. I'm in love with png, ttf, ascii and also namespaces, filestreams, stringstreams, bitflags, inheritance, and polymorphism.
 
 
~"In hindsight, I realized I could see into the future. Which is kind of like having
 premonitions of flashbacks." --- Steven Wright ~



On Thu, Jan 23, 2014 at 11:58 AM, ronkrepps wrote:
Quote:
I noticed something odd when using RENDER_SCALE_QUALITY of linear or best.
There are certain artifacts that appear on some images and around rendered text.

If you check the screens included here you can see what I mean:

This image uses the best option:

http://i.imgur.com/UCLLJpO.png

In this image you can see at the top of the cloud box there is some extra lines that are not in the actual image.


This image also uses the best option:

http://i.imgur.com/jAUVsvf.png

In this image you can clearly see the corners of the smaller boxes have lines extending off them. Also and the biggest flaw is in the background.
A giant line runs across the image. The background is made of three images (top, middle, and bottom) as the middle portion is an animation that plays. Right where the seams are the line separates the two.

Also there are extra lines around text, for example see the blue line above "large"

Check this image for what it looks like using nearest at the same window size:

http://i.imgur.com/YlNOHJC.png


It seems that some of the image might be clipping and rendered at the top instead. Like it went below its bounds and wrapped around to the top. If you notice the line in the text large seems to be line right up with the bottom of the "G" that's what seems to be happening where all of the text anomaly's are.


I can use nearest neighbor option when rendering on PC and that's fine. But for android I'd like to use best because it looks much better on smaller screens, but when its on a larger screen like a tablet you can clearly see these artifacts.

There is some more artifacts going on that I can only see on tablets where in the corners of rounded images (like that cloud box) there is garbage pixels data and just random colors there. I wasn't able to get a screen shot of this yet.

Is it possible this has to due with the image type I am saving as or maybe another option I am missing?


Also, as a bonus... When trying this app out on a kindle some of the text is mirrored!
Yeah, some, not all of it is... strange... And only on a kindle. I have tested my app on PC, an android phone, and a kindle. The text is fine on the PC and android phone.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
R Manard wrote:
Hiyya, looks like a mismatch of data exception handled differently on different platforms. Could I see some code that loads and displays the cloud texture and the font? When I get something weird like that I find that my code was good but with a little clarification here or there it starts popping. I'm glad to see you going with png files. I'm in love with png, ttf, ascii and also namespaces, filestreams, stringstreams, bitflags, inheritance, and polymorphism.


To load fonts:

Code:

        TTF_Font* f = LoadFont("SourceSansPro-Regular.ttf", 18);
   if(f == nullptr)
      return false;
   mTextManager->AddFont("Text", f);

   f = LoadFont("SourceSansPro-Regular.ttf", 18);
   if(f == nullptr)
      return false;
   TTF_SetFontOutline(f, 1);
   mTextManager->AddFont("TextOutline", f);


Fonts are added to the text manager which is called every frame to render each text object to the screen:

Code:

void TextManager::Render(int group)
{
   std::vector< Text* >::iterator it;
   SDL_Rect d;

   for (it = mTextObjects.begin(); it != mTextObjects.end(); it++)
   {
      Text* t = (*it);

      if(group == -1 || t->GetGroup() == group )
      {
         //rerender the texture if it has changed
         if(!t->GetOutline())
            t->Render(mRenderer, mFonts.find(t->GetFontName())->second, NULL);
         else
            t->Render(mRenderer, mFonts.find(t->GetFontName())->second, mFonts.find(t->GetOutlineFontName())->second);

         //render the texture to the screen
         SDL_QueryTexture(t->GetTexture(), NULL, NULL, &d.w, &d.h);

         switch (t->GetHorizontalJust())
         {
            case HJ_CENTER:
               t->SetX((mScreenWidth / 2.0f) - (d.w / 2.0f));
               break;

            case HJ_LEFT:
               t->SetX(0);
               break;

            case HJ_RIGHT:
               t->SetX(mScreenWidth - d.w);
               break;

            default:
               d.x = static_cast<int>(t->GetX());
               break;
         }

         switch (t->GetVerticalJust())
         {
            case VJ_CENTER:
               t->SetY((mScreenHeight / 2.0f) - (d.h / 2.0f));
               break;

            case VJ_TOP:
               t->SetY(0);
               break;

            case VJ_BOTTOM:
               t->SetY(mScreenHeight - d.h);
               break;

            default:
               break;
         }
         
         if (t->GetHorizontalAlignment() == HA_LEFT)
            d.x = static_cast<int>(t->GetX());

         else if (t->GetHorizontalAlignment() == HA_CENTER)
            d.x = static_cast<int>(t->GetX() - (d.w / 2.0f));

         else if (t->GetHorizontalAlignment() == HA_RIGHT)
            d.x = static_cast<int>(t->GetX() - d.w);

         d.y = static_cast<int>(t->GetY());

         //Change the alpha if it is fading
         if(t->GetState() == TS_FADE)
            SDL_SetTextureAlphaMod(t->GetTexture(), static_cast<int>((t->GetFadeTimer() / t->GetFadeDuration()) * 255));

         SDL_RenderCopy(mRenderer, t->GetTexture(), NULL, &d);
      }
   }
}


Each text object's stored texture is rendered when the object is created or changed:

Code:

void Text::Render(SDL_Renderer* renderer, TTF_Font* font, TTF_Font* outlineFont)
{
   if (mDirty)
   {
      SDL_DestroyTexture(mTexture);

      if(!mOutline)
         mTexture = RenderText(mText, mColor, font, renderer);

      else
         mTexture = RenderOutlinedText(mText, mColor, mOutlineColor, font, outlineFont, renderer);

      mDirty = false;
   }
}

SDL_Texture* RenderText(const String& message, SDL_Color color, TTF_Font *font, SDL_Renderer* renderer)
{
   //Render the message to an SDL_Surface and create a texture to return
   SDL_Surface *surface = nullptr;
   surface = TTF_RenderText_Blended(font, message.c_str(), color);
   //surface = TTF_RenderText_Solid(font, message.c_str(), color);
   SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
   
   //Clean up unneeded stuff
   SDL_FreeSurface(surface);
 
   return texture;
}

SDL_Texture* RenderOutlinedText(const String& message, SDL_Color color, SDL_Color outlineColor, TTF_Font *font, TTF_Font *outlineFont, SDL_Renderer* renderer)
{
   //Render the message to an SDL_Surface and create a texture to return
   SDL_Surface *bgSurface = TTF_RenderText_Blended(outlineFont, message.c_str(), outlineColor);
   SDL_Surface *fgSurface = TTF_RenderText_Blended(font, message.c_str(), color);
   
   SDL_Rect r = {TTF_GetFontOutline(outlineFont), TTF_GetFontOutline(outlineFont), fgSurface->w, fgSurface->h};

   /* blit text onto its outline */
   SDL_SetSurfaceBlendMode(fgSurface, SDL_BLENDMODE_BLEND);
   SDL_BlitSurface(fgSurface, NULL, bgSurface, &r);

   SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, bgSurface);
 
   //Clean up unneeded stuff
   SDL_FreeSurface(fgSurface);
   SDL_FreeSurface(bgSurface);

   return texture;
}
Graphic artifacts when using RENDER_SCALE_QUALITY
R Manard
Guest

Sorry I thought you had an issue also with font. So the Image texture is the thing in issue. That's the relevant code. I'm seeing so far code that decides on the fly what the dimensions and placements are. Try absolute values for testing. Like maybe a white square with a single pixel width of red border. If you print out the data at each juncture the area of corruption is more easily found also like:
 

 
 
 

#include <iostream>

#include <fstream>

#include <sstream>

ofstream fout("diag_main.txt"); fout << "main >accessed" << endl;

fout << "stuff value:" << stuff << endl; fout.close();

or maybe on the screen like:

stringstream myString;

string stringtime = "";

then later you

myString.str("");//most awesome way to clear a stringstream

myString << textcycles;//int to stringstream

stringtime = "program cycles every hundreth of a second :" + myString.str();//stringstream to string

drawText(stringtime.c_str(), font15, current.w / 2, 500, 0);












 

On Thu, Jan 23, 2014 at 12:00 PM, ronkrepps wrote:
Quote:
Hmm yeah now that I think about it more the image is wrapping at its edges. You can see the lines on the top of the cloud box are from the bottom of the image, but were rendered above it instead.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Graphic artifacts when using RENDER_SCALE_QUALITY
Jonny D


Joined: 12 Sep 2009
Posts: 932
These are actually symptoms of some pretty common OpenGL issues.  I haven't looked into what the GL renderer does for texture env parameters, but perhaps the wrapping could be prevented with something like this: glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );


Jonny D
ronkrepps


Joined: 25 Aug 2013
Posts: 35
It seems it was wrapping around because the first line of pixels of the cloud image was transparent. I removed the transparent line and you can clearly see what is probably the underlying issue here... comparing this image to the first you can see that when I use best it is adding a border to some of the images.

http://i.imgur.com/xj8zAR2.png

The clouds have a dark border (which is actually not in the original image)

Very strange!
Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
R Manard wrote:
Sorry I thought you had an issue also with font. So the Image texture is the thing in issue. That's the relevant code. I'm seeing so far code that decides on the fly what the dimensions and placements are. Try absolute values for testing. Like maybe a white square with a single pixel width of red border. If you print out the data at each juncture the area of corruption is more easily found also like:
 


I'm not sure what I'm attempting to figure out here with your example code. Could you explain?
Graphic artifacts when using RENDER_SCALE_QUALITY
R Manard
Guest

Textures have data that they are composed of. I was illustrated how you could create a text file with this data in it and then put the data in it again at each juncture. Anytime you move the data or change it in anyway you could send it to the file to compare. After that I was showing that you could put it on the screen. Its just general information about troubleshooting . There are many other ways to go about it . On Jan 23, 2014 3:34 PM, "ronkrepps" wrote:
Quote:


R Manard wrote:


Sorry I thought you had an issue also with font. So the Image texture is the thing in issue. That's the relevant code. I'm seeing so far code that decides on the fly what the dimensions and placements are. Try absolute values for testing. Like maybe a white square with a single pixel width of red border. If you print out the data at each juncture the area of corruption is more easily found also like:
 




I'm not sure what I'm attempting to figure out here with your example code. Could you explain?


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

mr_tawan


Joined: 13 Jan 2014
Posts: 161
This is what I think, which could be wrong because I've been away from 3D-things for quite a long time. Feel free to correct me (or even bash me :-) ). I don't have time to prove my hypothesis yet.

Nearest neighborhood technique takes the value from a pixel that is nearest to the target pixel position. The results is quite predictable. Texture filtering in the other hand takes samples/pixels/texels (whatever) from an area around the target pixel to calculate the result pixel. The difference between algorithms is the pattern of the area that pixels are taken from.

When the target pixel is on the edge of the texture, it also take an off-image pixel into the calculation. This off-image pixel might be (0,0,0,0) or even pixels from the other side of the image. It could be anything, based on the OpenGL context I guess. Anyway, if the off-image pixel value is (0,0,0,0), the pixel around the edge would be darken, results in some weird-looking dark color border. Usually these pixels would have lower alpha value, so it should be blended into the background (and does not look as much ugly).

Also if the texture contains transparent area, the pixel closed to that area might be also darken (or even lighten), because usually the artist paint the transparent area black.

So I think, how the filtering works should be taken into consideration when creating the texture, if the texture filtering is used. You might want to paint the transparent area the same color as the edge of opaque area (with alpha = 0). So when the filter works, it uses better color into the algorithm, and results in better image. Also you might want to add 1 pixel-wide transparent border around the picture to prevent off-image sampling.

Again, this might be totally wrong. Try experimenting. And if I'm wrong, I'm sorry for wasting your time!
mr_tawan


Joined: 13 Jan 2014
Posts: 161
Here is more details on texture filtering, from DirectX web site. You may find it interesting.

http://msdn.microsoft.com/en-us/library/windows/desktop/bb206250(v=vs.85).aspx
Graphic artifacts when using RENDER_SCALE_QUALITY
Pallav Nawani


Joined: 19 May 2011
Posts: 122
Location: Dehradun, India
I agree. This most likely the reason for the dark lines.

Solutions: 
(a) Use RENDER_SCALE_QUALITY of 0.
(b) When storing images, create a border around them of 2 pixels. The border is created by taking the last row, column of pixels and duplicating them
(c) Render your scene into a render texture without any scaling. Then you can scale the render texture and copy it to screen. This is usually the best option, if there are no technical issues preventing you from doing this.



On Fri, Jan 24, 2014 at 10:45 PM, mr_tawan wrote:
Quote:
This is what I think, which could be wrong because I've been away from 3D-things for quite a long time. Feel free to correct me (or even bash me ). I don't have time to prove my hypothesis yet.

Nearest neighborhood technique takes the value from a pixel that is nearest to the target pixel position. The results is quite predictable. Texture filtering in the other hand takes samples/pixels/texels (whatever) from an area around the target pixel to calculate the result pixel. The difference between algorithms is the pattern of the area that pixels are taken from.

When the target pixel is on the edge of the texture, it also take an off-image pixel into the calculation. This off-image pixel might be (0,0,0,0) or even pixels from the other side of the image. It could be anything, based on the OpenGL context I guess. Anyway, if the off-image pixel value is (0,0,0,0), the pixel around the edge would be darken, results in some weird-looking dark color border. Usually these pixels would have lower alpha value, so it should be blended into the background (and does not look as much ugly).

Also if the texture contains transparent area, the pixel closed to that area might be also darken (or even lighten), because usually the artist paint the transparent area black.

So I think, how the filtering works should be taken into consideration when creating the texture, if the texture filtering is used. You might want to paint the transparent area the same color as the edge of opaque area (with alpha = 0). So when the filter works, it uses better color into the algorithm, and results in better image. Also you might want to add 1 pixel-wide transparent border around the picture to prevent off-image sampling.

Again, this might be totally wrong. Try experimenting. And if I'm wrong, I'm sorry for wasting your time!


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





--
Pallav Nawani
IronCode Gaming Private Limited
Website: http://www.ironcode.com
Twitter:  http://twitter.com/Ironcode_Gaming
Facebook: http://www.facebook.com/Ironcode.Gaming
Mobile: 9997478768
ronkrepps


Joined: 25 Aug 2013
Posts: 35
Thank you for your suggestions I will be attempting to implement these over the next couple days and I'll let you know what I've found out.
ronkrepps


Joined: 25 Aug 2013
Posts: 35
After some testing, you guys are absolutely right.
All of my base images have transparent borders around them.

When drawn with nearest neighbor scaling they look fine.
When drawn with linear or best the color (even though it's alpha value is set to 0) is drawing no matter what around the border of everything.

I tested this by taking the image making the transparent area a magenta color and setting it's alpha to 0. The image draws with a magenta border when scaled.

There's something I don't understand though. Is it common practice to do like you said and make sure all of the transparent areas are set to a similar color before setting the alpha value to 0? That seems like a lot of extra work that just doesn't make sense.

I'm wondering why these scaling algorithms don't take into account the fact that if it's reached a border of its bounds to just simply not take any other colors into account when blending and just use the ones in the border?


This is what is happening in the TTF library as well, once you've created a text surface and made it into a texture. Anytime it's scaling text - pixels on the extreme edge are wrapping over to the opposite sides.

Some examples: http://i.imgur.com/sF8qHON.png

It seems something would need to be changed in the TTF library to fix this. Has no one else encountered this before?
Graphic artifacts when using RENDER_SCALE_QUALITY
Gerry JJ
Guest

Den 27. jan. 2014 21:42, skrev ronkrepps:
Quote:
When drawn with nearest neighbor scaling they look fine.
When drawn with linear or best the color (even though it's alpha value
is set to 0) is drawing no matter what around the border of everything.

In short, this happens because the transparent pixels still technically
have a color even if you can't see it, so the surrounding pixels are
blended with that color.

Quote:
There's something I don't understand though. Is it common practice to do
like you said and make sure all of the transparent areas are set to a
similar color before setting the alpha value to 0? That seems like a lot
of extra work that just doesn't make sense.

You can also solve it by using premultiplied alpha. When saving (or
loading) your textures, multiply the rgb values by the alpha value for
all the pixels (leave the alpha value as is). When drawing, instead of
"normal" alpha blending, use additive blending. That way, transparent
pixels literally contribute nothing when blended.

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
Alex Szpakowski
Guest

You should use a premultiplied alpha blend mode instead of additive or ’normal’ alpha blending. SDL_Render doesn’t support this directly though. In OpenGL it would be this:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

whereas ‘regular’ post-multiplied alpha blending is this:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);


On Jan 28, 2014, at 5:31 AM, Gerry JJ wrote:

Quote:
When drawing, instead of "normal" alpha blending, use additive blending. That way, transparent pixels literally contribute nothing when blended.

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
Gerry JJ
Guest

Den 28. jan. 2014 10:36, skrev Alex Szpakowski:
Quote:
You should use a premultiplied alpha blend mode instead of additive or ’normal’ alpha blending. SDL_Render doesn’t support this directly though. In OpenGL it would be this:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Oh, I'm sorry! You're right. For some reason I thought that's what SDL's
additive mode did =P

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
mr_tawan


Joined: 13 Jan 2014
Posts: 161
There's one thing I haven't tried.

1. Render text into a texture, with black color (0,0,0).
2. Create another texture, slightly larger than the text texture. render the text texture into this.
3. Render the target color into this texture with blend mode 'SDL_BLENDMODE_ADD'. SDL_FillRect() should do the job.

May be it works, may be not.
Graphic artifacts when using RENDER_SCALE_QUALITY
Sik


Joined: 26 Nov 2011
Posts: 905
Maybe we should add a function to set this?

2014-01-28, Alex Szpakowski:
Quote:
You should use a premultiplied alpha blend mode instead of additive or
’normal’ alpha blending. SDL_Render doesn’t support this directly though. In
OpenGL it would be this:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

whereas ‘regular’ post-multiplied alpha blending is this:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
GL_ONE_MINUS_SRC_ALPHA);


On Jan 28, 2014, at 5:31 AM, Gerry JJ wrote:

Quote:
When drawing, instead of "normal" alpha blending, use additive blending.
That way, transparent pixels literally contribute nothing when blended.

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
Alex Szpakowski
Guest

A whole new function isn’t needed, just a new SDL_BlendMode enum (and implementations in the backends of SDL_Render.)

It should probably be pretty trivial to implement if anyone wants to take a stab at it - although it seems a bit late to add features for 2.0.2 specifically.

On Jan 28, 2014, at 4:18 PM, Sik the hedgehog wrote:

Quote:
Maybe we should add a function to set this?

2014-01-28, Alex Szpakowski:
Quote:
You should use a premultiplied alpha blend mode instead of additive or
’normal’ alpha blending. SDL_Render doesn’t support this directly though. In
OpenGL it would be this:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

whereas ‘regular’ post-multiplied alpha blending is this:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
GL_ONE_MINUS_SRC_ALPHA);


On Jan 28, 2014, at 5:31 AM, Gerry JJ wrote:

Quote:
When drawing, instead of "normal" alpha blending, use additive blending.
That way, transparent pixels literally contribute nothing when blended.

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
Mason Wheeler
Guest

I brought this up several months ago. SDL_BlendMode is defined as a bitmask (values of 1, 2 and 4), but passing the OR of the Blend and Add parameters (3) doesn't work, when it should.


Nothing was done to fix this.


It ought to be redefined as a simple enum, with a value of 3 performing additive blending.


Mason



On Tuesday, January 28, 2014 12:23 PM, Alex Szpakowski wrote:

A whole new function isn’t needed, just a new SDL_BlendMode enum (and implementations in the backends of SDL_Render.)It should probably be pretty trivial to implement if anyone wants to take a stab at it - although it seems a bit late to add features for 2.0.2 specifically.
Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
Alex Szpakowski wrote:
You should use a premultiplied alpha blend mode instead of additive or ’normal’ alpha blending. SDL_Render doesn’t support this directly though. In OpenGL it would be this:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

whereas ‘regular’ post-multiplied alpha blending is this:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);


I have no idea how to make these calls and when I should do it.
Does it need to be done for every texture?
Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
Gerry JJ wrote:
Den 27. jan. 2014 21:42, skrev ronkrepps:
Quote:
When drawn with nearest neighbor scaling they look fine.
When drawn with linear or best the color (even though it's alpha value
is set to 0) is drawing no matter what around the border of everything.

In short, this happens because the transparent pixels still technically
have a color even if you can't see it, so the surrounding pixels are
blended with that color.

Quote:
There's something I don't understand though. Is it common practice to do
like you said and make sure all of the transparent areas are set to a
similar color before setting the alpha value to 0? That seems like a lot
of extra work that just doesn't make sense.

You can also solve it by using premultiplied alpha. When saving (or
loading) your textures, multiply the rgb values by the alpha value for
all the pixels (leave the alpha value as is). When drawing, instead of
"normal" alpha blending, use additive blending. That way, transparent
pixels literally contribute nothing when blended.

-g

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org



How could I save or load the textures as you are suggesting?
ronkrepps


Joined: 25 Aug 2013
Posts: 35
Some additional info...

Here is what I tried and I'm sure I messed this up but...

Changed the SDL_BLENDMODE enum to the following:

Code:
typedef enum
{
    SDL_BLENDMODE_NONE = 0x00000000,     /**< no blending
                                              dstRGBA = srcRGBA */
    SDL_BLENDMODE_BLEND = 0x00000001,    /**< alpha blending
                                              dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
                                              dstA = srcA + (dstA * (1-srcA)) */
    SDL_BLENDMODE_ADD = 0x00000002,      /**< additive blending
                                              dstRGB = (srcRGB * srcA) + dstRGB
                                              dstA = dstA */
    SDL_BLENDMODE_MOD = 0x00000004,       /**< color modulate
                                              dstRGB = srcRGB * dstRGB
                                              dstA = dstA */
   SDL_BLENDMODE_PREMULTIPLIED = 0x00000008  /**< new test mode */

} SDL_BlendMode;


In SDL_render_gl.c changed the switch statement in GL_SetBlendMode() to the following:

Code:
              switch (blendMode) {
        case SDL_BLENDMODE_NONE:
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
            data->glDisable(GL_BLEND);
            break;
        case SDL_BLENDMODE_BLEND:
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            data->glEnable(GL_BLEND);
            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
            break;
        case SDL_BLENDMODE_ADD:
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            data->glEnable(GL_BLEND);
            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
            break;
        case SDL_BLENDMODE_MOD:
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            data->glEnable(GL_BLEND);
            data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
            break;
      case SDL_BLENDMODE_PREMULTIPLIED:
         data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
         data->glEnable(GL_BLEND);
         data->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
         break;
        }



Rebuilt the sdl2 library and using the newly rebuilt lib/dll I added the following code:
Code:

SDL_SetTextureBlendMode(texturefile, SDL_BLENDMODE_PREMULTIPLIED);


I also tried:

Code:
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_PREMULTIPLIED);


After trying these things: nothing changed


Here's what I don't understand. I created the following image:



When I apply no SDL_BLENDMODE flag to the image or when I apply SDL_BLENDMODE_BLEND with the following:
Code:

SDL_SetTextureBlendMode(cloudbox, SDL_BLENDMODE_BLEND);


I get the bordered result:

But when I apply the following flag:

Code:

SDL_SetTextureBlendMode(cloudbox, SDL_BLENDMODE_NONE);


I get the following result:

It's perfect... but how is it even working if the blendmode is set to SDL_BLENDMODE_BLEND how is it drawing the transparent areas correctly? And why is this one image not drawing the dark border?
Graphic artifacts when using RENDER_SCALE_QUALITY
David Olofson
Guest

On Tue, Feb 4, 2014 at 11:44 PM, ronkrepps wrote:
[...]
[...picture with unwanted gray outline...]
[...]

This happens because the combination of blending and magnification
filtering causes the color of the transparent pixels to leak in
through the magnification filter.

To avoid this, you need to have your graphics application save the
color of the transparent pixels - even if they're supposed to be
completely invisible. And of course, for that to work properly, you
need to make sure those pixels actually are the same color as the
pixels around the edge of the object. That is, if you remove the alpha
channel in the application, the transparent areas should become blue,
in this case.

Or, you can add some code to your loader that tries to fix this, but
that's not entirely trivial to do correctly in every case.


--
//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.--- Games, examples, libraries, scripting, sound, music, graphics ---.
| http://consulting.olofson.net http://olofsonarcade.com |
'---------------------------------------------------------------------'
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
David Olofson wrote:


This happens because the combination of blending and magnification
filtering causes the color of the transparent pixels to leak in
through the magnification filter.

To avoid this, you need to have your graphics application save the
color of the transparent pixels - even if they're supposed to be
completely invisible. And of course, for that to work properly, you
need to make sure those pixels actually are the same color as the
pixels around the edge of the object. That is, if you remove the alpha
channel in the application, the transparent areas should become blue,
in this case.

Or, you can add some code to your loader that tries to fix this, but
that's not entirely trivial to do correctly in every case.


Others have told me that I could edit the way I "load" the images and actually premultiply when loading them. This is what I'm trying to figure out. I am using SDL_Image to load the png's but I don't see any way to do it with that library. Instead I may have to use another library that has the premultiply option? I know there is some information about it in the libpng manual but not much. Surely someone has done this before?
mr_tawan


Joined: 13 Jan 2014
Posts: 161
I think pre-multiplyed alpha has nothing to do with scaling artifact. When scaling is performed, additional pixel has to be created using color value from surrounding pixels, and that causes the problem, not just the alpha function or alpha channel whatsoever.
ronkrepps


Joined: 25 Aug 2013
Posts: 35
mr_tawan wrote:
I think pre-multiplyed alpha has nothing to do with scaling artifact. When scaling is performed, additional pixel has to be created using color value from surrounding pixels, and that causes the problem, not just the alpha function or alpha channel whatsoever.

According to some of the info in this thread and a couple others I've read I have to do two things:

1. Load the image with premultiplied alpha
&
2. Render with

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

I'm not sure how to load the image with premultiplied alpha though.
Graphic artifacts when using RENDER_SCALE_QUALITY
David Olofson
Guest

On Wed, Feb 5, 2014 at 5:21 AM, ronkrepps wrote:
[...]
Quote:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

I'm not sure how to load the image with premultiplied alpha though.

Premultiplied alpha is primarily a performance optimization, so you
can use the above instead of this:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

However, it actually does eliminate this artifact as well, because
what you do is mask out the background (the GL_ONE_MINUS_SRC_ALPHA
part), and then apply the texture using additive blending - and adding
black means "no operation!" Most importantly here, this means that
interpolating from any color towards black fades towards "no
operation", rather than towards black.


I don't know if there is any feature to premultiply alpha when
loading. If not, you'll have to process the pixels of the surface
yourself; load as 32 bit RGBA with a specific byte order, multiply R,
G and B with A.

You could probably use SDL to alpha blend the image over a black
background, but you still need the alpha channel for the
GL_ONE_MINUS_SRC_ALPHA part, so I don't think you can avoid some pixel
level coding there.


As to the alternative; full alpha blending, I'm not sure PhotoShop and
other applications actually *can* do the right thing. (I'm seeing a
lot of complaints about this on the 'net.) In GIMP, you can check the
"Save color values from transparent pixels" when exporting to PNG, and
it'll work just fine - provided the original image is correct,
obviously! Usually not a problem, as antialiasing from selections etc
is implemented on the alpha channel, but it's easy to get it wrong
with pixel art, where you basically use alpha as a 1 bit channel. If
you remove the alpha channel in GIMP, you'll see the color information
in those transparent pixels. I'm not sure what PhotoShop does, but
apparently some applications automatically set all zero alpha pixels
to white or black.


--
//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.--- Games, examples, libraries, scripting, sound, music, graphics ---.
| http://consulting.olofson.net http://olofsonarcade.com |
'---------------------------------------------------------------------'
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
Alex Szpakowski
Guest

It’s likely not any kind of meaningful performance optimization at all, on desktop hardware at least.


Premultiplied alpha is generally used for reasons other than performance. Blending correctness (e.g. getting rid of ‘fringes’), better image compression, and advanced blending techniques (going between additive and alpha blending without changing blend modes) are a few reasons.


https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre
http://home.comcast.net/%7Etom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]
http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx
http://blogs.msdn.com/b/shawnhar/archive/2010/04/09/how-shawn-learned-to-stop-worrying-and-love-premultiplied-alpha.aspx
http://blogs.msdn.com/b/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx

On Feb 5, 2014, at 4:47 AM, David Olofson wrote:
Quote:
On Wed, Feb 5, 2014 at 5:21 AM, ronkrepps wrote:
[...]
Quote:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

I'm not sure how to load the image with premultiplied alpha though.

Premultiplied alpha is primarily a performance optimization,
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
David Olofson
Guest

On Wed, Feb 5, 2014 at 9:54 AM, Alex Szpakowski wrote:
Quote:
It's likely not any kind of meaningful performance optimization at all, on
desktop hardware at least.
[...]

True, that aspect is probably completely irrelevant to most of us
these days. It used to matter when you could still find machines and
devices without 3D accelerators. ;-)

I don't think there is such a thing as a not meaningful performance
optimization in an AAA engine though, and I don't think there ever
will be. Hardware gets faster, but people want more out of it - and
now they're selling 4K displays... o.O


--
//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.--- Games, examples, libraries, scripting, sound, music, graphics ---.
| http://consulting.olofson.net http://olofsonarcade.com |
'---------------------------------------------------------------------'
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Graphic artifacts when using RENDER_SCALE_QUALITY
ronkrepps


Joined: 25 Aug 2013
Posts: 35
I guess I just need to understand this on a lower level.
Is it not fixable without using just some SDL code or must it be modified.

I kind of understand what you are saying but I just thought there wouldn't be an issue doing it with just SDL code.
Graphic artifacts when using RENDER_SCALE_QUALITY
David Olofson
Guest

On Wed, Feb 5, 2014 at 7:00 PM, ronkrepps wrote:
Quote:
I guess I just need to understand this on a lower level.
Is it not fixable without using just some SDL code or must it be modified.

Depends on the tools you use. I'm not sure what you're using, but I
know some applications can't get it right. What you need to do it
without post processing tools/code is PNGs with correct color
information in the transparent pixels. Then you should be able to use
"full" alpha blending without getting these artifacts.

If all else fails, you could use GIMP to fix it manually; import the
image, convert alpha to selection, fill with the color of the edge
pixels (provided it's a single color all the way around - or you're in
for some manual work), delete selected area (this is where you get
transparent pixels with the correct color), save as PNG with color
information in transparent pixels.


Quote:
I kind of understand what you are saying but I just thought there wouldn't
be an issue doing it with just SDL code.

One would think so, but these things aren't as trivial as they may
seem at first, and many of the tools we use weren't really designed
for game development and the like in the first place, so there are
almost always glitches at various places in the tool chain...


--
//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.--- Games, examples, libraries, scripting, sound, music, graphics ---.
| http://consulting.olofson.net http://olofsonarcade.com |
'---------------------------------------------------------------------'
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Graphic artifacts when using RENDER_SCALE_QUALITY
R Manard
Guest

I like to "green screen" all of my PNG source stuff as you can see in my code. Also, I don't trust what comes from the file as far as propagation so I also redundantly set the green screen . I like this as A best practice because the green shows up nicely when there are problems and the edges of my black outlined images always turn out better . So this is me, sharing a best practice
mattbentley


Joined: 07 Jul 2013
Posts: 72
where exactly is RENDER_SCALE_QUALITY defined in SDL documentation?
Can't find it.
Graphic artifacts when using RENDER_SCALE_QUALITY
Jonny D


Joined: 12 Sep 2009
Posts: 932
http://wiki.libsdl.org/CategoryHints#Hints



On Sun, Feb 9, 2014 at 5:17 PM, mattbentley wrote:
Quote:
where exactly is RENDER_SCALE_QUALITY defined in SDL documentation?
Can't find it.


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org