Calling glDrawElements after glInterleavedArrays isn't working - c

I am writing some openGL wrappers and am trying to run the following code:
void some_func1() {
float vertices[] = {50.0, 50.0, 0.0, 20.0, 50.0, 0.0, 20.0, 60.0, 0.0};
glColor3f(1.0, 0.0, 0.0);
glInterleavedArrays(GL_V3F, 0, vertices);
}
void some_func2() {
int indices[] = {0,1,2};
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
}
void parent_func() {
some_func1();
some_func2();
}
But it would seem that openGL is not picking up the call to glDrawElements in the second function. My routine opens a window, clears it to black, and draws nothing. What's weird is that running this code
void some_func1() {
float vertices[] = {50.0, 50.0, 0.0, 20.0, 50.0, 0.0, 20.0, 60.0, 0.0};
int indices[] = {0,1,2};
glColor3f(1.0, 0.0, 0.0);
glInterleavedArrays(GL_V3F, 0, vertices);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
}
void parent_func() {
some_func1();
}
works exactly as expected: a red triangle is drawn. I've looked through the documentation and searched around, but I can't find any reason that glDrawElements wouldn't work, or would miss data somehow if called in another function. Any ideas?
FYI: I am running this on an Ubuntu 12.04 VM through VirtualBox, 32-bit processor on the host, and freeglut is doing my window handling. I have also set LIBGL_ALWAYS_INDIRECT=1 to work around an issue with the VM's 3D rendering. (not sure if any of that matters but... :))

The reason is, that at the point of drawing with glDrawElements, there is no valid vertex data to draw. When calling glInterleavedArrays (which just does a bunch of gl...Pointer calls under the hood) you are merely telling OpenGL where to find the vertex data, without copying anything. The actual data is not accessed before the drawing operation (glDrawElements). So in some_func1 you are setting a pointer to the local variable vertices, which doesn't exist anymore after the function returns. This doesn't happen in your modified code (where the pointer is set and drawn in the same function).
So either make this array survive until the glDrawElements call or, even better, make OpenGL to actually store the vertex data itself, by employing a vertex buffer object and performing an actual data copy. In this case you might also want to refrain from the awfully deprecated glInterleavedArrays function (which isn't much more than a mere software wrapper around proper gl...Pointer and glEnableClientState calls, anyway).

Related

Optimising the rendition of quads using GLUT?

I'm making a 3d voxel engine, similar to Minecraft. I have some world generation and chunk logic working, however when I have a render distance of 12 chunks (which seems fairly typical for Minecraft for example), (2*12*12*16*16*2), I see there is a potential of being upwards of 150,000 faces needing to be rendered. Before trying to optimize the engine as a whole, I run a test where I just rendered one face 150,000 times. In theory, as the points aren't having to be calculated in 3d space each time, this task should really the least computationally expensive rendition the engine would have to make.
Nevertheless, running the following
glBegin(GL_QUADS);
glColor3f(1, 0, 0);
for (int i = 0; i < 150000;i++) {
glVertex3fv(renderp1);
glVertex3fv(renderp2);
glVertex3fv(renderp3);
glVertex3fv(renderp4);
}
glEnd();
Even when theres no texture and the points are all the same, I still get a very shabby fps, which makes the engine unusable.
I know modern games have meshes with upwards of 100,000 polygons, and run fantastically. Which makes me wonder how this code here is so slow? Is rendering using this technique a horrible way to go about doing this? How could i achieve such a render?
The first thing you should do (before any of the shader stuff) is to stop using glBegin/glEnd and start using glDrawArrays or glDrawElements.
e.g.
// define data structures
struct vec3 { GLfloat x, y, z; };
struct vertex_t {
vec3 position, color;
};
// define data (just a single triangle with RGB colors)
static const vertex_t vertices[] = {
{ { 0.0f, 0.5f, 0.0f }, { 1, 0, 0 } },
{ { 0.5f, -0.5f, 0.0f }, { 0, 1, 0 } },
{ { -0.5f, -0.5f, 0.0f }, { 0, 0, 1 } }
};
...
// setup the arrays
glVertexPointer(3, GL_FLOAT, sizeof(vertex_t), (char*)vertices + offsetof(vertex_t, position) );
glColorPointer(3, GL_FLOAT, sizeof(vertex_t), (char*)vertices + offsetof(vertex_t, color) );
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
...
// draw
glDrawArrays(GL_TRIANGLES, 0, 3);
This is OpenGL 1.1 stuff. It can be further improved with VBO (Vertex Buffer Object), which requires OpenGL 1.5
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// now replace vertices with nullptr in calls to glVertexPointer and glColorPointer
and we haven't even touched shaders yet.
For OpenGL 2.x style shaders, the above code can stay as is, or you can further "modernize" it by replacing glVertexPointer/glColorPointer with glVertexAttribPointer, and glEnableClientState with glEnableVertexAttribArray, to make "modern OpenGL" people happy.
But just using glDrawArrays, OpenGL 1.1 style, should be enough to resolve the performance problem.
This way you don't call glVertex/glColor 100000 times, but a single call to glDrawArrays can draw 100000 vertices at once (and if using VBO, they're already in the GPU memory).
And oh, quads are deprecated since 3.0. We're supposed to build everything from triangles.

Infinite Loop on OpenGL

I decided that whenever the user tries to resize the screen the screen must go back to preset sizes, so it makes my life easier on graph nodes drawing. On MAC, my application is working properly but on Linux it is happening an infinte loop on the resize function, and I don't know why. After some loop calls I got a Segmentation fault (core dumped)
here's my opengl configuration(main funciton)
glutInit(&argc, argv);
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutInitWindowPosition(100, 100);
glutCreateWindow(APP_NAME);
glClearColor(0.0, 0.0, 0.0, 0.0); // black background
glMatrixMode(GL_PROJECTION); // setup viewing projection
glLoadIdentity(); // start with identity matrix
glOrtho(0.0, 50.0, 0.0, 50.0, 0.0, 0.1); // setup a 50x50 viewing world
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutMainLoop();
and here's my display and resize functions implementations
void display() {
Matrix* distanceMatrix = NULL;
PalleteNodePosition* nodesPositions = NULL;
distanceMatrix = fromFile(inputFileName);
printf("Finish input parsing...\n");
nodesPositions = calculateNodesPositions(distanceMatrix);
printf("Finish calculating nodes position on screen...\n");
glClear( GL_COLOR_BUFFER_BIT);
drawNodes(nodesPositions, distanceMatrix->width);
drawLink(10, 10, 18, 18);
glFlush();
}
void resize(int w, int h){
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);
}
When I print the resize call, I got w equals to WINDOW_WIDTH and h equals to WINDOW_HEIGHT as expected, so why the app is resizing the screen everytime?
Your resize() callback will be indirectly called by itself even if it
is in an asynchronous way.
You ask the windowing system to resize your window, then later
you receive the event that says that your window has been resized,
then your callback is triggered, which leads to a new resize
request...
If nobody stops this loop (apparently the windowing system
does not detect that the resize is not actually needed),
it is infinite.
May be should you consider comparing w and h to the expected
values, inside your resize() callback, and only invoke glutReshapeWindow() if it is actually needed?
You should also be aware that the inner size and the outer size
of the window are probably different (border, title-bar...).

C - Depth effect in OpenGL

I read this tutorial online: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/. More precisely the chapter about projection matrices.
I am trying to apply what I read, to a specific part of what I drew. However I don't see anything different. Did I misunderstand anything or do I just apply it incorrectly?
I am actually drawing 2 houses. And I would like to create this effect: http://www.opengl-tutorial.org/assets/images/tuto-3-matrix/homogeneous.png
My code:
void rescale()
{
glViewport(0,0,500,500);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glOrtho(-6.500, 6.500, -6.500, 6.500, -6.00, 12.00);
}
void setup()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
}
void draw()
{
glPushMatrix();
//draw something in the orthogonal projection
glPopMatrix();
glPushMatrix();
gluPerspective(0.0, 1, -12, 30); //perspective projection
glPushMatrix();
glScalef(0.2,0.2,0.2);
glTranslatef(-1, 0.5, -5);
glColor3f(1.0, 0.0, 0.0);
drawVertexCube();
glPopMatrix();
glPushMatrix();
glScalef(0.2,0.2,0.2);
glTranslatef(-1, 0.5, -40);
glColor3f(0, 1.0, 0.0);
drawVertexCube();
glPopMatrix();
glPopMatrix();
glFlush();
}
This is the result:
As you can see there is no (visible) result. I would like to accentuate the effect much more.
Your gluPerspective call is invalid:
gluPerspective(0.0, 1, -12, 30);
The near and far parameters must both be positive, otherwise the command will generate just an GL error and will leave the current matrix unmodified, so your ortho projection is still in use. Your glPushMatrix()/glPopMatrix() calls won't help because you never enclosed the glOrtho() call in such a block, so you never restore to a state where that matrix is not already applied. Furthermore. the glMatrixMode() inbetween a glLoadIdentity() and the glOrtho seems also quite weird.
You should also be aware that all GL matrix functions besides the glLoad* ones will multiply the current matrix by a new matrix. Since you still have the ortho matrix applied, you would get the product of both matrices, which will totally screw up your results.
Finally, you should be aware that all of the GL matrix strack functionality is deprecated and completely removed in the core profile of modern OpenGL. If you are learning OpenGL nowadays, you should really consider learning the "modern" way in OpenGL (which is basically already a decade old).

3D pyramid appears scattered, with mixed up sides

First of all I defined a structure to express the coordinated of a pyramid:
typedef struct
{
GLfloat xUp;
GLfloat yUp;
GLfloat zUp;
GLfloat base;
GLfloat height;
}pyramid;
Pretty self-explanatory here : I store the coordinates of the uppest point, the base and the height.
The I wrote a function to draw a pyramid:
void drawPyramid(pyramid pyr)
{
GLfloat p1[]= {pyr.xUp+pyr.base/2.0, pyr.yUp-pyr.height, pyr.zUp-pyr.base/2.0};
GLfloat p2[]= {pyr.xUp+pyr.base/2.0, pyr.yUp-pyr.height, pyr.zUp+pyr.base/2.0};
GLfloat p3[]= {pyr.xUp-pyr.base/2.0, pyr.yUp-pyr.height, pyr.zUp+pyr.base/2.0};
GLfloat p4[]= {pyr.xUp-pyr.base/2.0, pyr.yUp-pyr.height, pyr.zUp-pyr.base/2.0};
GLfloat up[]= {pyr.xUp, pyr.yUp, pyr.zUp};
glBegin(GL_TRIANGLES);
glColor4f(1.0, 0.0, 0.0, 0.0);
glVertex3fv(up);
glVertex3fv(p1);
glVertex3fv(p2);
glColor4f(0.0, 1.0, 0.0, 0.0);
glVertex3fv(up);
glVertex3fv(p2);
glVertex3fv(p3);
glColor4f(0.0, 0.0, 1.0, 0.0);
glVertex3fv(up);
glVertex3fv(p3);
glVertex3fv(p4);
glColor4f(1.0, 1.0, 0.0, 0.0);
glVertex3fv(up);
glVertex3fv(p4);
glVertex3fv(p1);
glEnd();
glColor4f(0.0, 1.0, 1.0, 0.0);
glBegin(GL_QUADS);
glVertex3fv(p1);
glVertex3fv(p2);
glVertex3fv(p3);
glVertex3fv(p4);
glEnd();
}
I struggled to draw all the vertices in anti-clockwise order, but probably I messed up something.
This is how I display the pyramid in my rendering function:
void display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.0, -25.0, 50.0);
glRotatef(-angle, 0.0, 1.0, 0.0);
glTranslatef(0.0, 25.0, -50.0);
pyramid pyr;
pyr.xUp=0.0;
pyr.yUp=10.0;
pyr.zUp=50.0;
pyr.base=10.0;
pyr.height=18.0;
glColor4f(1.0, 0.0, 0.0, 0.0);
drawPyramid(pyr);
glutSwapBuffers();
}
I also use an init method called before the glut main loop:
void init()
{
glEnable(GL_DEPTH);
glViewport(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(35.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,1.0,0.0, 0.0,1.0,30.0, 0.0,1.0,0.0);
}
angle is just a double that I use to rotate the pyramid, changeable by pressing 'r', but this is not relevant.It appears that the real problem is how I draw the vertices.
The problem is that the faces of the pyramid appear scattered, messed up.I would better describe this situation with an image:
There's a face that is too small, that is displayed and I don't know why.
If I rotate the pyramid it appears messed up, I even recored a video to describe this.
Later I could upload it if the problem is not totally clear.
PS: Many people have noticed that I am using outdated techniques.But unfortunately this is what my university offers.
EDIT
I forgot to say about the main function:
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowPosition(100, 100);
glutInitWindowSize(500, 500);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Sierpinsky Pyramid");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}
It looks like depth buffer isn't initialzied.
Calling glEnable(GL_DEPTH_TEST) is not enough. You must correctly initialize glut and specify that you want depth buffer support, otherwise you won't get a depth buffer. If I remember correctly, this is done using glutInitDisplayMode(GLUT_DEPTH|...). See documentation here and introduction here. Additional info can be found using google.
--EDIT--
You're passing invalid parameter to glEnable. call glEnable(GL_DEPTH_TEST) instead of glEnable(GL_DEPTH).
Also:
Matrix code in display function isn't protected by glPushMatrix/glPopMatrix. Which means that every time you rotate pyramid, rotation is applied to previous transform. I.e. calling display function will rotate the pyramid.
glViewport is called with invalid parameters. glViewport takes 4 integer arguments, but you're trying to pass floats. Also, what's "width of -1.0" supposed to mean?
You have not checked any error codes (glGetError). If you tried to call glGetError after glEnable call, then you'd see that it returns GL_INVALID_ENUM.
OpenGL has documentation. Documentation is available on opengl.org. Use it and read it. Also, I'd recommend reading "OpenGL red book".

Drawing using Vertex Buffer Objects in OpenGL ES 1.1 vs ES 2.0

i am new to openGL. Iam using apple documentation as my major referens
http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html#//apple_ref/doc/uid/TP40008793-CH107-SW6
My problem is that i am using openGL ES 1.1 and not 2 thus functions which are used in Listing 9-3 such as glVertexAttribPointer, glEnableVertexAttribArray are not recognized ... :)
I trying to make the optimizations which are described in this documentation:
to hold indices and vertex as a struct with all of its data: position, color (Listing 9-1)
typedef struct _vertexStruct
{
GLfloat position[3];
GLubyte color[4];
} VertexStruct;
const VertexStruct vertices[] = {...};
const GLushort indices[] = {...};
and to use VBOs such as in Listing 9-2, 9-3
As i mentioned, some of the functions that are used there don't exists in openGL ES 1.1. I am wondering if there is a way to do the same in ES 1.1 maybe with some other code ?
thank,
Alex
Edit according to Christians answer, tried to use glVertexPointer, glColorPointer.
Here is the code, it prints the cube but no colors ... :(. Anyone, is it possible to use
VBOs in such menner using ES 1.1
typedef struct {
GLubyte red;
GLubyte green;
GLubyte blue;
GLubyte alpha;
} Color3D;
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
} Vertex3D;
typedef struct{
Vector3D position;
Color3D color;
} MeshVertex;
Cube Data:
static const MeshVertex meshVertices [] =
{
{ { 0.0, 1.0, 0.0 } , { 1.0, 0.0, 0.0 ,1.0 } },
{ { 0.0, 1.0, 1.0 } , { 0.0, 1.0, 0.0 ,1.0 } },
{ { 0.0, 0.0, 0.0 } , { 0.0, 0.0, 1.0 ,1.0 } },
{ { 0.0, 0.0, 1.0 } , { 1.0, 0.0, 0.0, 1.0 } },
{ { 1.0, 0.0, 0.0 } , { 0.0, 1.0, 0.0, 1.0 } },
{ { 1.0, 0.0, 1.0 } , { 0.0, 0.0, 1.0, 1.0 } },
{ { 1.0, 1.0, 0.0 } , { 1.0, 0.0, 0.0, 1.0 } },
{ { 1.0, 1.0, 1.0 } , { 0.0, 1.0, 0.0, 1.0 } }
};
static const GLushort meshIndices [] =
{ 0, 1, 2 ,
2, 1, 3 ,
2, 3, 4 ,
3, 5, 4 ,
0, 2, 6 ,
6, 2, 4 ,
1, 7, 3 ,
7, 5, 3 ,
0, 6, 1 ,
1, 6, 7 ,
6, 4, 7 ,
4, 5, 7
};
Function
GLuint vertexBuffer;
GLuint indexBuffer;
- (void) CreateVertexBuffers
{
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(meshVertices), meshVertices, GL_STATIC_DRAW);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(meshIndices), meshIndices, GL_STATIC_DRAW);
}
- (void) DrawModelUsingVertexBuffers
{
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(3, GL_FLOAT, sizeof(MeshVertex), (void*)offsetof(MeshVertex,position));
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MeshVertex), (void*)offsetof(MeshVertex,color));
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLE_STRIP, sizeof(meshIndices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
Functions like glVertexAttribPointer and glEnableVertexAttribArray are used for generic custom vertex attributes (which are the only supported method for submitting vertex data in OpenGL ES 2.0).
When using the fixed-function pipeline (as you have to in OpenGL ES 1.1) you just use the builtin attributes (think of the glVertex and glColor calls, you might have used before switching to vertex arrays). There are functions for each attribute which are called similar to their immediate mode counterparts, like glVertexPointer or glColorPointer (instead of glVertexAttribPointer). These arrays are enabled/disabled by calling gl(En/Dis)ableClientState with constants like GL_VERTEX_ARRAY or GL_COLOR_ARRAY (instead of gl(En/Dis)ableVertexAttribArray).
But as a general rule you should not learn OpenGL ES 1.1 programming with 2.0 resources, as much of the information won't be of use to you (at least if you are new to OpenGL). For example some methods described on your linked site may not be supported in 1.1, like VBOs or even VAOs. But I also have to admit, that I have completely no ES experience, so am not perfectly sure about that.
EDIT: Regarding your updated code: I assume no colors means the cube is of a single color, probably white. In your first code example you used GLubyte color[4], and now its some Color3D type, maybe this doesn't fit to the glColorPointer(4, GL_UNSIGNED_BYTE, ...) call (where the first argument is the number of components and the second one the type)?
If your Color3D type only contains 3 colors or floating point colors, I would anyway suggest you to use 4-ubyte colors, because together with your 3 floats for the position you should get a perfectly 16-byte aligned vertex, which is also and optimization they suggest in your provided link.
And by the way, the repetition of the index buffer creation in your CreateVertexBuffers function is rather a typo, isn't it?
EDIT: Your colors contain ubytes (which range from 0 (black) to 255 (full color)) and you initialize them with floats. So your float value 1.0 (which should surely mean full color) is converted to ubyte and you get 1, which compared to the whole [0,255] range is still very small, so everything is black. When you use ubytes, then you should also initialize them with ubytes, so just replace every 0.0 with 0 and every 1.0 with 255 in the color data.
And by the way, since you're using VBOs in ES 1.1 and at least something is drawn, then ES 1.1 seems to support VBOs. I didn't know that. But I'm not sure if it also supports VAOs.
And by the way, you should call glBindBuffer(GL_ARRAY_BUFFER, 0) and likewise for the element array buffer after you're finished with using them at the end of these two functions. Othwerwise you may get problems in other functions which assume no buffers but the buffers are still bound. Always remember that OpenGL is a state machine and every state you set stays until it's changed again or the context is destroyed.

Resources