entire program modified from example (example did no depth stuff):
// Globals
int gLastFrameTime;
GLuint pyramid_vbo;
GLuint pyramid_ebo;
GLuint pyramid_vao;
GLuint main_shader;
double gProjectionMatrix[16];
float gProjectionMatrixf[16];
float gOrthoProjectionMatrixf[16];
double gModelViewMatrix[16];
float gModelViewMatrixf[16];
int screen_width = 640, screen_height = 480;
/* Shader source */
/******************************************************************************/
// Basic shader
const GLchar* basicVertexShaderSource =
GLSL_COMPAT_STRING
TO_STRING(
in vec4 in_position;
in vec3 in_color;
uniform mat4 in_proj_matrix;
uniform mat4 in_modelview_matrix;
out vec3 color;
out vec4 pos;
void main()
{
color = in_color;
gl_Position = pos = in_proj_matrix * in_modelview_matrix* in_position;
}
);
const GLchar* basicFragmentShaderSource =
GLSL_COMPAT_STRING
TO_STRING(
in vec3 color;
out vec4 out_color;
in vec4 pos;
void main()
{
//fragment color
out_color = vec4(color, 1.0f);
//fragment depth, required for depth testing to work
//gl_FragDepth = pos.z/pos.w;//gl_FragCoord.z;
}
);
/* Geometry data */
/******************************************************************************/
#define NUM_PYR_VERTS 5
#define NUM_PYR_TRIS 6
static float pyramid_verts[NUM_PYR_VERTS][3] =
{
//base
{ -5.0, -5.0, 0.0 }, { 5.0, -5.0, 0.0 }, { 5.0, 5.0, 0.0 }, { -5.0, 5.0, 0.0 },
//pinnacle peak...
{ 0.0, 0.0, 5.0 }
};
static float pyramid_colors[NUM_PYR_VERTS][3] =
{
//base
{ 1.0, 0.0, 0.0 }, { 0.5, 0.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 },
// peak...
{ 0.0, 1.0, 0.0 }
};
static unsigned int pyramid_inds[NUM_PYR_TRIS][3] =
{
{0,1,2},{2,3,0},{0,1,4},{1,2,4},{2,3,4},{3,0,4}
};
/******************************************************************************/
void matrixIdentity(double A[16])
{
size_t bytes = 16*sizeof(double);
printf("bytes: %d
", bytes );
bzero(A, bytes);
A[0] = A[5] = A[10] = A[15] = 1.0;
}
void matrixTranslate(double A[16], double tx, double ty, double tz)
{
bzero(A, 16*sizeof(double));
A[0] = A[5] = A[10] = A[15] = 1.0;
A[12] = tx;
A[13] = ty;
A[14] = tz;
}
//http://www.cprogramming.com/tutorial/3d/rotationMatrices.html
void matrixRotateX(double A[16], double angle)
{
double angled = DEG2RAD(angle);
bzero(A, 16*sizeof(double));
A[0] = A[15] = 1.0;
A[5] = cos(angled);
A[6] = -sin(angled);
A[9] = sin(angled);
A[10] = cos(angled);
}
void matrixRotateY(double A[16], double angle)
{
double angled = DEG2RAD(angle);
bzero(A, 16*sizeof(double));
A[5] = A[15] = 1.0;
A[0] = cos(angled);
A[2] = sin(angled);
A[8] = -sin(angled);
A[10] = cos(angled);
}
void matrixRotateZ(double A[16], double angle)
{
double angled = DEG2RAD(angle);
bzero(A, 16*sizeof(double));
A[10] = A[15] = 1.0;
A[0] = cos(angled);
A[1] = -sin(angled);
A[4] = sin(angled);
A[5] = cos(angled);
}
void matrixMultiply(double A[16], double B[16], double C[16])
{
int i, j, k;
for ( i=0;i<4;i++ ) {
for ( j=0;j<4;j++ ) {
C[MAT4_INDEX(i,j)] = A[MAT4_INDEX(i,0)] * B[MAT4_INDEX(0,j)];
for (k=1;k<4;k++) {
C[MAT4_INDEX(i,j)] += A[MAT4_INDEX(i,k)] * B[MAT4_INDEX(k,j)];
}
}
}
}
void matrixPrint(double mat[16])
{
int i, j;
for (j=0;j<4;j++) {
for (i=0;i<4;i++) {
printf("%4.2f ", mat[MAT4_INDEX(i,j)]);
}
printf("
");
}
}
void matrixfPrint(float mat[16])
{
int i, j;
for (j=0;j<4;j++) {
for (i=0;i<4;i++) {
printf("%4.2f ", mat[MAT4_INDEX(i,j)]);
}
printf("
");
}
}
/******************************************************************************/
GLuint utilCompileShader(GLenum shaderType, const GLchar *source)
{
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status)
{
printf("shader compile error: %s ", source );
return 0;
}
return shader;
}
/******************************************************************************/
//http://www.songho.ca/opengl/gl_projectionmatrix.html
void utilCreateFrustum( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal,
GLdouble *mat)
{
double A = (right+left)/(right-left);
double B = (top+bottom)/(top-bottom);
double C = (farVal+nearVal)/(farVal-nearVal);
double D = (2.0*farVal*nearVal)/(farVal-nearVal);
int i;
for (i=0;i<16;i++) { mat[i] = 0.0; }
mat[0] = (2.0*nearVal)/(right-left);
mat[5] = (2.0*nearVal)/(top-bottom);
mat[8] = A;
mat[9] = B;
mat[10] = C;
mat[11] = -1.0;
mat[14] = D;
}
/******************************************************************************/
void setup_proj(GLuint width, GLuint height)
{
int i;
if (width ==0)
width = 1;
float nearPlane = 0.1f;
float farPlane = 1000.0f;
GLfloat h = (GLfloat) height / (GLfloat) width;
glViewport(0, 0, (GLint) width, (GLint) height);
utilCreateFrustum(-1.0f*nearPlane,
nearPlane,
-h*nearPlane,
h*nearPlane,
nearPlane,
farPlane,
gProjectionMatrix);
for(i=0;i<16;i++) { gProjectionMatrixf[i] = gProjectionMatrix[i];}
}
/******************************************************************************/
void utilCreateOrtho(float w, float h, GLdouble mat[16])
{
GLdouble left = 0;
GLdouble right = w;
GLdouble bottom = 0;
GLdouble top = h;
GLdouble near = -1.0;
GLdouble far = 1.0;
GLdouble tx = -(right+left)/(right-left);
GLdouble ty = -(top+bottom)/(top-bottom);
GLdouble tz = -(far+near)/(far-near);
int i=0;
for (i=0;i<16;i++) { mat[i] = 0.0;}
mat[0] = (2.0/(right-left));
mat[5] = (2.0/(top-bottom));
mat[10] = -(2.0/(far-near));
mat[12] = tx;
mat[13] = ty;
mat[14] = tz;
mat[15] = 1.0;
}
/******************************************************************************/
//if we wanted 2D...
void setup_ortho(GLuint width, GLuint height)
{
if (width ==0)
width = 1;
double mat[16];
int i;
glViewport(0, 0, (GLint) width, (GLint) height);
utilCreateOrtho(width, height, mat);
for (i=0;i<16;i++) {gOrthoProjectionMatrixf[i] = mat[i]; }
}
void createShaders()
{
GLint status;
// The basic shader for the geometry
main_shader = glCreateProgram();
GLuint vertexShader= utilCompileShader(GL_VERTEX_SHADER,
basicVertexShaderSource);
GLuint fragmentShader = utilCompileShader(GL_FRAGMENT_SHADER,
basicFragmentShaderSource);
glAttachShader(main_shader, vertexShader);
glAttachShader(main_shader, fragmentShader);
glBindFragDataLocationEXT(main_shader, 0, "out_color");
glLinkProgram(main_shader);
glGetProgramiv(main_shader, GL_LINK_STATUS, &status);
if (!status) {
printf("program link error
");
}
}
void createVertexBuffers()
{
int sizeInBytes = 0;
glGenVertexArrays(1, &pyramid_vao);
glBindVertexArray(pyramid_vao);
sizeInBytes = sizeof(float)*3*NUM_PYR_VERTS;
glGenBuffers(1, &pyramid_vbo);
glBindBuffer(GL_ARRAY_BUFFER, pyramid_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeInBytes*2, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeInBytes, pyramid_verts);
glBufferSubData(GL_ARRAY_BUFFER, sizeInBytes, sizeInBytes, pyramid_colors);
GLuint positionLoc = glGetAttribLocation(main_shader, "in_position");
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(positionLoc);
positionLoc = glGetAttribLocation(main_shader, "in_color");
glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, sizeInBytes);
glEnableVertexAttribArray(positionLoc);
sizeInBytes = sizeof(unsigned int)*3*NUM_PYR_TRIS;
glGenBuffers(1, &pyramid_ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramid_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeInBytes, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeInBytes, pyramid_inds);
glBindVertexArray(0);
}
/******************************************************************************/
void render_3d()
{
glUseProgram(main_shader);
int i;
double test[16];
//uniforms are given after selecting the shader program
//this is how the matrixes are given to the shader
GLuint projMatrixLoc = glGetUniformLocation(main_shader, "in_proj_matrix");
glUniformMatrix4fv(projMatrixLoc, 1, GL_FALSE, gProjectionMatrixf);
GLuint mvMatrixLoc = glGetUniformLocation(main_shader, "in_modelview_matrix");
glUniformMatrix4fv(mvMatrixLoc, 1, GL_FALSE, gModelViewMatrixf);
glBindVertexArray(pyramid_vao);
glDrawElements(GL_TRIANGLES, 3*3, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
//glDrawElements(GL_TRIANGLES, NUM_PYR_TRIS*3, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glBindVertexArray(0);
}
static void processing()
{
double T[16];
double R[16];
int i;
static float t = 0.0;
setup_proj(screen_width, screen_height);
t += 1.0;
// transform the geometry
matrixTranslate(T , 0, 0, -10);
matrixRotateX(R, t);
matrixMultiply(T, R, gModelViewMatrix);
// copy doubles to float
for(i=0;i<16;i++) { gModelViewMatrixf[i] = gModelViewMatrix[i];}
}
/******************************************************************************/
void cbDisplay()
{
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render_3d();
glutSwapBuffers();
}
/******************************************************************************/
void cbReshape(int width, int height)
{
screen_width = width;
screen_height = height;
}
/******************************************************************************/
void cbIdle()
{
processing();
glutPostRedisplay();
}
/******************************************************************************/
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(screen_width, screen_height);
glutCreateWindow("");
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
createShaders();
createVertexBuffers();
glutDisplayFunc(cbDisplay);
glutReshapeFunc(cbReshape);
glutIdleFunc(cbIdle);
glutMainLoop();
return EXIT_SUCCESS;
}
/******************************************************************************/