GLSL新手上路 -- 《交互式计算机图形学》附录中GLSL代码有误 -- 修改如下

《交互式计算机图形学》可谓是一本很不错的graphics领域的入门书籍,这是站在客观的角度来说的,尽管书中有我老板的名字。然而,对于小猪这样的菜鸟,这本书是非常合适的。以前总以为自己的图形学是多么多么的牛B,因为毕竟用Level set做过surface reconstruction以及ray tracing,用GPU做ocean surface simulation等等,自我感觉是图形学小牛,然而,CUHK的老大让我做一个基于ray casting的体绘制和面绘制结合起来,却一时想不起来如何下手。所以,最近一周恶补图形学基本知识,就用上《交互式计算机图形学》这本书了,这本书将的非常好,top-down,非常喜欢这种讲述方式,因此,用了三天,已经看得差不多了,毕竟以前对图形学领域的前沿知识还是了解的,所以,哈哈。

下面重点说GLSL一章的问题,这本书讲的是很好,但是附录中的GLSL的代码是有问题的,不能顺利运行,我用的是《交互式计算机图形学》(第五版),主要是,

1. 没有进行glew初始化;

2. 读取shader文件有误;

 

分别对此进行了修改,废话不多说,贴正确的code。

 

//////////////////////////////////////////////////////////////////////////
/*
 * my first glsl program, hello - glsl
 * now, go!
 *
 */


#define GLUT_DISABLE_ATEXIT_HACK


#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl/glew.h>
#include <gl/glut.h>

 

// grid resolution
#define N 64


// vision region
const GLdouble nearVal = 1.0;
const GLdouble farVal  = 20.0;

// program object ID
GLuint program = 0;

GLint timeParam;


// error buffer and error message length
GLchar *ebuffer;
GLsizei elength;


// high field data
GLfloat data[N][N];

 

// shader read entry function
static char* readShaderSource(const char * shaderFile)
{
 char *buf = NULL;

 int size(0);


 FILE *file = fopen(shaderFile, "r");

 if (!file) return NULL;

 fseek(file, 0, SEEK_END);

 size = ftell(file);

 rewind(file);


 if (size > 0)
 {
  buf = (char*)malloc(sizeof(char)*(size+1));

  size = fread(buf, sizeof(char), size, file);

  buf[size] = '\0';
 }

 fclose(file);

 return buf;
}


// init OpenGL
static void initGL()
{
 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 glColor3f(0.0, 0.0, 0.0);

 glMatrixMode( GL_PROJECTION );
 glLoadIdentity();
 glOrtho(-0.75, 0.75, -0.75, 0.75, -5.5, 5.5);
}


// init GLSL
static void initShader(const GLchar * vShaderFile, const GLchar * fShaderFile)
{
 GLint status;
 GLchar *vSource, *fSource;
 GLuint vShader, fShader;


 // read shader file
 vSource = readShaderSource(vShaderFile);


 if ( vSource == NULL )
 {
  printf("Failed to read vertex shader\n");

  exit( EXIT_FAILURE );
 }


 fSource = readShaderSource(fShaderFile);
 
 if ( fSource == NULL )
 {
  printf("Failed to read fragment shader\n");

  exit( EXIT_FAILURE );
 }


 //create program and shader object
 vShader = glCreateShader( GL_VERTEX_SHADER );
 fShader = glCreateShader( GL_FRAGMENT_SHADER );
 

 program = glCreateProgram();


 // bind shader to program object
 glAttachShader( program, vShader );
 glAttachShader( program, fShader );

 
 // read shader
 glShaderSource( vShader, 1, (const GLchar**)&vSource, NULL );
 glShaderSource( fShader, 1, (const GLchar**)&fSource, NULL );


 // compile vertex shader
 glCompileShader( vShader );


  // error detection
  glGetShaderiv( vShader, GL_COMPILE_STATUS, &status );
 
  if ( status == GL_FALSE )
  {
   printf("Failed to compile vertex shader\n");
 
   glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &elength);
 
   ebuffer = (char*)malloc(elength*sizeof(char));
 
   glGetShaderInfoLog(vShader, elength, NULL, ebuffer);
 
   printf("%s\n", ebuffer);
 
   exit( EXIT_FAILURE );
  }


 // compile fragment shader
 glCompileShader( fShader );

 // error detection
 glGetShaderiv( fShader, GL_COMPILE_STATUS, &status );

 if ( status == GL_FALSE )
 {
  printf("Failed to compile fragment shader\n");

  glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &elength);

  ebuffer = (char*)malloc(elength*sizeof(char));

  glGetShaderInfoLog(fShader, elength, NULL, ebuffer);

  printf("%s\n");

  exit( EXIT_FAILURE );
 }


 // link and error detection
 glLinkProgram( program );

 glGetProgramiv( program, GL_LINK_STATUS, &status );

 if ( status == GL_FALSE )
 {
  printf("Failed to link program object\n");

  glGetProgramiv( program, GL_INFO_LOG_LENGTH, &elength );

  ebuffer = (char*)malloc(elength*sizeof(char));

  glGetProgramInfoLog(program, elength, &elength, ebuffer);

  printf("%s\n");

  exit( EXIT_FAILURE );
 }


 // use program object
 glUseProgram( program );


 // set uniform parameter
 timeParam = glGetUniformLocation( program, "time" );

}

 

// mesh
void mesh()
{
 int i(0), j(0);

 glMatrixMode( GL_MODELVIEW );

 glLoadIdentity();

 gluLookAt(2.0, 2.0, 2.0, 0.5, 0.0, 0.5, 0.0, 1.0, 0.0);

 for (i = 0; i < N; i++)
 {
  for (j = 0; j < N; j++)
  {
   glBegin( GL_LINE_LOOP );
    glVertex3f((float)i/N, data[i][j], (float)j/N);
    glVertex3f((float)i/N, data[i][j], (float)(j+1)/N);
    glVertex3f((float)(i+1)/N, data[i][j], (float)(j+1)/N);
    glVertex3f((float)(i+1)/N, data[i][j], (float)j/N);
   glEnd();
  }
 }

}


static void display()
{
 // transfer run-time to shader
 glUniform1f( timeParam, glutGet(GLUT_ELAPSED_TIME) );

 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

 mesh();

 glutSwapBuffers();

}

 

// reshape callback function
static void reshape(int w, int h)
{
 glMatrixMode( GL_PROJECTION );

 glLoadIdentity();

 glOrtho(-0.75, 0.75, -0.75, 0.75, -5.5, 5.5);


 glViewport(0, 0, w, h);

 glutPostRedisplay();

}

 

// keyboard callback function
static void keyboard(unsigned char key, int x, int y)
{
 switch(key)
 {
 case 27:
  
 case 'Q':

 case 'q':

  exit( EXIT_FAILURE );

  break;

  
 default:

  break;

 }

}

 

// idle callback function
static void idle()
{
 glUniform1f( timeParam, (GLfloat)glutGet(GLUT_ELAPSED_TIME) );

 glutPostRedisplay();

}

 

// check whether GLEW and GLSL are supported
bool check()
{
 const char * version = (const char*)glGetString( GL_VERSION );

 printf("OpenGL version : %s\n", version);


 // check OpenGL
 if ( glewIsSupported("GL_VERSION_2_0") )
 {
  printf("Ready for OpenGL 2.0\n");
 }
 else
 {
  printf("OpenGL 2.0 not supported\n");

  return false;
 }

 // check extensions
 if ( GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader )
 {
  printf("Ready for GLSL\n");
 }
 else
 {
  printf("Not totally ready\n");

  return false;
 }


 return true;

}

 

// main
int main(int argc, char ** argv)
{
 int i(0), j(0);

 for (i = 0; i < N; i++)
 {
  for (j = 0; j < N; j++)
  {
   data[i][j] = 0;
  }
 }

 

 glutInit(&argc, argv);

 glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );

 glutInitWindowSize(512, 512);

 glutCreateWindow("Simple GLSL example");

 

 glutDisplayFunc(display);

 glutReshapeFunc(reshape);

 glutKeyboardFunc(keyboard);

 glutIdleFunc(idle);

 

 // init GLEW, this is very important
 glewInit();


 // check whether GLEW and GLSL are supported
 if ( !check() )
 {
  return 0;
 }


 initGL();

 initShader("vmesh.vert", "fPassThrough.frag");

 

 glutMainLoop();


 return 0;

}

 

 

 

两个shader文件,分别存为vmesn.vert和fPassThrough.frag,代码如下:

vmesh.vert文件

//
// vertex shader
//


uniform float time;


void main()
{
 float s;
 
 vec4 t = gl_Vertex;
 
 t.y = 0.1*sin(0.001*time + 5.0*gl_Vertex.x) * sin(0.001*time + 5.0*gl_Vertex.z);
 
 gl_Position = gl_ModelViewProjectionMatrix * t;
 
 gl_FrontColor = gl_Color;
 
}

 

 

 

fPassThrough.frag文件

 

//
// mesh shader
//

 

void main()
{
 gl_FragColor = gl_Color;
}

 

 

这样就over了。

欢迎大家提问题,多多交流。

tc.zhu@sub.siata.c.cn

 

 

posted @ 2010-08-12 23:39  Tandy  阅读(2120)  评论(0编辑  收藏  举报