《交互式计算机图形学》可谓是一本很不错的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 regionconst GLdouble nearVal = 1.0;const GLdouble farVal = 20.0;// program object ID
GLuint program = 0;GLint timeParam;
// error buffer and error message lengthGLchar *ebuffer;GLsizei elength; // high field dataGLfloat 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 OpenGLstatic 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 GLSLstatic 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了。
欢迎大家提问题,多多交流。