Unusual Lighting Effects - Random Polygons Coloured - objective-c

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.

Related

OpenGL ES 2.0 Grid Lines With Triangle Strip

I need to draw a 10 x 10 grid in OpenGL ES 2.0. Are triangle strips the best way to do this? How do you draw this without drawing the diagonal lines? All of the searches that I come up with show grid lines with the diagonals drawn, but this defeats the purpose.
I've drawn the grid just using a bunch of lines, but I'm having trouble transforming it as a unit. Is this the right approach, but I'm not executing it correctly? Or is there a better way, like triangle strips? Thanks!
// draw the horizontal gridlines
for (i=0; i<12; i++) {
modelViewMatrixRight = GLKMatrix4MakeTranslation(0.0f, 1.0f/11.0f*(float)i - 0.5f, -2.0f);
// modelViewMatrixRight = GLKMatrix4Rotate(modelViewMatrixRight, GLKMathDegreesToRadians(-45.0f), 0.0f, 0.0f, 1.0f);
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrixRight, modelViewMatrixRight);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glUniform4fv(uniforms[UNIFORM_COLOR_VECTOR], 1, _color);
glBindVertexArrayOES( [my_line[i] getVertexArray] ); // make this line the current object
[my_line[i] render];
}
// draw the vertical gridlines
for (i=12; i<24; i++) {
modelViewMatrixRight = GLKMatrix4MakeTranslation(0.5f - 1.0f/11.0f * (float) (i-12), 0.0f, -2.0f);
modelViewMatrixRight = GLKMatrix4Rotate(modelViewMatrixRight, GLKMathDegreesToRadians(90.0f), 0.0f, 0.0f, 1.0f);
modelViewMatrixRight = GLKMatrix4Rotate(modelViewMatrixRight, GLKMathDegreesToRadians(60.0f), 1.0f, 0.0f, 1.0f);
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrixRight, modelViewMatrixRight);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glUniform4fv(uniforms[UNIFORM_COLOR_VECTOR], 1, _color);
glBindVertexArrayOES( [my_line[i] getVertexArray] ); // make this line the current object
[my_line[i] render];
}

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.

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 :)

OpenGL ES on iOS - glReadPixels() returns the image with a black bar on the side

i like to render a simple texture with my fragment shader to 4 vertices and read the image resolution with glReadPixels. I set the (readPixel) size like the (source)picture size but i didn't get a complete image back. There is always a black bar on the right side. And the image seems to be compressed.
The returned part of the image is correct. It shows the resolution of my sobel shader. So i didn't think that there are some errors on the ReadPixel part or the SetImage part. But i don't know...
Here is my method to set the image source:
-(void)setImageSource : (unsigned char*) image
{
static const GLfloat textureVertices[] =
{
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f,
};
static const GLfloat squareVertices[] =
{
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
glGenTextures(1, &pictureTexture);
glActiveTexture(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, pictureTexture);
glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageHeight, imageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
}
Here the part to render the texture:
-(void)render
{
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, imageHeight, imageWidth);
[self presentFramebuffer];
}
And here is the part to read the resolution back:
-(void)readPixels : (unsigned char*) dest
{
glReadPixels(0, 0, imageHeight, imageWidth, GL_RGBA, GL_UNSIGNED_BYTE, dest);
glDeleteTextures(1, &pictureTexture);
}
I don't have any idea where i make the error. I've searched on this forum and on the khronos group forum but i didn't get a solution for this (and i didn't find a case with the same error description).
Maybe another important or confusing information - I've also tried to put the code to a c++ class. But when i go outside the Objective C class with the EAGLContext i got the correct picture size back but the resolution is wrong the resolution image contains just snow but without the black bar on the side.
Did someone knew a solution for this error?
Regards,
krikit
i have solved the problem. The error was in the initialization of the OpenGL ES view. The part where i create the rectangle for the initWithFrame.
CGRectMake(0.0f, 0.0f, applicationFrame.size.width, applicationFrame.size.height)
There is the wrong size when i set the size by myself i get a complete picture in the destination.
The other part with the snow on my rendered picture comes from the wrong datatype. When i cast an variable to GLuint it's not the same then initialize a new GLuint variable and set it with the value... but i don't know why.
unsigned int j = 20
GLuint i = 20;
glReadPixels(0, 0, j, (GLuint)j, GL_RGBA, GL_UNSIGNED_BYTE, pictureDest);
When i work with the GLuint variables instead of the casted elements everything works fine.
krikit

OpenGL depth test problem

I've got a problem with OpenGL on mac, and I think the problem is the Depth test.
So, to my problem: Rather than explaining, I made two screenshots:
My scene from far: http://c0848462.cdn.cloudfiles.rackspacecloud.com/dd2267e27ad7d0206526b208cf2ea6910bcd00b4fa.jpg
And from near: http://c0848462.cdn.cloudfiles.rackspacecloud.com/dd2267e27a561b5f02344dca57508dddce21d2315f.jpg
If I do not draw the green floor, everything looks (kinda) fine. But still, like this it looks just aweful.
Here are the three codeblocks I use to set up Opengl:
+ (NSOpenGLPixelFormat*) defaultPixelFormat
{
NSOpenGLPixelFormatAttribute attributes [] = {
NSOpenGLPFAWindow,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16,
(NSOpenGLPixelFormatAttribute)nil
};
return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];
}
- (void) prepareOpenGL
{
NSLog(#"Preparing OpenGL");
glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
glEnable(GL_TEXTURE_2D);
glClearDepth(1);
glEnable(GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
- (void)reshape
{
NSLog(#"Reshaping view");
glViewport( 0, 0, (GLsizei)[self bounds].size.width, (GLsizei)[self bounds].size.height);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0, [self bounds].size.width / [self bounds].size.height, 0.1f /*Nearest render distance*/, 5000.0 /*Render distance*/);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
gluPerspective( 45.0, [self bounds].size.width / [self bounds].size.height, 0.1f /*Nearest render distance*/, 5000.0 /*Render distance*/);
That's way too small of a near clip plane. The closer your near clip value is to 0, the less precision you get on values that are farther away. Push your near clip back to at least 1.0, if not farther. In general, you should push it back as far away as you can live with.
Oh, and you should be using a 24-bit depth buffer, not 16-bit.