Related
I'm trying to draw some basic triangles using opengl, but it's not rendering on screen. These are the relevant functions:
glewInit();
glClearColor(0.0, 0.0, 0.0, 1.0);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
Vertex vertices[] = {Vertex(Vector3f(0.0, 1.0, 0.0)),
Vertex(Vector3f(-1.0, -1.0, 0.0)),
Vertex(Vector3f(1.0, -1.0, 0.0))};
mesh.addVertices(vertices, 3);
Pastebin links to Vertex.hpp and Vector3f.hpp:
Vertex.hpp
Vector3f.hpp
/*
* Mesh.cpp:
*/
Mesh::Mesh()
{
glGenBuffers(1, &m_vbo); // unsigned int Mesh::m_vbo
}
void Mesh::addVertices(Vertex vertices[4], int indexSize)
{
m_size = indexSize * 3;
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_size, vertices, GL_STATIC_DRAW);
}
void Mesh::draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(Vertex), 0);
glDrawArrays(GL_TRIANGLES, 0, m_size);
glDisableVertexAttribArray(0);
}
It's just black if I call glClear otherwise just the random noise of a default window. I can make it draw a triangle by using the most primitive method:
glBegin(GL_TRIANGLES);
glColor3f(0.4, 0.0, 0.0);
glVertex2d(0.0, 0.5);
glVertex2d(-0.5, -0.5);
glVertex2d(0.5, -0.5);
glEnd();
That works and displays what it should do correctly, so I guess that at least says my application is not 100% busted. The tutorial I'm following is in Java, and I'm translating it to C++ SFML as I go along, so I guess it's possible that something got lost in translation so to speak, unless I'm just missing something really basic (more likely.)
How do we fix this so it uses the Vertex list to draw the triangle like it's supposed to?
So many mistakes. There are truly a lot of examples, in any language, so why?
const float pi = 3.141592653589793; is member field of Vector3f. Do you realise this is non-static member and it is included in each and every Vector3f you use, so your vectors actually have four elements - x, y, z, and pi? Did you informed GL about it, so it could skip this garbage data? I don't think so.
You using glVertexAttribPointer, but don't have active shader. There is no guarantee that position is in slot 0. Either use glVertexPointer, or use shader with position attribute bound to 0.
void Mesh::addVertices(Vertex vertices[4], int indexSize) what [4] supposed to mean here? While it is not an error, it is at least misguiding.
glBufferData(GL_ARRAY_BUFFER, m_size, vertices, GL_STATIC_DRAW); m_size is 3*3 in your example, while documentation says it should be array size in bytes - which is sizeof(Vertex) * indexSize.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(Vertex), 0); why stride parameter is 4*sizeof(Vertex)? Either set it to 0 or write correct stride - which is sizeof(Vertex).
glDrawArrays(GL_TRIANGLES, 0, m_size); m_size is already [incorrectly] set as "vertex buffer size", while DrawArrays expects number of vertices to draw - which is m_size / sizeof(Vertex) (given m_size is calculated correctly).
Umm.. I wrote this code to print mesh (var m), and it's running well
glBegin(GL_TRIANGLES);
for (unsigned i : m.vtIndex)
{
const aiVector3D *pv = &m.pMesh->mVertices[i];
const aiVector3D *pvn = &m.pMesh->mNormals[i];
glNormal3fv((const GLfloat *)pvn);
glVertex3fv((const GLfloat *)pv);
}
glEnd();
And here is other one
glVertexPointer(3, GL_FLOAT, 0, m.pMesh->mVertices);
glNormalPointer(GL_FLOAT, 0, m.pMesh->mNormals);
glDrawElements(GL_TRIANGLES, m.vtIndex.size(), GL_UNSIGNED_INT, &m.vtIndex[0]);
But second one occured access violation
Could you give me an opinion?
You are using deprecated OpenGL in this example and using client memory to store vertex data. In deprecated OpenGL, you need to enable the appropriate client states:
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_NORMAL_ARRAY);
If you add this to your code before your draw call, it ought to fix your crash.
You can safely leave GL_VERTEX_ARRAY enabled for the entire time your program runs, but you may need to enable/disable other arrays such as GL_NORMAL_ARRAY depending on which vertex pointers your meshes actually use.
I figure out.
glEnableClientState(GL_INDEX_ARRAY); // Oops!!
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
haha....
I'm trying to emulate exactly how a game sets up a VBO and draws it to the screen. I've never set one up before and the tutorials all show how to do it with glDrawArrays but I want to use glDrawElements.
I came up with the following:
glViewport(0, 0, 765, 553);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 765, 553, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
xCast(ptr_glActiveTextureARB, ptr_wglGetProcAddress("glActiveTextureARB"));
xCast(ptr_glMultiTexCoord2fARB, ptr_wglGetProcAddress("glMultiTexCoord2fARB"));
xCast(ptr_glGenBuffersARB, ptr_wglGetProcAddress("glGenBuffersARB"));
xCast(ptr_glBindBufferARB, ptr_wglGetProcAddress("glBindBufferARB"));
xCast(ptr_glBufferDataARB, ptr_wglGetProcAddress("glBufferDataARB"));
struct PointInfo
{
float Pos[3];
float Colour[3];
};
const int NumVerts = 3, NumInds = 3;
std::vector<PointInfo> Vertices;
Vertices.push_back({{0.0f, 1.0f, 0.0f}, {1, 1, 1}}); ///top left;
Vertices.push_back({{0.5f, 0.0f, 0.0f}, {1, 1, 1}}); ///bottom middle;
Vertices.push_back({{1.0f, 1.0f, 0.0f}, {1, 1, 1}}); ///top right;
std::vector<std::uint32_t> Indices = {0, 1, 2};
std::uint32_t VBO = 0, IBO = 0;
ptr_glGenBuffersARB(1, &VBO);
ptr_glGenBuffersARB(1, &IBO);
///Put Vertices In.
ptr_glBindBufferARB(GL_ARRAY_BUFFER, VBO);
ptr_glBufferDataARB(GL_ARRAY_BUFFER, sizeof(PointInfo) * NumVerts, &Vertices[0], GL_STATIC_DRAW);
Log(glGetError());
///Put Indices In.
ptr_glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IBO);
ptr_glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * NumInds, &Indices[0], GL_STATIC_DRAW);
Log(glGetError());
I run the above only once at the start of my program. Then in my while loop, I run:
glPushMatrix();
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Log(glGetError());
ptr_glBindBufferARB(GL_ARRAY_BUFFER, VBO);
Log(glGetError());
glVertexPointer(3, GL_FLOAT, sizeof(PointInfo), (void*) offsetof(PointInfo, Pos));
Log(glGetError());
glColorPointer(3, GL_FLOAT, sizeof(PointInfo), (void*) offsetof(PointInfo, Colour));
Log(glGetError());
ptr_glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IBO);
Log(glGetError());
glDrawElements(GL_TRIANGLES, NumInds, GL_UNSIGNED_INT, 0);
Log(glGetError());
glPopMatrix();
SwapBuffers(DC);
Sleep(1);
But the only thing that happens is my screen clearing. I never see my triangle at all :S I think it might be my view setup via the glOrtho but I'm not sure. Is there anything wrong with what I did? The glGetError just prints 0.. No errors :S
The triangle coordinates you specified are very small. The triangle occupies only half of a pixel at the top left corner of the screen. Try scaling it by 100.
Also I think you're missing calls to glEnableClientState with GL_VERTEX_ARRAY and GL_COLOR_ARRAY.
As a general approach I would suggest to take things one step at a time. Start with immediate mode glVertex to make sure you got the coordinates and camera setup right. Then add shaders. Then convert to a position-only VBO with DrawArrays. Then add vertex colors. Then convert to DrawElements. That way you have a better sense of where problems might lie.
You might also be interested in the glload library here to get rid of these ptr_ prefixes.
You should use glVertexAttribPointer. The functions you are using are deprecated. Perhaps you could get this code to work, but if you aren't forced to use such an ancient OpenGL, chances are you'd save yourself a lot of trouble.
Oh also manually loading function pointers is extremely cumbersome. I suggest you looked at libraries such as GLload.
A specialized debugger such as CodeXL or gDebugger can be very helpful in solving issues like that.
As for the problems in this code, your triangle is simply too small.
I have something rather strange going on at the moment with my code. I am running this on a BlackBerry Playbook and it is OpenGL ES 1.1
EDIT 4: I deleted everything I have posted to simplify my question.
I took the code and simplified it to drawing two overlapping triangles. Here is the array containing the coordinates as well as an array containing colours:
GLfloat vertices[] =
{
// front
175.0f, 200.0f, -24.0f,
225.0f, 200.0f, -24.0f,
225.0f, 250.0f, -24.0f,
// back
200.0f, 200.0f, -25.0f,
250.0f, 200.0f, -25.0f,
250.0f, 250.0f, -25.0f
};
static const GLfloat colors[] =
{
/* front */ 1.0f,0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f, //Red
/* back */ 0.0f,1.0f,0.0f,1.0f,0.0f,1.0f,0.0f,1.0f,0.0f,1.0f,0.0f,1.0f //Green
};
Please note that my coordinates are 0 to 1024 in the x direction and 0 to 600 in the y direction as well as 0 to -10000 in the z direction.
Here is my setup code which reflects this:
glClearDepthf(1.0f);
glClearColor(1.0f,1.0f,1.0f,1.0f);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glShadeModel(GL_SMOOTH);
glViewport(0, 0, surface_width, surface_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, surface_width, 0, surface_height, 0, 10000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
I have depth enabling in two places as I was trying to rule out the possibility that it was supposed to be used while a certain matrix mode was chosen.
Lastly here is my render code:
void render()
{
//Typical render pass
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLES, 0 , 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//Use utility code to update the screen
bbutil_swap();
}
The issue is that no matter what I do the green triangle is always overlayed over the red one. Changing z values either way has no effect on the finished image. I cannot figure this out.
By default, depth testing is disabled. You have to enable it with glEnable(GL_DEPTH_TEST). The reason why it is working when you enable culling is because the back facing triangles are not drawn, and since a cube is a convex polyhedron, no front-facing quad will ever overlap another front-facing quad. If you try to render a second cube, however, you will see depth problems as well, unless you enable depth testing.
I finally got it to work. The issue was with EGL setup code that I used that was provided. In bbutil.c (in my case .cpp) there is some code:
if(!eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs)) {
bbutil_terminate();
return EXIT_FAILURE;
}
(that is not all the code in the file but its the important bit)
This basically freaks if the given attribute list is nor supported. Up higher in the file attrib_list is set as follows:
EGLint attrib_list[]= { EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, 0,
EGL_NONE};
There is no depth buffer specified. Now if you look in the EGL spec it says no depth is the default. BINGO, that's the problem. So I just modified it to look like this:
EGLint attrib_list[]= { EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, 0,
EGL_DEPTH_SIZE, 24,
EGL_NONE};
Note the EGL_DEPTH_SIZE and the 24. This sets the depth buffer to 24 bits. On the PlayBook 32 throws a segmentation fault although usually 32 is not supported anyways. Perhaps this will help someone out there trying to figure out why the provided include is causing this funny result I described as my problem.
I have been trying to get an object to be lit properly all day long, without results, so I'm going to try here. In the essence, I am trying the object to look like this:
While in my program it looks like this:
Here's my context:
glClearDepth(1.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLight(GL_LIGHT0, GL_POSITION, {0, 5, 0, 1});
glDisable(GL_TEXTURE_2D);
And my material/lighting settings:
glMaterialf(GL_FRONT, GL_SHININESS, 10);
glLight(GL_LIGHT0, GL_AMBIENT, {0.1, 0.1, 0.1, 1.0});
glLight(GL_LIGHT0, GL_DIFFUSE, {0.2, 0.2, 0.2, 1.0});
glLight(GL_LIGHT0, GL_SPECULAR, {0.6, 0.6, 0.6, 1.0});
glMaterial(GL_FRONT, GL_AMBIENT, {1, 0.8078, 0});
glMaterial(GL_FRONT, GL_DIFFUSE, {1, 0.8078, 0});
glMaterial(GL_FRONT, GL_SPECULAR, {0.5, 0.5, 0.5});
glMaterial(GL_FRONT, GL_EMISSION, {0, 0, 0});
[I used {r, g, b, a} to denote an array for simplicity. I looked up the actual values that were used to draw the model and wrote them into the arrays]
The main problem is that whenever my objects get fully lit, everything "clutters" together into the ambient colour. There are no lighter and darker parts depending on the orientation of the fragment anymore, just one chunk of solid colour.
I have searched the whole project for openGL settings I may have missed, though the only thing I found was what you see above (omitting a few calls to reset the projection and modelview matrices, clearing the screen, and a translation/rotation).
I have also tried to alter the values of the lights and materials, without much success. Changing the ambient colour just causes the whole model to become brighter. I also tried moving the light.
EDIT: By request, here's how I store and draw the model:
I load the model from an OBJ file. I looked at the file itself, which lists normals. The loader also recognizes that.
Here's how it draws the VBO:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBufferID);
glVertexPointer(3, GL_FLOAT, stride, 0 * 4);
glNormalPointer(GL_FLOAT, stride, 3 * 4);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
glDrawElements(GL_TRIANGLES, this.numberOfVertices, GL_UNSIGNED_INT, 0);
The VBO is interleaved, formatted like [vertex, normal, vertex, normal, ..]. I dropped some print calls in the drawing code, and it sets the vertex and normal pointers. Hence I am pretty sure that the VBO itself is loaded and drawn correctly.
It's crashing because you leave texture_coord_array client state enabled, so it tries to access whatever is at the texcoord pointer, which is null.
So with many problems, the answer is often unexpected. The first part was the switch statement I used to determine how to set the data pointers of the VBO:
private void setDataPointers() {
int stride = this.dataFormat.elementsPerVertex * 4;
glVertexPointer(3, GL_FLOAT, stride, 0 * 4);
switch(this.dataFormat)
{
case VERTICES_AND_TEXTURES:
glTexCoordPointer(2, GL_FLOAT, stride, (3)*4);
case VERTICES_AND_NORMALS:
glNormalPointer(GL_FLOAT, stride, 3 * 4);
case VERTICES_TEXTURES_NORMALS:
glTexCoordPointer(2, GL_FLOAT, stride, 3 * 4);
glNormalPointer(GL_FLOAT, stride, (3 + 3) * 4);
}
}
As you can see the break; statements are missing. So the vertex, normal AND texture pointers would be set.
Second, when drawing the VBO, all three client side modes were enabled:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
So the renderer was looking for texture coordinates that didn't exist, and somehow spit out the strange unlit geometry.