miércoles, 17 de agosto de 2011

Ejecutando y compilando programas CG

En este post coloco el código para ejecutar el sencillo ejemplo de cambiar el color.
Para comenzar creamos un widget que contenga opengl.
El header es:

#ifndef QGLWIDGET_H_INCLUDED
#define QGLWIDGET_H_INCLUDED
#include <QtOpenGL/QGLWidget>
#include <Cg/cg.h>
#include <Cg/cgGL.h>


class Glwidget : public QGLWidget     //hereda de QGLwidget
{
    public:
    Glwidget(QWidget *parent=0);
    ~Glwidget();
    protected:
   //funciones a sobrescribir de opengl
    void initializeGL();
    void paintGL();
    void resizeGL(int,int);
    private:
    //Miembros de CG
    CGcontext contexto;
    CGprofile perfil;   //para crear el perfil dependiendo de la api y la gpu
    CGparameter modelViewMatrix;  //parámetro para ingresar
    CGprogram programa;
};

Ahora el archivo cpp. qglwidget.cpp es:

#include <QtGui>
#include "qglwidget.h"
#include <iostream>
//Estos includes siguientes son necesarios para utilizar code-completion de codeblocks sin problemas
#include <GL/gl.h>
#include <GL/glu.h>


//función para el manejador de errores
void MyErrorHandler(CGcontext contexto, CGerror error, void *data) {
    CGcontext alf=cgCreateContext();
    if(contexto!=NULL){//para arreglar un problema de salida del programa
    alf=contexto;}
    const char *lastListing = cgGetLastListing(alf);
    qDebug() << (lastListing == 0 ? "No error." : lastListing);
}


Glwidget::Glwidget(QWidget *parent){};
Glwidget::~Glwidget(){
    cgDestroyProgram(programa);
    cgDestroyContext(contexto);
    cgDestroyParameter(modelViewMatrix);
}


void Glwidget::initializeGL(){
    contexto=cgCreateContext();
  //Creamos un manejador de errores con la función MyErrorHandler es muy útil utilizarlo para 
   // encontrar los errores facilmente en el archivo CG.
    cgSetErrorHandler(MyErrorHandler,NULL);
    //Se crea el perfil a partir de la ultima versión soportada por nuestra GPU.
    //Este es simplemente un Vertex shader, para hacer shaders mas realistas es necesario
    //utilizar también pixel shaders y para eso poner CG_GL_FRAGMENT
    perfil= cgGLGetLatestProfile(CG_GL_VERTEX);
    cgGLSetOptimalOptions(perfil);
//mi archivo cg se llama simplemente red.cg únicamente cambia el color del polígono.
//mainv es la función principal en nuestro programa.
    programa = cgCreateProgramFromFile(contexto,CG_SOURCE,"red.cg",perfil,"mainv",NULL);
    cgGLLoadProgram(programa);
    //Relacionamos nuestro parámetro a la variable literalmente de nuestro programa en cg
    modelViewMatrix = cgGetNamedParameter(programa, "ModelViewProj");
    glShadeModel(GL_SMOOTH); 
    glClearColor(0.0,0.0,0.0,0.0);
    glClearDepth(1.0f); // Depth buffer setup
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LEQUAL); 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // R
}
void Glwidget::resizeGL(int width,int height){
    if (height == 0)
        height = 1;
    glViewport(0, 0, width, height); // Reset current viewport
    glMatrixMode(GL_PROJECTION); // Select projection matrix
    glLoadIdentity(); // Reset projection matrix
    gluPerspective (45.0f, (GLfloat)(width)/(GLfloat)(height),0.1f, 100.0f); // Calculate The Aspect Ratio
    glMatrixMode(GL_MODELVIEW); // Select modelview matrix
}
void Glwidget::paintGL(){
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
     glLoadIdentity(); 
     //las transformaciones siempre antes de aplicar el shader
     glTranslatef(0.0f, 0.0f, -5.0f);
    //ingresar nuestra matriz de proyección.
     cgGLSetStateMatrixParameter(modelViewMatrix, CG_GL_MODELVIEW_PROJECTION_MATRIX,        CG_GL_MATRIX_IDENTITY);
      //activamos el perfil y el programa.
     cgGLEnableProfile(perfil);
     cgGLBindProgram(programa);
    //Hacemos un sencillo cuadrado
    glBegin(GL_QUADS); 
        glVertex2f(0.7f,  0.7f); 
        glVertex2f(0.7f, -0.7f); 
        glVertex2f(-0.7f, -0.7f); 
        glVertex2f(-0.7f, 0.7f); 
       glEnd(); 
       cgGLDisableProfile(perfil);
       glFlush ();
}

creamos una archivo main.cpp con el siguiente código:

#include <iostream>
#include "qglwidget.h"  //el widget creado
#include <QApplication>
using namespace std;


int main(int argc,char *argv[])
{
    QApplication app2(argc,argv);
    Glwidget wid;
    wid.show();
    return app2.exec();
}
De esta manera podemos utilizar nuestro shader creado con CG.