Lighting and OpenGL ES - opengl-es

I'm working on getting a simple lighting right on my OpenGL ES iPhone scene. I'm displaying a simple object centered on the origin, and using an arcball to rotate it by touching the screen. All this works nicely, except I try to add one fixed light (fixed w.r.t. eye position) and it is badly screwed: the whole object (an icosahedron in this example) is lit uniformly, i.e. it all appears in the same color.
I have simplified my code as much as possible so it's standalone and still reproduces what I experience:
glClearColor (0.25, 0.25, 0.25, 1.);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable (GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrthof(-1, 1, -(float)backingWidth/backingHeight, (float)backingWidth/backingHeight, -10, 10);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { -1.5f, 1.0f, -400.0f, 0.0f };
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
float currRot[4];
[arcball getCurrentRotation:currRot];
glRotatef (currRot[0], currRot[1], currRot[2], currRot[3]);
float f[4];
f[0] = 0.5; f[1] = 0; f[2] = 0; f[3] = 1;
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, f);
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, f);
f[0] = 0.2; f[1] = 0.2; f[2] = 0.2; f[3] = 1;
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, f);
glEnableClientState (GL_VERTEX_ARRAY);
drawSphere(0, 0, 0, 1);
where the drawSphere function actually draws an icosahedron:
static void drawSphere (float x, float y, float z, float rad)
{
glPushMatrix ();
glTranslatef (x, y, z);
glScalef (rad, rad, rad);
// Icosahedron
const float vertices[] =
{ 0., 0., -1., 0., 0., 1., -0.894427, 0., -0.447214, 0.894427, 0.,
0.447214, 0.723607, -0.525731, -0.447214, 0.723607, 0.525731,
-0.447214, -0.723607, -0.525731, 0.447214, -0.723607, 0.525731,
0.447214, -0.276393, -0.850651, -0.447214, -0.276393, 0.850651,
-0.447214, 0.276393, -0.850651, 0.447214, 0.276393, 0.850651,
0.447214 };
const GLubyte indices[] =
{ 1, 11, 7, 1, 7, 6, 1, 6, 10, 1, 10, 3, 1, 3, 11, 4, 8, 0, 5, 4, 0,
9, 5, 0, 2, 9, 0, 8, 2, 0, 11, 9, 7, 7, 2, 6, 6, 8, 10, 10, 4, 3,
3, 5, 11, 4, 10, 8, 5, 3, 4, 9, 11, 5, 2, 7, 9, 8, 6, 2 };
glVertexPointer (3, GL_FLOAT, 0, vertices);
glDrawElements (GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, indices);
glPopMatrix ();
}
A movie of what I see as the result is here. Thanks to anyone who can shed some light into this (no kidding!). I'm sure it will look embarassingly trivial to someone, but I swear I have looked at many lighting tutorials before this and am stuck.

Try adding some vertex normals using glNormalPointer(). It looks like OpenGL ES is just using the default normal for everything.

Related

Not getting the correct EigenValue/EigenVector (eigenVV)

I'm trying to figure out how to use eigenVV, but no luck so far. The following is my code and could anyone of you point out what I'm doing wrong? Thanks.
CvMat* A2;
A2 = cvCreateMat(3, 3, CV_32FC1);
cvmSet(A2, 0, 0, 1);
cvmSet(A2, 0, 1, 3);
cvmSet(A2, 0, 2, -3);
cvmSet(A2, 1, 0, -3);
cvmSet(A2, 1, 1, 7);
cvmSet(A2, 1, 2, -3);
cvmSet(A2, 2, 0, -6);
cvmSet(A2, 2, 1, 6);
cvmSet(A2, 2, 1, -2);
CvMat* transp_A2;
CvMat* ATA2;
CvMat* eigenVal2;
CvMat* eigenVec2;
transp_A2 = cvCreateMat(3, 3, CV_32FC1);
ATA2 = cvCreateMat(3, 3, CV_32FC1);
eigenVal2 = cvCreateMat(3, 1, CV_32FC1);
eigenVec2 = cvCreateMat(3, 3, CV_32FC1);
cvTranspose(A2, transp_A2);
cvMatMul(transp_A2, A2, ATA2);
cvEigenVV(ATA2, eigenVec2, eigenVal2);
Edit :
This is output of eigenVec2 variable
-0.236854,0.862897,-0.446442,
0.969565,0.239264,-0.0519332,
-0.0620046,0.445154,0.893304,
I wanted to use that EigenVector EigenValue to create projection matrix and comparing it against with projection matrix I have. I thought my answer was wrong when it doesn't match with the one I have. But I figured out the resulting projection matrix is not exactly the same. It is differed by scale factor. So the way I use eigenvv is correct.

How to rotate (after a 90 degrees rotation in x axis ) in the new coordinates on the y axis in openGL es 2.0

I'm rotation a cube 90 degrees in x axis, after that I want to rotate in another 90 degrees in y axis but it does get the expected(from me) result since it was rotated before
I'd like rotation to happen lets say in world coordinates ... My current code I think is resetting the identity matrix but if I remove that line nothing renders.Here is my code:
public void onDrawFrame(GL10 arg0) {
// GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(iProgId);
cubeBuffer.position(0);
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, cubeBuffer);
GLES20.glEnableVertexAttribArray(iPosition);
texBuffer.position(0);
GLES20.glVertexAttribPointer(iTexCoords, 3, GLES20.GL_FLOAT, false, 0, texBuffer);
GLES20.glEnableVertexAttribArray(iTexCoords);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, iTexId);
GLES20.glUniform1i(iTexLoc, 0);
Matrix.setIdentityM(m_fIdentity, 0);
if(rotating == true)
{
rotate();
}
Matrix.rotateM(m_fIdentity, 0, -xAngle, 0, 1, 0);
Matrix.rotateM(m_fIdentity, 0, -yAngle, 1, 0, 0);
Matrix.multiplyMM(m_fVPMatrix, 0, m_fViewMatrix, 0, m_fIdentity, 0);
Matrix.multiplyMM(m_fVPMatrix, 0, m_fProjMatrix, 0, m_fVPMatrix, 0);
// Matrix.translateM(m_fVPMatrix, 0, 0, 0, 1);
GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, m_fVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
// GLES20.glDisable(GLES20.GL_TEXTURE_CUBE_MAP);
}

glMultiDrawElements stops my code

I'm trying to learn OpenGL with "the redbook", and I'm now at the point were I'm testing glMultiDrawElements. I already got my code to work with glDrawElements, and other "simpler" methods, but it stops working here, and now I'm completly stuck. My code is supposed to draw a cube, and the acctuall drawing code is posted under:
GLfloat verticies[] = {-0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5};
glVertexPointer(3, GL_FLOAT, 0, verticies);
GLubyte front[] = {4, 5, 6, 7};
GLubyte left[] = {0, 3, 7, 4};
GLubyte right[] = {5, 1, 2, 6};
GLubyte back[] = {0, 1, 2, 3};
GLubyte bottom[] = {0, 1, 5, 4};
GLubyte topp[] = {2, 3, 7, 6};
GLvoid *faces[6] = {front, left, right, back, bottom, topp};
glMultiDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, faces, 6);
glFlush();
The program is cocoa based, and compile fine, but stops under running due to "EXC_BAD_ACCESS". There is a yellow warning triangle next to glMultiDrawElements(..) saying "incompatible integer to pointer conversion", but i tought i was using pointers in the "faces" array (at least that exactly how it looks in "the red book"). Can somone help me?
The second parameter to glMultiDrawElements() is a pointer to an array of sizes, not a numerical value for a size. This is why the compiler is complaining about an integer to pointer conversion (which, by the way, is another reason why you should enable the compiler flag for turning warnings into errors when doing Cocoa development).
I believe changing the above to read
GLsizei count[] = {4, 4, 4, 4, 4, 4};
glMultiDrawElements(GL_QUADS, count, GL_UNSIGNED_BYTE, faces, 6);
should work, but I haven't tested it here.

Open GLES 1.1 - GLColorPointer creates a rainbow of colours when I just want red

I'm rendering an object like this:
for (int i = 0; i < COLOR_ARRAY_SIZE; i += 4) {
colors[i] = 1.0f;
colors[i + 1] = 0.0f;
colors[i + 2] = 0.0f;
colors[i + 3] = 1.0f;
}
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set GL11 flags:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_DEPTH_TEST);
// make sure nothing messes with the colour
glDisable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glShadeModel(GL_FLAT);
// Load projection matrix:
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projectionMatrix);
// Load model view matrix and scale appropriately
int kObjectScale = 300f;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(modelViewMatrix);
glTranslatef(0.5f, 0.5f, 0.5f);
glScalef(kObjectScale, kObjectScale, kObjectScale);
// Draw object
glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &vertexPositions[0]);
glNormalPointer(GL_FLOAT, 0, (const GLvoid*) &vertexNormals[0]);
glColorPointer(4, GL_FLOAT, 0, (const GLvoid*) &colors[0]);
glDrawElements(GL_TRIANGLES, 11733, GL_UNSIGNED_SHORT,
(const GLvoid*) &indices[0]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
I would expect that this would render my object all in red, but instead it's a rainbow of different colours. Does anyone know why? I would assume that there is something wrong with my "colors" array buffer but I can't for the life of me see what it is. The actual vertices seem to rendered just fine.
Your for loop is very confused. You're incrementing your value of i by 4 each time. What's more is that you're indexing with an offset of 1, 2 and 3 in lines 3-5. I presume that your define of COLOR_ARRAY_SIZE is 4? Try initializing your color array as follows:
float colors[] = {1.0f, 0.0f, 0.0f, 1.0f};
And then calling glColorPointer as follows:
glColorPointer(4, GL_FLOAT, 0, colors);
Notice that I've set the stride to be 0. If your color array only contains colors then I don't see any reason why you should be using a stride (stride is used to jump over interwoven information in an array).

Whats the difference between these two OpenGL calls (Basic OpenGL Question)?

It's a really stupid, basic question, but: Can someone please tell me the difference between:
glBegin(GL_QUADS);
glTexCoord3f(0, 0, 0); glVertex3f(0, 1, 0);
glTexCoord3f(1, 0, 0); glVertex3f(1, 1, 0);
glTexCoord3f(1, 1, 0); glVertex3f(1, 0, 0);
glTexCoord3f(0, 1, 0); glVertex3f(0, 0, 0);
glEnd();
and
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
width, 0, 0,
0, height, 0,
width, height, 0
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
(width & height is the texture size in pixel)
I can't really understand why, but if I use the second code (because OpenGL ES compatible) my texture is on the y-axis inverted. What I'm doing wrong?
Edit:
I dont know, if its relevant - maybe i made a mistake at init the viewport for 2D drawing?
GLint iViewport[4];
glGetIntegerv( GL_VIEWPORT, iViewport );
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho( iViewport[0], iViewport[0]+iViewport[2], iViewport[1]+iViewport[3], iViewport[1], -1, 1 );
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
Sticking to the simplest, you have 4 vertices with texcoords. Here they are put in parallel:
texcoord/vert
0, 0, / 0, 1
1, 0, / 1, 1
1, 1, / 1, 0
0, 1, / 0, 0
0, 0 / 0, 0
1, 0 / width, 0
0, 1 / 0, height
1, 1 / width, height
Now, if we reorder them by verts, you can see that the texcoords do not correspond
// sorted verts by "alphabetical" position.
0, 1, / 0, 0
0, 0, / 0, 1
1, 1, / 1, 0
1, 0, / 1, 1
0, 0 / 0, 0
0, 1 / 0, height
1, 0 / width, 0
1, 1 / width, height
As you can see, for each equivalent position, the second texture coordinate is inverted between the 2. That explains why the textures are y-flipped.
So if you want to fix it, simply flip them back on the second method:
const GLfloat texCoords[] = {
0, 1,
1, 1,
0, 0,
1, 0
};
Try using the same geometry in each case:
Immediate mode:
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0, 0); glVertex3f(1, 0, 0);
glTexCoord2f(1, 1, 0); glVertex3f(1, 1, 0);
glTexCoord2f(1, 1, 0); glVertex3f(1, 1, 0);
glTexCoord2f(0, 1, 0); glVertex3f(0, 1, 0);
glTexCoord2f(0, 0, 0); glVertex3f(0, 0, 0);
glEnd();
Vertex arrays:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
width, 0, 0,
width, height, 0
width, height, 0
0, height, 0,
0, 0, 0,
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
1, 1
1, 1
0, 1,
0, 0,
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
Ok, try this complete GLUT program. I actually tested it this time around :)
#include <vector>
#include <GL/glut.h>
using namespace std;
size_t win_w = 0;
size_t win_h = 0;
double aspect_ratio = 0;
GLuint tex_obj;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10*aspect_ratio, 10*aspect_ratio, -10, 10, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glPushMatrix();
glScalef(5,5,0);
/*
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(1, 0); glVertex3f(1, 0, 0);
glTexCoord2f(1, 1); glVertex3f(1, 1, 0);
glTexCoord2f(1, 1); glVertex3f(1, 1, 0);
glTexCoord2f(0, 1); glVertex3f(0, 1, 0);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glEnd();
*/
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat vertexData[] = {
0, 0, 0,
1, 0, 0,
1, 1, 0,
1, 1, 0,
0, 1, 0,
0, 0, 0,
};
const GLfloat texCoords[] = {
0, 0,
1, 0,
1, 1,
1, 1,
0, 1,
0, 0,
};
glVertexPointer(3, GL_FLOAT, 0, &vertexData);
glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
win_w = w;
win_h = h;
aspect_ratio = (double)win_w / (double)win_h;
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Aspect Ratio");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex_obj);
glBindTexture(GL_TEXTURE_2D, tex_obj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
vector< unsigned char > pixels(4 * 3);
pixels[3*0+0] = 255;
pixels[3*0+1] = 0;
pixels[3*0+2] = 0;
pixels[3*1+0] = 0;
pixels[3*1+1] = 255;
pixels[3*1+2] = 0;
pixels[3*2+0] = 0;
pixels[3*2+1] = 0;
pixels[3*2+2] = 255;
pixels[3*3+0] = 255;
pixels[3*3+1] = 255;
pixels[3*3+2] = 255;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

Resources