OpenGL C++ Occlusion Query - c++

In Christer Ericson great book on Collision Detection, he gives an accelerated GPU method for detecting collision among convex polygons with the following algorithm.
I'm completely new to OpenGL, and my question is, given two std::vector of Points where:
struct Point{
double x,
double y,
}
How can I pass this std::vector<Point> to the following function and return the result in C++? My vector is a convex polygon order CCW.
// Initialize depth buffer to far Z (1.0)
glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
// Disable color buffer writes
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
// Initialize occlusion queries
Gluint query[1], numSamplesRendered;
glGenQueries(1, query);
// Set pixels to always write depth
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_TRUE);
// Draw front faces of object A
glCullFace(GL_BACK);
RenderObject(A);
// Pass pixels if depth is greater than current depth value
glDepthFunc(GL_GREATER);
// Disable depth buffer updates
glDepthMask(GL_FALSE);
// Render back faces of B with occlusion testing enabled
glBeginQuery(GL_SAMPLES_PASSED, query[0]);
glCullFace(GL_FRONT);
RenderObject(B);
glEndQuery(GL_SAMPLES_PASSED);
// If occlusion test indicates no samples rendered, exit with no collision
glGetQueryObjectuiv(query[0], GL_QUERY_RESULT, &numSamplesRendered);
if (numSamplesRendered == 0) return NO_COLLISION;
// Set pixels to always write depth
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_TRUE);
// Draw front faces of object B
glCullFace(GL_BACK);
RenderObject(B);
// Pass pixels if depth is greater than current depth value
glDepthFunc(GL_GREATER);
// Disable depth buffer updates
glDepthMask(GL_FALSE);
// Render back faces of A with occlusion testing enabled
glBeginQuery(GL_SAMPLES_PASSED, query[0]);
glCullFace(GL_FRONT);
RenderObject(A);
glEndQuery(GL_SAMPLES_PASSED);
// If occlusion test indicates no pixels rendered, exit with no collision
glGetQueryObjectuiv(query[0], GL_QUERY_RESULT, &numSamplesRendered);
if (numSamplesRendered == 0) return NO_COLLISION;
// Objects A and B must be intersecting
return COLLISION;

One possible way :
U need to pass your std::vector<Point> to a function which will update object's (A or B or both) buffers (vertex/index).
Call the function which will do the occlusion query and return result. Probably a boolean in your case

Related

Stop two shadows overlapping using the stencil buffer in OpenGL

I have two planar shadows of the same object coming from the same light source - one that casts on the floor and one to cast on the wall when the object is close enough. Everything works just fine as far as the shadows being cast, I'm using the stencil buffer to make sure that the two shadows only cast on their respective surfaces without being rendered outside of the room.
The problem is that the two stencil buffers bleed into each other, specifically whichever shadow I render second bleeds into the stencil buffer for the first one. I figure it's some issue with the stencil function or something, using the wrong parameters, but I can't seem to figure it out.
// Generate the shadow using a shadow matrix (created using light position and vertices of
// the quad on which the shadow will be projected) and the object I'm making a shadow of
void createShadow(float shadowMat[16])
{
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
// Set the shadow color
glColor3f(0.1, 0.1, 0.1);
glPushMatrix();
// Create the shadow using the matrix and the object casting a shadow
glMultMatrixf((GLfloat*)shadowMat);
translate, rotate etc;
render object;
glPopMatrix();
// Reset values to render the rest of the scene
glColor3f(1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
}
// Set up the stencil buffer and render the shadow to it
void renderShadow(float shadowMat[16], float shadowQuad[12])
{
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glDisable(GL_DEPTH_TEST);
// Create a stencil for the shadow, using the vertices of the plane on which it will
// be projected
glPushMatrix();
translate, rotate etc;
glEnableClientState(GL_VERTEX_ARRAY);
// The shadow quad is the same vertices that I use to make the shadow matrix
glVertexPointer(3, GL_FLOAT, 0, shadowQuad);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Render the shadow to the plane
createShadow(shadowMat);
glDisable(GL_STENCIL_TEST);
}
// In the render function:
Render floor/surrounding area;
Set up light using the same position used to make the shadow matrix;
renderShadow(wallShadowMatrix, wallVertices);
renderShadow(floorShadowMatrix, floorVertices);
Render rest of scene;
If I render the shadows on their own they work as intended, but when I render them together, whichever one rendered second shows up in the stencil of the first shadow.
I've included a few pictures; the first two show the individual Shadow on the wall and Shadow on the floor, and here is the floor shadow rendered after the wall shadow, and vice versa.
Fixed it, I needed to add the following code between the two renderShadow calls in the render function:
glClear(GL_STENCIL_BUFFER_BIT);

OpenGL - depth buffer cuts out faces it shouldn't while rendering semi-transparent cubes [duplicate]

This question already has answers here:
Order of translucent object rendering
(2 answers)
Closed 3 years ago.
i'm fairly new to OpenGL and came across this problem: I am trying to render multiple semi-transparent cubes which are inside of each other and some faces in the back of the cubes just get cut out. It also depends from where im looking inside the cube (see the gif).
https://i.imgur.com/bL4U8BS.gifv
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, transparentTexture);
for (int i = 0; i < CacheSizeInfo.size(); ++i)
{
int totalCacheSize = CacheSizeInfo[i][0]* CacheSizeInfo[i][1]* CacheSizeInfo[i][2];
std::vector<float> Cachecolor = { CacheColorInfo[i][0], CacheColorInfo[i][1], CacheColorInfo[i][2]};
int cacheOffset = (renderIndex / totalCacheSize) * totalCacheSize;
mat4 translationMatrix = glm::translate(mat4(1.0f), modelMatrices[cacheOffset]);
glUniformMatrix4fv(glGetUniformLocation(shaderID, "translation"), 1, GL_FALSE, &translationMatrix[0][0]);
glUniform3fv(glGetUniformLocation(shaderID, "color"), 1, &Cachecolor[0]);
glBindVertexArray(CacheVAOInfo[i]);
glDrawArrays(GL_TRIANGLES, 0, CacheVertexCountInfo[i]);
glBindVertexArray(0);
}
}
mat4 translationMatrix = glm::mat4(1.0f);
glUniformMatrix4fv(glGetUniformLocation(shaderID, "translation"), 1, GL_FALSE, &translationMatrix[0][0]);
glUniform3fv(glGetUniformLocation(shaderID, "color"), 1, &matColor[0]);
glBindVertexArray(VAO_Matrix);
glDrawArrays(GL_TRIANGLES,0, mainMatSize*3);
glBindVertexArray(0);
First I enable the Depth Test and set it to GL_LESS. Then I bind the transparent texture. After that, in the for loop, I render the green matrix and after that, outside of the loop, the white one.
The Depth Test is enabled
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
The geometry is "cut out" because of the depth test. The faces in the back are not drawn, when the faces in the front have been draw before, because the depth test fails and the fragments are discarded.
Disable the depth test to make the faces in the back visible.
But note, Blending depends on the drawing order. You've to render the geometry from the back to the front, so the depth test (GL_LESS) becomes superfluous.

opengl glDepthFunc doesn't work

I'm writing code that display hidden part of the object.
Here is example : the plate is larger polygonal object, and cylinder is smaller polygonal object. cylinder is hidden by plate. (See the lower half window : cylinder penetrates the plate. some part of the cylinder is hidden by plate. )
The image is made by below code.
draw plate (not draw it to RGB buffer. only catch the depth values)
draw cylinder (if depth test 'less' passes : that means visible part of the cylinder (smaller depth) is drawn)
The model is rotated along y axis for each frame. It gives me a correct result for every frame.
Now, I'd like to display hidden part of the cylinder as transparent.
Before using blending, I want to display only the hidden part of the cylinder. That is, I have to display cylinder's region that have more greater depth values than plate's depth. Then, I just change
glDepthFunc(GL_LESS);
to
glDepthFunc(GL_GREATER);
However, If I changed it to GL_GREATER, it does not give me a correct result.
I got correct result at first frame, but after then, the model is gone. (That means, the model is not displayed on window. Both of upper, and lower viewport)
I cannot catch the reason. Help me!
void MyDisplay()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glRotatef(rot, 0, 1, 0);
glViewport(0,0, width, height/2);
glEnable(GL_DEPTH_TEST);
DrawPlate();
glColor4f(0,0,0,1);
DrawCylinder();
glDisable(GL_DEPTH_TEST);
glViewport(0,height/2, width, height/2);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
//glDrawBuffer(GL_NONE); // No color buffers are written
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
DrawPlate();
glDepthFunc(GL_LESS);
// glDepthFunc(GL_GREATER); // doesn't work !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColor4f(0,0,0,0.5f);
DrawCylinder();
delay(1);
glFlush();
glutPostRedisplay();
}
Hey guys i found a solution.
That is : depth test (greater) does not initialized after one frame.
the depth goes to 1 after frame, then no pixel passes the test.
Thus I have to input glDepthFunc(GL_LESS) at first line.

Pre Z buffer pass with OpenGL?

How exactly can I do a Z buffer prepass with openGL.
I'v tried this:
glcolormask(0,0,0,0); //disable color buffer
//draw scene
glcolormask(1,1,1,1); //reenable color buffer
//draw scene
//flip buffers
But it doesn't work. after doing this I do not see anything. What is the better way to do this?
Thanks
// clear everything
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// z-prepass
glEnable(GL_DEPTH_TEST); // We want depth test !
glDepthFunc(GL_LESS); // We want to get the nearest pixels
glcolormask(0,0,0,0); // Disable color, it's useless, we only want depth.
glDepthMask(GL_TRUE); // Ask z writing
draw()
// real render
glEnable(GL_DEPTH_TEST); // We still want depth test
glDepthFunc(GL_LEQUAL); // EQUAL should work, too. (Only draw pixels if they are the closest ones)
glcolormask(1,1,1,1); // We want color this time
glDepthMask(GL_FALSE); // Writing the z component is useless now, we already have it
draw();
You're doing the right thing with glColorMask.
However, if you're not seeing anything, it's likely because you're using the wrong depth test function.
You need GL_LEQUAL, not GL_LESS (which happens to be the default).
glDepthFunc(GL_LEQUAL);
If i get you right, you are trying to disable the depth-test performed by OpenGL to determine culling. You are using color functions here, which does not make sense to me. I think you are trying to do the following:
glDisable(GL_DEPTH_TEST); // disable z-buffer
// draw scene
glEnable(GL_DEPTH_TEST); // enable z-buffer
// draw scene
// flip buffers
Do not forget to clear the depth buffer at the beginning of each pass.

Alpha transparency with particle effects in OpenGL

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();
...
}