glDrawElements with Stack Memory - objective-c

I have two arrays that I declared on the stack in a function, and verified that they both contain the exact same data:
/// Rasters the textured quad using the specified parameters.
- (void)privateConfigureRasterWithTexture:(GLuint)theTexture
bottomLeftX:(GLfloat)bottomLeftX
bottomLeftY:(GLfloat)bottomLeftY
topRightX:(GLfloat)topRightX
topRightY:(GLfloat)topRightY
{
const GLfloat texices[] =
{ bottomLeftX, bottomLeftY, // bottom left corner
bottomLeftX, topRightY, // top left corner
topRightX, topRightY, // top right corner
topRightX, bottomLeftY }; // bottom right corner
const GLfloat texices2[] =
{ 0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f };
for(int x=0;x<8;x++)
if(texices[x] != texices2[x])
{
NSLog(#"Mismatch!");
abort();
}
When I execute the following line of code in (the bottom of) that function
glVertexAttribPointer(_attributeTexturedTexCoords, 2, GL_FLOAT, GL_FALSE,
2*sizeof(GLfloat), texices2);
I get the expected result, however if I instead execute
glVertexAttribPointer(_attributeTexturedTexCoords, 2, GL_FLOAT, GL_FALSE,
2*sizeof(GLfloat), texices);
I get a bad result. I don't get what the difference is.
Edit: Here is how I'm invoking this function.
[self privateConfigureRasterWithTexture:_atlasTexture1
bottomLeftX:0.0f
bottomLeftY:0.0f
topRightX:1.0f
topRightY:1.0f];

Nevermind, I think I've found it (probably at around the exact same time Martins did). It looks like glVertexAttribPointer doesn't make a copy of the data until the call to glDrawElements. Since my glDrawElements is outside of that function, the stack memory was being released (yet for some reason texices2 remained valid).
I've rewritten the code a bit so that texices is heap allocated once when that class is allocated, and just reused over and over again and free'd when the application deallocs.

Related

How to use glClearBuffer* in Cocoa OpenGLView to clear color buffer

I'm trying to understand how to use glClearBuffer* to change the background color in a (either single or double buffered) NSOpenGLView in Cocoa for OS X.
The following code fragment as suggested by the OpenGL Superbible fails with GL_INVALID_OPERATION:
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, red);
What do I need to supply for the second parameter?
I'm using a double buffered View extending OpenGLView.
#import "MyOpenGLView.h"
#include <OpenGL/gl3.h>
#implementation MyOpenGLView
-(void) drawRect: (NSRect) bounds
{
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, red);
GLenum e = glGetError();
// e == GL_INVALID_OPERATION after this call
// and the view is drawn in black
// The following two lines work as intended:
//glClearColor(1.0, 0.f, 0.f, 1.f);
//glClear(GL_COLOR_BUFFER_BIT);
[[self openGLContext] flushBuffer];
}
#end
Really? It is giving you GL_INVALID_OPEARATION?
This function is not supposed to generate that error... are you sure something earlier in your program did not create the error and you are mistaking the source?
The bigger problem however, is that using GL_COLOR as the buffer in this API call expects the second parameter to be an index into your set of draw buffers. It is unclear how your draw buffers are setup in this code, it is possible that you have GL_NONE. As there is no defined error behavior if you try to clear a draw buffer when GL_NONE is used, I suppose an implementation might choose to raise GL_INVALID_OPERATION.
In order for your current usage of glClearBufferfv (...) to make sense, I would expect to see something like this:
GLenum buffers [] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
GLfloat red [] = { 1.0f, 0.0f, 0.0f, 1.0f };
glDrawBuffers (2, buffers);
glClearBufferfv (GL_COLOR, 0, red);
Now this call will clear GL_COLOR_ATTACHMENT0, if you wanted to clear GL_COLOR_ATTACHMENT1, you could replace 0 with 1.

Draw multiple objects with textures

I want to draw cubes using textures.
void OperateWithMainMatrix(ESContext* esContext, GLfloat offsetX, GLfloat offsetY, GLfloat offsetZ) {
UserData *userData = (UserData*) esContext->userData;
ESMatrix modelview;
ESMatrix perspective;
//Manipulation with matrix
...
glVertexAttribPointer(userData->positionLoc, 3, GL_FLOAT, GL_FALSE, 0, cubeFaces);
//in cubeFaces coordinates verticles cube
glVertexAttribPointer(userData->normalLoc, 3, GL_FLOAT, GL_FALSE, 0, cubeFaces);
//for normals (use in fragment shaider for textures)
glEnableVertexAttribArray(userData->positionLoc);
glEnableVertexAttribArray(userData->normalLoc);
// Load the MVP matrix
glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE,
(GLfloat*)&userData->mvpMatrix.m[0][0]);
//Bind base map
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, userData->baseMapTexId);
//Set the base map sampler to texture unit to 0
glUniform1i(userData->baseMapLoc, 0);
// Draw the cube
glDrawArrays(GL_TRIANGLES, 0, 36);
}
(coordinates transformation is in OperateWithMainMatrix() )
Then Draw() function is called:
void Draw(ESContext *esContext)
{
UserData *userData = esContext->userData;
// Set the viewport
glViewport(0, 0, esContext->width, esContext->height);
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(userData->programObject);
OperateWithMainMatrix(esContext, 0.0f, 0.0f, 0.0f);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
This work fine, but if I try to draw multiple cubes (next code for example):
void Draw(ESContext *esContext)
{ ...
// Use the program object
glUseProgram(userData->programObject);
OperateWithMainMatrix(esContext, 2.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, 1.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, 0.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, -1.0f, 0.0f, 0.0f);
OperateWithMainMatrix(esContext, -2.0f, 0.0f, 0.0f);
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}
A side faces overlapes frontal face. This process is illustrated on image:
Alternate picture (with colours and clean image):
The side face of the right cube overlaps frontal face of the center cube.
How can i remove this effect and display miltiple cubes without it?
To fix this you need to utilize what's known as the depth buffer. This is what's responsible for making sure that surfaces don't get drawn overtop of surfaces that are nearer (like the side of a cube showing over the front of a cube).
Luckily it's not much work involved to do so:
Enable depth testing at initialization with glEnable(GL_DEPTH_TEST)
Clear depth buffer on each frame by adding it's bit to the glClear call:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
After this you should no longer see your surfaces popping on top of nearer surfaces.

glColor4f Stops Textures From Loading Using GLKTextureLoader

I'm currently using OpenGL ES 2.0 under GLKView on the new iPad. It seems, whenever I make the call to glColor4f, nothing happens (ie. it doesn't color the polygons I want it to) other than causing a GL_INVALID_OPERATION error. Then, as soon as I try to load a texture, I get this error message:
Error loading file: The operation couldn't be completed. (GLKTextureLoaderErrorDomain error 8.)
But before the glColor4f is called, everything works fine. Here's my code below for drawInRect:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Render the object with GLKit
self.effect.texture2d0.enabled = NO;
self.effect.transform.modelviewMatrix = _defaultModelMatrix;
[self.effect prepareToDraw];
// Render the grid
glBindBuffer(GL_ARRAY_BUFFER, _gridVertexBuffer);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, TRIANGLES * 6);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
If anyone can help, I'd really appreciate it. Some things to point out though. The object I'm trying to color is stored in a VBO and is rendered fine, in a white color (even though I'm trying to color it red).
Thanks
glColor4f is not an OpenGLES2.0 command (it's from GLES1.1)
What you want to do is declare a uniform in your shader called 'color' (or something similar), set that uniform as you typically would with any shader uniform, and multiply your fragment color with that uniform before writing the pixel.

How to use GLKMatrixStack?

I'm writing an iOS game that draws many cubes on screen, but I have a problem with positioning the cubes.
I have a function draw_voxel that draws a cube:
void draw_voxel(Point location, Color color, GLKMatrixStackRef stack) {
GLKMatrixStackPush(stack);
GLKMatrixStackTranslate(stack, location.x, location.y, location.z);
std::array<Color, 36> triangle_colors;
triangle_colors.fill(color);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, static_cast<const GLvoid*>(triangle_vertices.data()));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, static_cast<const GLvoid*>(triangle_colors.data()));
glDrawArrays(GL_TRIANGLES, 0, 36);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribColor);
GLKMatrixStackPop(stack);
}
I pass it a GLKMatrixStackRef, push the current matrix on top and use GLKMatrixStackTranslate to translate the top matrix. However, all cubes are still drawn at (0, 0, 0).
I call draw_voxel like this:
[self.effect prepareToDraw];
GLKMatrixStackRef stack = GLKMatrixStackCreate(nullptr);
draw_voxel(Point(-1.0f, 0.0f, 0.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), stack);
draw_voxel(Point(+0.0f, 0.0f, 0.0f), Color(0.0f, 1.0f, 0.0f, 1.0f), stack);
draw_voxel(Point(+1.0f, 0.0f, 0.0f), Color(0.0f, 0.0f, 1.0f, 1.0f), stack);
CFRelease(stack);
I couldn't find any useful information on the internet about GLKit matrix stacks, and I'm really stuck. How do I "apply" the top matrix so that the cubes are translated?
While I still haven't fully grasp how to use GLKMatrixStack, looking at your code I think the problem is that you are not passing the top matrix of the stack to the shader, or, in GLKit words, you are not properly configuring the effect.
Probably, at some point you should be doing something like:
self.effect.transform.modelviewMatrix = GLKMatrixStackGetMatrix4(stack);
Hope this help, I'm stuck on that stack too :)

Unusual Lighting Effects - Random Polygons Coloured

I am working on creating an object loader for use with iOS, I have managed to load the vertices, normals and face data from and OBJ file, and then place this data into arrays for reconstructing the object. But I have come across an issue with the lighting, at the bottom is a video from the simulation of my program - this is with the lighting in the following position:
CGFloat position[] = { 0.0f, -1.0f, 0.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position);
This is specified in both the render method each frame and the setup view method which is called once at setup.
Various other lighting details are here, these are called once during setup:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
CGFloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
CGFloat diffuseLight[] = { 1.0f, 0.0f, 0.0, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
CGFloat position[] = { 0.0f, -1.0f, 0.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
The video of the issue can be found here:
http://youtu.be/dXm4wqzvO5c
Thanks,
Paul
[EDIT]
for further info normals are also supplied by the following code, they are currently in a large normals array or XYZ XYZ XYZ etc...
// FACE SHADING
glColorPointer(4, GL_FLOAT, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);
glNormalPointer(GL_FLOAT, 3, normals);
glEnableClientState(GL_NORMAL_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3*numOfFaces);
glDisableClientState(GL_COLOR_ARRAY);
I now feel incredibly stupid... All part of being a student programmer I guess. I will leave an answer to this so if anyone else gets this problem they can solve it too! The mistake was simply down to a typo:
glNormalPointer(GL_FLOAT, 3, normals);
Should have read
glNormalPointer(GL_FLOAT, 0, normals);
The second argument being the STRIDE which is only used if the array contains other values e.g. Vert Coords / Normals / Texture Coords. As mine are in single arrays the stride between the values should be 0.