Color coded picking problem in OpenGL - c++

I am making a game, actually a very basic replica of Minecraft, for a class project of mine. I'm stuck in the picking process right now, which would enable me to destroy and create blocks in the game environment.
I've been trying to use OpenGL's own picking mode without any success, and building my own ray picker using math libraries seems to large a work for a project of this size. So, I've decided to use the color coded picking method, which consists of rendering every pickable object in a different color, then getting the color at the mouse position and using it to identify the picked object.
My current interface is just a 3D rendering of many boxes stacked, creating a terrain-like structure. Since I've done no texture mapping yet, all the boxes are shades of grey (lighting enabled).
Now, time for some actual code:
This is the initialization part, enabling texturing, lighting etc.
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
When a mouse button is clicked, I try to get the color at the mouse cursor's position (always the middle of the window, actually) by:
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DITHER);
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
renderColors();
GLubyte pixels[3];
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, (void *)pixels);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_DITHER);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
Problem is, the disables do not work and I always get the RGB values of different shades of grey in my pixels array.
What could be the problem?

Perhaps you forget to clear the color buffer and disable depth buffer and all your rendered colors are causing Z-Fighting or not rendered at all (if z-test is "less"). Try to add swapbuffers code and see what gets rendered after your ColorRender code.

Related

Is there any way to make front face of gluCylinder() transparent?

I am using gluCylinder() to create a cylinder in openGL and then plotting points inside the cylinder with Depth Test On .
When i see the front view of the cylinder, the points inside the cylinder are obstructed by front face.
To make front face of the cylinder translucent i am using Blending.
I am using below functions.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
But whatever coloring or alpha value i assign to the cylinder the front face is not looking transparent due to its back face.
Tell whether it is possible to do with blending only or else i need to introduce lighting for both the faces of Cylinder.Here it clearly visible the change in the color of front face and back face of cylinder. And the points inside the cylinder are not visible due to being obstructed by front face of cylinder.
You should be able to accomplish this by drawing the cylinder twice, while culling the front faces the first time, and culling the back faces the second time. This way, you can draw the front and back parts differently, e.g. by making the front part transparent.
The code sequence could look like this:
// Draw back part of cylinder, opaque.
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
gluCylinder(...);
// Draw points.
// Draw front part of cylinder, transparent.
glCullFace(GL_BACK);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gluCylinder(...);
glDisable(GL_BLEND);
If I understand you right then no, you can't do it with blending alone.
If the cylinder's normals all point outward then you also won't be able to see the cylinder's internal parts no matter what you do.
I do something similar to show characters behind walls and it goes like this - render your scene normally and save it all to a framebuffer. Then render what you want shown behind with the buffer contents on top, using a custom shader to make a bubble of transparency around the thing you want shown behind.
Not sure if I am explaining it well or not but it unfortunately requires multiple steps to get the results you want.
Your problem is still a bit unclear to me despite the image but I will attempt to answer based on my perception of your issue.
You are drawing a cylinder and have geometry (lines or other models) inside the cylinder. You want the cylinder to look translucent so the inner objects are visible. Here is one way to do it. Assuming your render functions are drawCylinder() and drawPoints().
init()
{
...
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
...
}
drawScene()
{
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
drawCylinder();
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
drawPoints();
}
doing so will make sure that the points are drawn regardless of the cylinder. Try using lower values of alpha for your cylinder color.
Please note this is one way to do it. I suggest using shaders to have more control over blending as well as exploring fragment/pixel discard options.

Drawing a stationary background

In my program, I am trying to use an image and draw it as a stationary background. The foreground does have some models loaded inside a camera and runnig fine.
However, when I apply a background image, the whole model and other objects don't appear and I can only see the background image appearing over the screen.
I did the disable the Depth_Test before drawing the background and then re-enabled it before drawing the model.
glDisbale(GL_DEPTH_TEST);
bgImage.draw(0,0); //draw the background image. Width and height parameters previously while initializing image
glEnable(GL_DEPTH_TEST);
cam.begin();
//stuff drawn inside
cam.end();
Also tried clearing the Depth Buffer/Depth Color bit after the bgImage.draw but nothing changes.
You need to disable depth writes so that the background doesn't hogs the depth buffer.
glDepthMask(GL_FALSE);
background();
glDepthMask(GL_TRUE);
Or you simply clear only the depth buffer after drawing the background:
glDisable(GL_DEPTH_TEST);
background(); // instead of clearing the color
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);

OpenGL: Able to see inside of an object despite the fact that transparency is set to 1.0

I am trying to check transparency and how it works.
I have created a solidsphere and a solidcube in it.
I have enabled
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
The transparency works as expected using color4f.
The problem is that when I am setting the transparency of the sphere to 1.0, the cube still appears.
I am also using these:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearDepth(1);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
How can I make the cube visible only when the transparency of the sphere is != 1.0 ?
Is there a reason you've set glFrontFace(GL_CW); ? The default is GL_CCW, so you'll be culling front faces, and rendering back faces. With the front of the sphere missing, you'll see inside it.
To elaborate:
When rendering translucent objects using a normal (src_alpha , 1-src_alpha) blend, the translucent surfaces need to be rendered in depth order, back to front.
If you render only the back-surfaces of an object, it may (if it's more or less symmetrical) appear normal, but it is in fact inside-out, and thus cannot occlude objects correctly which are actually inside it.
So for this to work, it is important both that the front-surfaces are not culled, and that the opaque or more distant objects are rendered first.
If you want both front and back of the sphere to render translucently, and correctly, you would need to render the back before the front. This could be done with polygon sorting, but for a convex object it would suffice to render it twice, with the backface culling inverted - so render back faces first, and then the front faces, in two seperate passes.

OpenGL non-square textures

I'm a little new to OpenGL. I am making a 2D application, and I defined a Quad class which defines a square with a texture on it. It loads these textures from a texture atlas, and it does this correctly. Everything works with regular textures, and the textures display correctly, but doesn't display correctly when the texture image is not a square.
For example, I want a Quad to have a star texture, and have the star to show up, and the area around the star image that still lies in the Quad to be transparent. But what ends up happening is that the star shows up fine, and then behind it is another texture from my texture atlas that fills the Quad. I assume the texture behind it is just the last texture I loaded into the system? Either way, I don't want that texture to show up.
Here's what I mean. I want the star but not the cloud-ish texture behind it showing up:
The important part of my render function is:
glDisable(GL_CULL_FACE);
glVertexPointer(vertexStride, GL_FLOAT, 0, vertexes);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(colorStride, GL_FLOAT, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, uvCoordinates);
//render
glDrawArrays(renderStyle, 0, vertexCount);
It seems like the obvious choice would be to use an RGBA texture, and make everything but the star transparent by setting the alpha channel to zero for those pixels (and enable alpha blending for the texture unit).
Use an image manipulation program. Photoshop is a great one, gimp is a free one. You don't really use OpenGL to crop your textures. Rather, your textures need to be prepared beforehand for your program.
There should be some sort of very easy tool to remove everything outside of the star. By remove, I mean make it transparent, which will require an alpha channel. This means you need to make sure that the way you load your textures in your program takes into account 32-bit colors (RGBA - red, green, blue, alpha), not just 24-bit colors (RGB - red, green, blue).
This will make everything behind your star see-through, or transparent.
Also, just an afterthought, it looks like you could be taking a copyrighted image off the internet and using it in your game/program. If you're doing anything commercial, I'd strongly recommend creating your own textures.
You want to make a call to glBindTexture(GL_TEXTURE_2D,0); after you have mapped your texture
here is an example from some code ive written
// Bind the texture
glBindTexture(GL_TEXTURE_2D, image.getID());
// Draw a QUAD with setting texture coordinates
glBegin(GL_QUADS);
{
// Top left corner of the texture
glTexCoord2f(0, 0);
glVertex2f(x, y);
// Top right corner of the texture
glTexCoord2f(image.getRelativeWidth(), 0);
glVertex2f(x+image.getImageWidth(), y);
// Bottom right corner of the texture
glTexCoord2f(image.getRelativeWidth(), image.getRelativeHeight());
glVertex2f(x+image.getImageWidth()-20, y+image.getImageHeight());
// Bottom left corner of the texture
glTexCoord2f(0, image.getRelativeHeight());
glVertex2f(x+20, y+image.getImageHeight());
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
I am no expert but this certainly solved what you are experiencing for me.

OpenGL : How can I put the skybox in the infinity

I need to know how can I make the skybox appears as it's in the infinity??
I know that it's something related to depth, but I don't know the exact thing to disable or to enable??
First, turn off depth writes/testing (you don't need to bother with turning off depth testing if you draw the skybox first and clear your depth buffer):
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
Then, move the camera to the origin and rotate it the inverse of the modelview matrix:
// assume we're working with the modelview
glPushMatrix();
// inverseModelView is a 4x4 matrix with no translation and a transposed
// upper 3x3 portion from the regular modelview
glLoadMatrix(&inverseModelView);
Now, draw your sky box and turn depth writes back on:
DrawSkybox();
glPopMatrix();
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
You'll probably want to use glPush/PopAttrib() to ensure your other states get correctly set after you draw the skybox too (make sure to turn off things like lighting or blending if necessary).
You should do this before drawing anything so all color buffer writes happen on top of your sky box.
First, Clear the buffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Then, save your current modelview matrix and load the identity.
glPushMatrix();
glLoadIdentity();
Then render your skybox.
Skybox.render();
Then, clear the depth buffer and continue normally with rendering
glClear(GL_DEPTH_BUFFER_BIT);
OtherStuff.render();
glutSwapBuffers();
The only problem with drawing the sky box is first is that your pixel shader will execute for every pixel in the sky box. Just to be overwritten by other object in your world later on. Your best bet is to render all opaque object first then render your sky box. That way the pixel shader for the sky box only gets executed for the pixel who pass the z buffer test.
There is no infinity. A skybox is just a textured box, with normaly 0,0,0 in the middle.
Here is a short tut: link text
The best approach I can think of is to draw it on a first pass(or layer), then clear only the depth buffer. After that just draw the rest of the scene in another pass. This way the skybox will always remain "behind" the scene. Just remember to use the same camera for both passes and somehow snap the skybox to the camera.