I'm using FLTK 1.3 as base for OpenGL window context creation (Fl_Gl_Window), etc. on Mac OS X 10.9.
The goal is to create some grid with simple primitives on it. I've done some easy stuff with OpenGL in 2D before, but now i'm lost. All rendered as good, as it need to, except edges. They are all so, uhmmm... Edgy, you know.
It's obvious that this objects need some anti-aliasing in any form. Will it be simple vendor-implementation-specific smooth AA or full Multisampling. Problem is i can't turn it on in FLTK. Can't for triangles, but can for lines.
So far, i tried glEnable(GL_POLYGON_SMOOTH), multisampling on window (seems not working), different blending funcs, changing shader models.
Maybe it is because of triangle fan structure of objects? Please help me and thanks to you!
Code used for object:
float object_width = 100;
float object_height = 50;
float object_x = 250;
float object_y = 100;
glColor3f(0, 0, 1);
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i < 30; i++)
glVertex2f(object_x + (object_width / 2) * cosf(i * 12 * DEG2RAD), object_y + (object_height / 2) * sinf(i * 12 * DEG2RAD));
glEnd();
Code on window creation (just mode setting):
mode(FL_RGB | FL_ALPHA | FL_DOUBLE);
Code used on init:
glClearColor(0.9, 0.9, 0.9, 1);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Colored output, but not smooth
//glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA); // All drawn black, no smooth
//glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE); // All drawn black, no smooth either
glEnable(GL_BLEND);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH); // not working???
On different blending modes than GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA getting this picture:
Related
I'm creating a 2D tile based tactical rpg using OpenGL using C++ and I'm having difficulties with layering my tiles/quads. I want to to able to put say a tree textured quad, the image is of the tree with a surrounding transparent alpha layer, on top of an opaque grass textured quad. I need to have the tree appear on top of the grass with the grass showing through the alpha layer of the tree image.
So far I've been messing with glDisable(GL_DEPTH_TEST), glEnable(GL_BLEND), andglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) but with no luck so far. I end up with a tree on a black background, instead of the grass tile. Could someone point me in the right direction?
Below is my render function and initialize function which are probably most relevant.
void View::initialize() {
updateProjection(window);
glDisable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 1.0);
camera = new Camera(Vector3(-1, -3, 25), Vector3(-1, -3, 0), Vector3(0, 1, 0));
loadImages();
initShaders();
//needed for transparency?
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void View::render(World* worldTemp)
{
Matrix4 mvpMatrix, viewMatrix, modelMatrix;
Matrix4 XAxisRotationMatrix, YAxisRotationMatrix, ZAxisRotationMatrix;
input->handleInput(camera, worldTemp->getPlayer());
worldTemp->timerTick();
worldTemp->clearFog();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen and Depth Buffer
XAxisRotationMatrix = Matrix4::IDENTITY;
YAxisRotationMatrix = Matrix4::IDENTITY;
ZAxisRotationMatrix = Matrix4::IDENTITY;
XAxisRotationMatrix.rotate(Vector3(1.0, 0.0, 0.0), XAxisRotationAngle);
YAxisRotationMatrix.rotate(Vector3(0.0, 1.0, 0.0), YAxisRotationAngle);
ZAxisRotationMatrix.rotate(Vector3(0.0, 0.0, 1.0), ZAxisRotationAngle);
viewMatrix = camera->getViewMatrix();
modelMatrix = translationMatrix(Vector3(-4, 2, 0));
mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
//Spit out the map
for (int i = 0; i < 100; i++){
for (int j = 0; j < 100; j++){
for (int t = 0; t < 5; t++){
if (worldTemp->getTile(i, j)->isOccupied() == true) {
if (worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getFog()){
worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getEntityQuad()->render_self(mvpMatrix, true);
}
else{
worldTemp->getTile(i, j)->getOccupyingEntityIndexed(t)->getEntityQuad()->render_self(mvpMatrix);
}
}
}
}
}
//Place the player
worldTemp->getPlayer()->getEntityQuad()->render_self(mvpMatrix);
renderEnemies();
glutSwapBuffers(); //works with GL_DOUBLE. use glFlush(); instead, if using GL_SINGLE
}
Basically, in 2d games layering done via ordering of render calls. If you want layer A on top of layer B, you should render layer B first and then layer A.
blend function that you're using should depend on texture format of images. There are two common formats for alpha:
Pre-multiplied alpha
Straight alpha
More info about this: https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre
opengl es2 premultiplied vs straight alpha + blending
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); is for premultiplied alpha, and it should work well if you use colors as is. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); is for straight alpha.
This question already has answers here:
OpenGL: always same color
(3 answers)
Closed 9 years ago.
I have a weird problem in OpenGL with glColor3f. In the code below, if I change the red value of glColor3f, then the polygon below will turn into that shade of red. However, if I change green or blue, then it somehow doesn't change the color of the polygon, but it changes the color of all the other objects in the game. Basically, only the red value of the function works, and I need the blue and green to work too.
glColor3f(1.0f,1.0f,0.0f);
for(int i = 0; i < totalhumans; i++)
{
if(humans[i].rage)
{
glPushMatrix();
glTranslatef(humans[i].x,humans[i].y,humans[i].depth);
glBegin(GL_QUADS);
glVertex3f(-16.0f,-(humans[i].dimen->bodyh/2)-16,0.0f);
glVertex3f(-16.0f,-(humans[i].dimen->bodyh/2)-8,0.0f);
glVertex3f(16.0f,-(humans[i].dimen->bodyh/2)-8,0.0f);
glVertex3f(16.0f,-(humans[i].dimen->bodyh/2)-16,0.0f);
glEnd();
glPopMatrix();
}
}
This is my initialization code:
void START_GAME()
{
SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER);
Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,2048);
SDL_ShowCursor(SDL_DISABLE);
loadsettings();
if(fullscreen)
{
const SDL_VideoInfo *VideoInfo = SDL_GetVideoInfo();
screen = SDL_SetVideoMode(VideoInfo->current_w, VideoInfo->current_h, 32, SDL_OPENGL|SDL_FULLSCREEN);
}
if(!fullscreen)
{
screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
setvariables();
loadimages();
loadsounds();
SDL_WM_SetCaption("Freshmen Stuffing Boys",NULL);
SDL_WM_SetIcon(badge,NULL);
running = true;
}
EDIT: I found out that for some reason, after disabling GL_TEXTURE_2D, the color I wanted appeared. Can someone explain why that is so?
This question is not a duplicate because 1) my computer is new, and all of it's graphics drivers are new, so it wasn't a gpu problem, and 2) I'm writing the code for the first time, so I have no idea if the code would work on any other computers.
I imagine you have, in other code, enabled texturing. When this polygon is drawn, GL will use the last used texture and texture coordinate (as you haven't told it otherwise), and in your case this is probably a red pixel. As a result, your vertex colour is being modulated by red, resulting in the blue and green values being multiplied by zero.
If you don't want texturing, disable it. If you do want it, set up the right texture and provide texture coordinates.
I'm wondering if it is possible to simulate the effect of looking through the keyhole in OpenGL.
I have my 3D scene drawn but I want to make everythig black everything except a central circle.
I tried this solution but its doing the completely opposite of what I want:
// here i draw my 3D scene
// Begin 2D orthographic mode
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
GLint viewport [4];
glGetIntegerv(GL_VIEWPORT, viewport);
gluOrtho2D(0, viewport[2], viewport[3], 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Here I draw a circle in the center of the screen
float radius=50;
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x, y);
for( int n = 0; n <= 100; ++n )
{
float const t = 2*M_PI*(float)n/(float)100;
glVertex2f(x + sin(t)*r, y + cos(t)*r);
}
glEnd();
// end orthographic 2D mode
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
What I get is a circle drawn in the center, but I would like to obtain its complementary...
Like everything else in OpenGL, there are a few ways to do this. Here are two off the top of my head.
Use a circle texture: (recommended)
Draw the scene.
Switch to an orthographic projection, and draw a quad over the entire screen using a texture which has a white circle at the center. Use the appropriate blending function:
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
/* Draw a full-screen quad with a white circle at the center */
Alternatively, you can use a pixel shader to generate the circular shape.
Use a stencil test: (not recommended, but it may be easier if you don't have textures or shaders)
Clear the stencil buffer, and draw the circle into it.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
/* draw circle */
Enable the stencil test for the remainder of the scene.
glEnable(GL_STENCIL_TEST)
glStencilFunc(GL_EQUAL, 1, 1);
glStencileOp(GL_KEEP, GL_KEEP, GL_KEEP);
/* Draw the scene */
Footnote: I recommend avoiding use of immediate mode at any point in your code, and using arrays instead. This will improve the compatibility, maintainability, readibility, and performance of your code --- a win in all areas.
Making a 2D OpenGL game. When rendering a frame I need to first draw some computed quads geometry and then draw some textured sprites. When the body of my render method only draws the sprites, everything works fine. However, when I try to draw my geometric quads prior to the sprites the texture of the sprite changes to be the color of the last GL.Color3 used previously. How do I tell OpenGL (well, OpenTK) "Ok, we are done drawing geometry and its time to move on to sprites?"
Here is what the render code looks like:
// Let's do some geometry
GL.Begin(BeginMode.Quads);
GL.Color3(_dashboardBGColor); // commenting this out makes my sprites look right
int shakeBuffer = 100;
GL.Vertex2(0 - shakeBuffer, _view.DashboardHeightPixels);
GL.Vertex2(_view.WidthPixelsCount + shakeBuffer, _view.DashboardHeightPixels);
GL.Vertex2(_view.WidthPixelsCount + shakeBuffer, 0 - shakeBuffer);
GL.Vertex2(0 - shakeBuffer, 0 - shakeBuffer);
GL.End();
// lets do some sprites
GL.Begin(BeginMode.Quads);
GL.BindTexture(TextureTarget.Texture2D, _rockTextureId);
float baseX = 200;
float baseY = 200;
GL.TexCoord2(0, 0); GL.Vertex2(baseX, baseY);
GL.TexCoord2(1, 0); GL.Vertex2(baseX + _rockTextureWidth, baseY);
GL.TexCoord2(1, 1); GL.Vertex2(baseX + _rockTextureWidth, baseY - _rockTextureHeight);
GL.TexCoord2(0, 1); GL.Vertex2(baseX, baseY - _rockTextureHeight);
GL.End();
GL.Flush();
SwapBuffers();
The default texture environment mode is GL_MODULATE, which does that, it multiplies the texture color with the vertex color.
A easy solution is to set the vertex color before drawing a textured primitive to 1,1,1,1 with:
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
Another solution is to change the texture environment mode to GL_REPLACE, which makes the texture color replace the vertex color and doesn't have the issue:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
I have a simple particle effect in OpenGL using GL_POINTS. The following is called, being passed particles in order from the particle furthest from the camera first to the one nearest the camera last:
void draw_particle(particle* part) {
/* The following is how the distance is calculated when ordering.
* GLfloat distance = sqrt(pow(get_camera_pos_x() - part->pos_x, 2) + pow(get_camera_pos_y() - part->pos_y, 2) + pow(get_camera_pos_z() - part->pos_z, 2));
*/
static GLfloat quadratic[] = {0.005, 0.01, 1/600.0};
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic);
glPointSize(part->size);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE_ARB);
glEnable(GL_TEXTURE_2D);
glBegin(GL_POINTS);
glColor4f(part->r, part->g, part->b, part->a);
glVertex3f(part->pos_x, part->pos_y, part->pos_z);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_POINT_SPRITE_ARB);
}
However, there is some artifacting when rendering as can be seen in the following effect:artifacted image http://img199.imageshack.us/img199/9574/particleeffect.png
The problems go away if I disable depth testing, but I need the effects to be able to interact with other elements of the scene, appearing in front of and behind elements of the same GL_TRIANGLE_STRIP depending on depth.
If your particules are already sorted you can render like this :
Render particule with GL WRITE DEPTH but no depth testing (I don't remember exactly the constants)
Render the rest of the scene with depth test.
This way you are sure to get scene interaction with nice-looking particules.
Note: Please specify which OpenGL version you use when you post questions. That goes for any API.
When you want to render primitives with alpha blending, you can't have depth writes enabled. You need to draw your blended primitives sorted back-to-front. If you have opaque objects in the scene, render them first, and then draw your transparent primitives in a back-to-front sorted fashion with depth test enabled and depth writes disabled.
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SPRITE);
glEnable(GL_CULL_FACE);
while(1)
{
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_BLEND);
glDepthMask(1);
RenderOpaque();
SortSprites();
glEnable(GL_BLEND);
glDepthMask(0);
DrawSprites();
...
}