Reading the background suggested by Alfonse would be a good start … Just to add on the replacement for deprecated GL matrix stack, you are close but need to provide your own matrices. The vertex shader would need to be changed as follows by adding two uniforms
//Simple.vert (modified)
#version 330
in vec4 vertex;
// replace "in mat4 ortho_matrix;" with
uniform mat4 mvmatrix;
uniform mat4 pmatrix;
void main(void)
{
//ModelViewProjectionMatrix is deprecated so replace
//gl_Position = gl_ModelViewProjectionMatrix * vertex;
//with
gl_Position=pmatrix*mvmatrix*vertex;
}
so in you render function you would have to explicitly pass those two matrices just before your draw call with something like
// Draw
glUniformMatrix4fv(glGetUniformLocation(program, "mvmatrix"),1, GL_FALSE, your_modelview_matrix );
glUniformMatrix4fv(glGetUniformLocation(program, "pmatrix"),1, GL_FALSE, your_projection_matrix );
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
The only question that remains is how do you keep track/define your_modelview_matrix and your_projection_matrix? This is where everyone diverges but one helper here that I have found is the GLM OpenGL Mathematics Library because it contains all the matrix functions (rotation, translation, ortho, perspective, etc).
I have an old old code that I used when transitioning from old GL that may help you understand this better. Its a helloworld code that simply rotates a rectangle without any deprecated matrix functions (requires/based on GLM).
//main.c
#include <stdio.h>
// Ensure we are using opengl's core profile only
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>
#include <GL/glut.h>
#include <GL/freeglut_ext.h>
#include "gl3_matrix.h"
float time = 0.0;
GLuint program;
GLuint vao;
GLuint bon_vert; // buffer object name
size_t VertexArrayCount;
void cleanupGLshader(void) {
printf("Quiting, so cleanup GL shader resources
");
glDeleteBuffers(1,&bon_vert);
glDeleteVertexArrays(1,&vao);
glDeleteProgram(program);
}
void initGLshader(void)
{
//Create shaders for shader program
GLuint vshader=glCreateShader(GL_VERTEX_SHADER);
GLuint fshader=glCreateShader(GL_FRAGMENT_SHADER);
const GLchar *vshader_source[] =
{
"#version 150 core
"
"
"
"uniform mat4 mvmatrix;
"
"uniform mat4 pmatrix;
"
"in vec3 vert;
"
"
"
"void main() {
"
" gl_Position=pmatrix*mvmatrix*vec4(vert,1.);
"
"}
"
"
"
};
glShaderSource(vshader,1,vshader_source,NULL);
const GLchar *fshader_source[] =
{
"#version 150 core
"
"out vec4 fragcolor;
"
"
"
"void main() {
"
"
"
" fragcolor=vec4(0.0f,0.0f,1.0f,0.0f);
"
"}
"
"
"
};
glShaderSource(fshader,1,fshader_source,NULL);
glCompileShader(vshader);
glCompileShader(fshader);
//Create shader program
program=glCreateProgram();
glAttachShader(program,vshader);
glAttachShader(program,fshader);
glLinkProgram(program);
glUseProgram(program);
//done with shader source
glDeleteShader(fshader);
glDeleteShader(vshader);
//Get handles to shader uniforms
//... none for this simple vert/frag shader
//Datas destioned for video memory, can be local (and lost after bound to GPU!).
#define R 0.9
GLfloat vertices[] = { // in vec3 vert;
-R, R, 0.0, // xyz
-R, -R, 0.0,
R, R, 0.0,
R, -R, 0.0
};
VertexArrayCount=sizeof(vertices)/(sizeof(GLfloat)*3); // 3 for {x y z}
//Create geometry vertex array using Model definition
//use global GLuint vao;
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
//in vec3 vert;
//use global GLuint bon_vert; // buffer object name
glGenBuffers(1,&bon_vert);
glBindBuffer(GL_ARRAY_BUFFER,bon_vert);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*3*VertexArrayCount,vertices,GL_STATIC_DRAW);
const GLint loc_vert(glGetAttribLocation(program,"vert"));
glVertexAttribPointer(loc_vert,3,GL_FLOAT,GL_TRUE,0,NULL);
glEnableVertexAttribArray(loc_vert);
//when exiting delete shared GL resources
atexit(cleanupGLshader);
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
gl3MatrixMode_GL_PROJECTION();
gl3LoadIdentity();
gl3Ortho(-2,2, -2,2, -2,2);
gl3MatrixMode_GL_MODELVIEW();
gl3LoadIdentity();
glu3LookAt(0.f,0.f,1.f, 0.f,0.f,0.f, 0.f,1.f,0.f);
}
void timer(int dt)
{
time += dt/1000.; // time in seconds
glutTimerFunc(16,timer,16);
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl3PushMatrix();
gl3Rotatef(time*360.0/4.0, 0.0, 0.0, 1.0 );
// pass openGL matrices to shader
glUniformMatrix4fv(glGetUniformLocation(program, "mvmatrix"),
1, GL_FALSE, glGetFloatv_GL_MODELVIEW_MATRIX() );
glUniformMatrix4fv(glGetUniformLocation(program, "pmatrix"),
1, GL_FALSE, glGetFloatv_GL_PROJECTION_MATRIX() );
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_STRIP,0,VertexArrayCount);
gl3PopMatrix();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
//Create window with GL 3.2 Core context using freeglut
glutInit(&argc, argv);
glutInitContextVersion(3,2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("gl3.2 freeglut HelloWorld");
printf("OpenGL %s, GLSL %s
", glGetString(GL_VERSION),
glGetString(GL_SHADING_LANGUAGE_VERSION));
initGLshader();
glutReshapeFunc(reshape);
glutTimerFunc(16,timer,16);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
//custom public interface to make GLM purposefully with API like
// old GL
#ifndef GL3_MATRIX_H
#define GL3_MATRIX_H
void gl3LoadIdentity(void);
void gl3MatrixMode_GL_MODELVIEW(void);
void gl3MatrixMode_GL_PROJECTION(void);
void gl3MultMatrixf( const float *m );
void gl3MultMatrixd( const double *m );
void gl3Ortho(float _left, float _right, float _bottom, float _top, float _zNear, float _zFar );
void gl3PopMatrix(void );
void gl3PushMatrix(void );
void gl3Rotatef(float _angle, float _x, float _y, float _z );
void gl3Scalef(float _x, float _y, float _z );
void gl3Translatef(float _x, float _y, float _z);
void glGetDoublev_GL_MODELVIEW_MATRIX(double *matrix);
void glGetDoublev_GL_PROJECTION_MATRIX(double *projection);
const float *glGetFloatv_GL_MODELVIEW_MATRIX(void);
const float *glGetFloatv_GL_PROJECTION_MATRIX(void);
void glu3LookAt( double eyeX, double eyeY, double eyeZ,
double centerX, double centerY, double centerZ,
double upX, double upY, double upZ );
void glu3Perspective( double fovy, double aspect, double zNear, double zFar );
void glu3PickMatrix(double x, double y, double deltax, double deltay, int viewport[4]);
#endif
//gl3_matrix.cpp
#include <stack>
//OpenGL Mathematics (GLM). A C++ mathematics library for 3D graphics.
#include "glm-0.9.1.a/glm/glm.hpp"
#include "glm-0.9.1.a/glm/ext.hpp"
class CustomGraphicsPipeline
{
public:
std::stack<glm::mat4> modelmatrix;
std::stack<glm::mat4> projectionmatrix;
std::stack<glm::mat4> *currentmatrix;
CustomGraphicsPipeline() {
modelmatrix.push( glm::mat4(1.0f) ); // identity matrix
projectionmatrix.push( glm::mat4(1.0f) ); // identity matrix
currentmatrix = &modelmatrix;
};
void LoadIdentity(void) {
currentmatrix->top() = glm::mat4(1.0);
};
void MatrixMode_ModelView() {
currentmatrix = &modelmatrix;
};
void MatrixMode_Projection() {
currentmatrix = &projectionmatrix;
};
void MultMatrixd( const double *m ) {
float mf[] = {
m[ 0], m[ 1], m[ 2], m[ 3],
m[ 4], m[ 5], m[ 6], m[ 7],
m[ 8], m[ 9], m[10], m[11],
m[12], m[13], m[14], m[15]
};
glm::mat4 *glmmat = (glm::mat4*)&mf[0];
currentmatrix->top() *= (*glmmat);
};
void MultMatrixf( const float *m ) {
glm::mat4* glmmat = (glm::mat4*)m;
currentmatrix->top() *= (*glmmat);
};
void Ortho(float left, float right, float bottom, float top, float zNear, float zFar ) {
currentmatrix->top() *= glm::ortho(left, right, bottom, top, zNear, zFar );
};
void Rotatef(float angle, float x, float y, float z ) {
currentmatrix->top() *= glm::rotate(angle, glm::vec3(x, y, z) );
};
void Scalef(float x, float y, float z ) {
currentmatrix->top() *= glm::scale( glm::vec3(x,y,z) );
};
void Translatef(float x, float y, float z) {
currentmatrix->top() *= glm::translate( glm::vec3(x,y,z) );
};
void push() {
currentmatrix->push(currentmatrix->top());
};
void pop() {
currentmatrix->pop();
};
void LookAt( double eyeX, double eyeY, double eyeZ,
double centerX, double centerY, double centerZ,
double upX, double upY, double upZ ) {
currentmatrix->top() *= glm::lookAt( glm::vec3(eyeX,eyeY,eyeZ),
glm::vec3(centerX,centerY,centerZ),
glm::vec3(upX,upY,upZ) );
};
void Perspective( float fovy, float aspect, float zNear, float zFar ) {
currentmatrix->top() *= glm::perspective( fovy, aspect, zNear, zFar );
};
void PickMatrix(double x, double y, double deltax, double deltay, int viewport[4]){
// modified from from /Mesa-7.7/src/glu/sgi/libutil/project.c
if (deltax <= 0 || deltay <= 0) { return; }
/* Translate and scale the picked region to the entire window */
Translatef((viewport[2] - 2 * (x - viewport[0])) / deltax,
(viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
Scalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
};
glm::mat4 *getmodelmatrix() {
return &modelmatrix.top();
};
glm::mat4 *getprojectionmatrix() {
return &projectionmatrix.top();
};
};
static CustomGraphicsPipeline z;
void gl3LoadIdentity(void) {
z.LoadIdentity();
};
void gl3MatrixMode_GL_MODELVIEW(void){
z.MatrixMode_ModelView();
};
void gl3MatrixMode_GL_PROJECTION(void){
z.MatrixMode_Projection();
};
void gl3MultMatrixd( const double *m ){
z.MultMatrixd(m);
};
void gl3MultMatrixf( const float *m ){
z.MultMatrixf(m);
};
void gl3Ortho(float _left, float _right, float _bottom, float _top, float _zNear, float _zFar ){
z.Ortho(_left, _right, _bottom, _top, _zNear, _zFar );
};
void gl3PopMatrix(void ){
z.pop();
};
void gl3PushMatrix(void ){
z.push();
};
void gl3Rotatef(float _angle, float _x, float _y, float _z ){
z.Rotatef(_angle, _x, _y, _z );
};
void gl3Scalef(float _x, float _y, float _z ){
z.Scalef(_x,_y,_z);
};
void gl3Translatef(float _x, float _y, float _z){
z.Translatef(_x,_y,_z);
};
void glGetDoublev_GL_MODELVIEW_MATRIX(double *m) {
const float *in = (const float*)z.getmodelmatrix();
m[0]=in[0]; m[4]=in[4]; m[ 8]=in[ 8]; m[12]=in[12];
m[1]=in[1]; m[5]=in[5]; m[ 9]=in[ 9]; m[13]=in[13];
m[2]=in[2]; m[6]=in[6]; m[10]=in[10]; m[14]=in[14];
m[3]=in[3]; m[7]=in[7]; m[11]=in[11]; m[15]=in[15];
};
void glGetDoublev_GL_PROJECTION_MATRIX(double *m) {
const float *in = (const float*)z.getprojectionmatrix();
m[0]=in[0]; m[4]=in[4]; m[ 8]=in[ 8]; m[12]=in[12];
m[1]=in[1]; m[5]=in[5]; m[ 9]=in[ 9]; m[13]=in[13];
m[2]=in[2]; m[6]=in[6]; m[10]=in[10]; m[14]=in[14];
m[3]=in[3]; m[7]=in[7]; m[11]=in[11]; m[15]=in[15];
};
const float *glGetFloatv_GL_MODELVIEW_MATRIX() {
return (const float*)z.getmodelmatrix();
};
const float *glGetFloatv_GL_PROJECTION_MATRIX() {
return (const float*)z.getprojectionmatrix();
};
void glu3LookAt( double eyeX, double eyeY, double eyeZ,
double centerX, double centerY, double centerZ,
double upX, double upY, double upZ ){
z.LookAt(eyeX, eyeY, eyeZ,
centerX, centerY, centerZ,
upX, upY, upZ );
};
void glu3Perspective( double fovy, double aspect, double zNear, double zFar ){
z.Perspective( fovy, aspect, zNear, zFar );
};
void glu3PickMatrix(double x, double y, double deltax, double deltay, int viewport[4]){
z.PickMatrix(x, y, deltax, deltay, viewport);
};
Note the glm library was downloaded and remamed glm-0.9.1.a to be clear what version – ie just make sure the two header lines referring to glm point to wherever you actually put glm on your system. I wouldn’t normally do that but glm is still in flux and header locations/files sometimes have been moved around from one version to the next – hopefully in time that will settle down and stop.
#include "glm-0.9.1.a/glm/glm.hpp"
#include "glm-0.9.1.a/glm/ext.hpp"