PDA

View Full Version : Orthographics View



_ShaderRookie_
02-02-2011, 11:54 AM
Hello.
I am currently trying to migrate to OpenGL 3.2.
I am not very experienced with OpenGL 1.5 but managed to get some simple Games going. I actually managed to port my VBO-Code to 3.2 and to render some triangles and stuff.
Since I mostly make 2D Games, I want of course my orthographic view back.
Since glOrtho is banned in 3.2, I am a bit lost.
So, I managed to render my Quad:


const GLfloat vertices[8] = {0.0f, 2.0f,
0.0f, 0.0f,
2.0f, 2.0f,
2.0f, 0.0f};

float col[12];
col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f;
col[3] = 0.0f; col[4] = 1.0f; col[5] = 0.0f;
col[6] = 0.0f; col[7] = 0.0f; col[8] = 1.0f;
col[9] = 0.0f; col[10] = 0.0f; col[11] = 1.0f;

m_shader = shader;
m_shader->attach();

GLuint vertLocation = 0;
GLuint colorLocation = 0;

// Get Location of uniforms
vertLocation = ShaderLoader::getAttribLocation(m_shader, "vertex");
colorLocation = ShaderLoader::getAttribLocation(m_shader, "fragColor");
GLuint matLocation = ShaderLoader::getAttribLocation(m_shader, "ortho_matrix");
glm::mat4 ortho = glm::ortho<float>(0.0f, 1024, 768, 0, -1.0f, 1.0f);
glUniformMatrix4fv(matLocation, 16, 0, glm::value_ptr(ortho));

// Create Vertex Array
glGenVertexArrays(1, &amp;m_VAObj);
glBindVertexArray(m_VAObj);

// Create 2 VBO
glGenBuffers(2, m_VBObj);
glBindBuffer(GL_ARRAY_BUFFER, m_VBObj[0]);

// Bind Vertex data
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(f32), vertices, GL_STREAM_DRAW);

// Index 0, 3 floats per vertex
glVertexAttribPointer(vertLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Enable Index 0
glEnableVertexAttribArray(vertLocation);

// VBO for color
glBindBuffer(GL_ARRAY_BUFFER, m_VBObj[1]);

// Send Color Data
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), col, GL_STATIC_DRAW);

// Index 1, 4 floats per color
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);

// Enable Index 1
glEnableVertexAttribArray(colorLocation);

// Unbind
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_shader->detach();


This are my shaders:


//Simple.vert
#version 330

in vec4 vertex;
in mat4 ortho_matrix;

void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vertex;
}

// Simple.frag:
#version 330

out vec4 fragColor;

void main(void)
{
fragColor = vec4(0.0, 0.0, 0.5, 1.0);
}




// Rendering:
m_shader->attach();

// Bind
glBindVertexArray(m_VAObj);
glBindBuffer(GL_ARRAY_BUFFER, m_VAObj);

// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Unbind
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

m_shader->detach();




When I do glModelViewProjectionMatrix*ortho_matrix, I get some errors.
Also, the color I bind in my code, does not seem to have any impact.If I remove the Line in the fragment Shader, the Quad renders in Black.
I crawled the net since some days, but all Shader Tutorials I find are for pre-3.2 only and they use deprecated stuff...
Any help? I don't want the whole bible, but maybe a chapter.

Alfonse Reinheart
02-02-2011, 12:11 PM
If you are trying to use 3.2 core, why does your shader refer to "glModelViewProjectionMatrix?" That's been removed in 3.2 core. It is simply the combined GL_MODELVIEW and GL_PROJECTION matrices. If you're using 3.2 core, then you should not be using any of the OpenGL matrix functions. Instead, you should be building matrices with your own matrix libraries and then setting matrix uniforms.


glBindVertexArray(m_VAObj);
glBindBuffer(GL_ARRAY_BUFFER, m_VAObj);

These statements cannot possibly work. You cannot bind a vertex array object as a buffer object.

And you don't need to bind the buffer object anyway. The association between buffer objects and VAOs was made back when you called glVertexAttribPointer.


I crawled the net since some days, but all Shader Tutorials I find are for pre-3.2 only and they use deprecated stuff...

Read my signature. You may not want a "whole bible," but you seem to need one. Learning how to do shader-based stuff when all you've done is fixed function requires relearning a lot of things from scratch.

marshats
02-02-2011, 08:11 PM
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 (http://glm.g-truc.net/) 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\n");
glDeleteBuffers(1,&amp;bon_vert);
glDeleteVertexArrays(1,&amp;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\n"
"\n"
"uniform mat4 mvmatrix;\n"
"uniform mat4 pmatrix;\n"
"in vec3 vert;\n"
"\n"
"void main() {\n"
" gl_Position=pmatrix*mvmatrix*vec4(vert,1.);\n"
"}\n"
"\n"
};
glShaderSource(vshader,1,vshader_source,NULL);

const GLchar *fshader_source[] =
{
"#version 150 core\n"
"out vec4 fragcolor;\n"
"\n"
"void main() {\n"
"\n"
" fragcolor=vec4(0.0f,0.0f,1.0f,0.0f);\n"
"}\n"
"\n"
};
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,&amp;vao);
glBindVertexArray(vao);

//in vec3 vert;
//use global GLuint bon_vert; // buffer object name
glGenBuffers(1,&amp;bon_vert);
glBindBuffer(GL_ARRAY_BUFFER,bon_vert);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*3*Ver texArrayCount,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(&amp;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\n", 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 = &amp;modelmatrix;
};
void LoadIdentity(void) {
currentmatrix->top() = glm::mat4(1.0);
};
void MatrixMode_ModelView() {
currentmatrix = &amp;modelmatrix;
};
void MatrixMode_Projection() {
currentmatrix = &amp;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*)&amp;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 &amp;modelmatrix.top();
};
glm::mat4 *getprojectionmatrix() {
return &amp;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"

_ShaderRookie_
02-03-2011, 06:22 AM
Thanks a ton to both of you. I managed to get an orthographic view yesterday, thanks to the Tutorial of Alfons. Did you make it? It is really cool and I enjoyed it.
The code I showed you first as a mess :D. It was from trying a lot of things I found and so on.
Now I sorted things out while working through the website from Alfons and it is much better.



// Matrices
int id = ShaderLoader::getUniformLocation(m_shader, "MatOrtho");
glm::mat4 ortho = glm::mat4(1);
ortho *= glm::ortho<float>(0.0f, 1024, 768, 0, -1.0f, 1.0f);
glUniformMatrix4fv(id, 1, false, glm::value_ptr(ortho));

Thats how I do it. Works as expected.