Problem with glBlendFunc!!

Hi everybody. I’ve got a problem with
glBlendFunc( GL_SRC_ALPHA_SATURATE, GL_ONE )
which I need to use for polygon antialiasing. When I use it, NOTHING is displayed!

The following initialisation lets me draw things happily:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 1.0f, 0.0, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glBegin(GL_LINES);
glColor4f(0.0f,0.0f,0.0f,1.0f);
glVertex3f(0.0f,0.0f,0.0f);
glVertex3f(1.0f,1.0f,0.0f);
glEnd();

But when I replace the glBlendFunc statement with
glBlendFunc( GL_SRC_ALPHA_SATURATE, GL_ONE );
I get NOTHING but a white background! The line isn’t drawn. What’s going on? I’ve tried playing around with alpha values of various things, to no avail. I need to use the GL_SRC_ALPHA_SATURATE blending function for polygon antialiasing.

Thanks,
Jamie.

I don’t know what is the difference with GL_SRC_ALPHA_SATURATE and GL_SRC_ALPHA but even if you set blend function like this:

glBlendFunc( GL_SRC_ALPHA, GL_ONE );

you would see nothing.

With GL_ONE you take the destination color (white background) as it is. Then you add the line color (black) modulated with its alpha value. So you are adding a color to a white color and because you are already at saturation, you would see white whatsoever the line color you set.

In the first case, you saw the line, because the white background is also modulated by the line alpha value.

Thanks, dletozeun, that makes sense. So what blending function should I choose if I want to have a white background? I want the edges of my polygons to be antialiased.

It seems that
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
should do what I want, and it lets me actually see things that I’m drawing — but polygons aren’t antialiasing! Blast. I’m sure I’ve enabled everything I should have.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glDisable( GL_DEPTH_TEST );
glHint(GL_POLYGON_SMOOTH, GL_NICEST);
glEnable(GL_POLYGON_SMOOTH);

I’m using Visual C++ 6.0. Is it possible that polygon antialiasing isn’t supported by the library?

Sorry I don’t know how to do anti-aliasing… you should ask someone else or read more about that.

As far as I know, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); won’t help you for anti-aliasing or at least, it is more complicated. This just set a transparency effect.

For instance, if you have a red quad in front of a green one, and the red quad is transparent with a alpha value of 0.7, then the final color will be: 0.7 * (1,0,0) + 0.3 * (0,1,0) at every pixels where both quads are visibles. So this as nothing to do with antialiasing.

POLYGON_SMOOTH is not supported by some recent hardware. The IHV’s want you to use multisampling instead.

POLYGON_SMOOTH is not supported? That’s pretty bad. What about running legacy stuff?

I have switched to white polygons on a black background, and am using
glBlendFunc( GL_SRC_ALPHA_SATURATE, GL_ONE );
which is the one that should work for polygon antialiasing.

But my polygons are still not antialiasing! This is really very irritating…

polygon-smooth is supported with fallback to software. And is as ugly as it has always been.

instead, I developed a bit straight-forward thing, that is accelerated at least on nVidia cards: use 2px wide lines, and wireframe mode to draw smooth edges.


glEnable(GL_CULL_FACE);
//--[ draw model ]---------[
SHADER::SetShader(1);
RenderModel(xm);
//-------------------------/

glLineWidth(2);
glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 
glDepthMask(false);
glPolygonMode(GL_FRONT,GL_LINE);

SHADER::SetShader(31);
RenderModel(xm);

glDepthMask(true);
glDisable(GL_BLEND);
glPolygonMode(GL_FRONT,GL_FILL);

The usual shader, used to draw the object normally is:


#include "system.h"
varying vec2 texcoord0 : TEX0;

#if IS_VERTEX
void main(){
	texcoord0=gl_MultiTexCoord0.xy;
	gl_Position=ftransform();
}
#endif


#if IS_FRAGMENT

uniform sampler2D tex0 : TEXUNIT0;
void main(){
	gl_FragColor = texture2D(tex0,texcoord0);
}
#endif

The shader “31”, used to draw the lines, is:


#include "system.h"
varying vec2 texcoord0 : TEX0;
varying vec4 posix : TEX1;

#if IS_VERTEX
void main(){
	texcoord0=gl_MultiTexCoord0.xy;
	posix = ftransform();
	gl_Position=posix;
	gl_Position.w+=0.001;
}
#endif



#if IS_FRAGMENT


 
uniform sampler2D tex0 : TEXUNIT0;
void main(){
	vec4 FinalColor = texture2D(tex0,texcoord0);

	

	vec2 ScreenSizeHalf = vec2(1280/2,720/2);
	vec2 posix1= (posix.xy/posix.w+1)*ScreenSizeHalf;
	vec2 fpos = gl_FragCoord.xy;
	float dist = distance(fpos,posix1);
	//FinalColor.w = 1-sqrt(sqrt(sqrt(dist)));
	//FinalColor.w = 1-sqrt(sqrt(dist));
	//FinalColor.w = pow(2.0,-1*dist);
	FinalColor.w = 1-dist;
	//FinalColor.w = 1-sqrt(dist);
	
	gl_FragColor = FinalColor;
	
}
#endif

It’s not perfect, but isn’t very slow and produces amazing results. You can selectively add edge-antialiasing on pre-flagged objects, that usually would be edgy stuff (houses, stairs - things with long straight lines).

Ilian, that’s a neat trick! I want polygon antialiasing to get text looking nicer, though, and unfortunately the small size and fine detail of character glyphs probably mean that your method would be unsuitable.

I am still frustrated that I can’t get GL_POLYGON_SMOOTH to work, at least to see what sort of results it gives. Can someone at least confirm that the standard Windows OpenGL implementation should support this, and that even if my graphics card doesn’t support it, it should be rendered in software? Or is it quite likely that what I’m trying to do is impossible?

Also, my application will be often run on low-end laptops; I really can’t rely on any graphics card stuff. Surely this rules out advanced techniques like multisampling?

I tried gl-polygon-smooth with my GF8600, and it doesn’t work. It worked on my previous card, GF7600, with some registry setting present iirc (that unlocked functionality, kept for Quadro) - and using a special blending and depth-test=off mode.

I’ve been searching for a page I’ve seen before, that shows previous generations of cards drawing smooth wide lines, but to no avail.
Oh well, just quantize the FinalColor.w into 4 values (0%, 25%, 75%, 100%), and you get the resulting image previous cards could draw. It’s uglier than basic MSAA4 (where no fancy tricks of sub-pixel position and computation were used). And required obscure blend/depth-test settings, which weren’t nice. (apart from having to Z-sort all polygons)

A suggestion for drawing nice small glyphs is to have cache-textures for glyphs. Render a character into a larger texture (128x128 or 256x256), and scale the data down with filtering to the target-size. Then draw rectangles with that texture. Subpixel-positioning of the rectangles is done by increasing the width and height of rectangle by 1px, btw.

My implementation of line-smoothing will show darker pixels at line endpoints, so it might never be useful for drawing text.