(1) 需要Shader文件,一个顶点着色器、一个片元着色器
顶点着色器 toon.vert
varying vec3 normal, lightDir; void main() { lightDir = normalize(vec3(gl_LightSource[0].position)); normal = normalize(gl_NormalMatrix * gl_Normal); gl_Position = ftransform(); }
varying vec3 normal, lightDir; void main() { float intensity; vec3 n; vec4 color; n = normalize(normal); intensity = max(dot(lightDir,n),0.0); if (intensity > 0.98) color = vec4(0.8,0.8,0.8,1.0); else if (intensity > 0.5) color = vec4(0.4,0.4,0.8,1.0); else if (intensity > 0.25) color = vec4(0.2,0.2,0.4,1.0); else color = vec4(0.1,0.1,0.1,1.0); gl_FragColor = color; }
(2) 需要一个函数来加载Shader内容
LoadShader.cpp
#include<stdio.h> #include<stdlib.h> #include<string.h> char* loadShaderFromFile(char* filename) { FILE *fp; char* content=NULL; int count=0; if(filename!=NULL) { fp=fopen(filename,"rt"); if(fp!=NULL) { fseek(fp,0,SEEK_END); //把位置指针移到文件尾,这样通过ftell获取到的位置指针返回文件大小给count count=ftell(fp); rewind(fp); if(count>0) { content=(char*)malloc(sizeof(char)*(count+1)); count=fread(content,sizeof(char),count,fp); content[count]='\0'; } fclose(fp); } } return content; }
(3) 用OpenGL画一个茶壶(Glet中自带函数),在例子中加载Shader - 编译Shader - Attach Shader
#include<stdio.h> #include<stdlib.h> #include<glew.h> #include"glut.h" #include"LoadShader.h" #pragma comment(lib,"glew32.lib") GLuint v,f,f2,p; float lpos[4]={1,0.5,1,0}; void changeSize(int w,int h) { if(h==0) { h=1; } float ratio=1.0*w/h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0,0,w,h); gluPerspective(45,ratio,1,1000); glMatrixMode(GL_MODELVIEW); } void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f ); glLightfv(GL_LIGHT0,GL_POSITION,lpos); glutSolidTeapot(1); glutSwapBuffers(); } void processNormalKeys(unsigned char key,int x,int y) { if(key==27) { exit(0); } } void setShaders() { char* vs=NULL,*fs=NULL,*fs2=NULL; v=glCreateShader(GL_VERTEX_SHADER); f=glCreateShader(GL_FRAGMENT_SHADER); f2=glCreateShader(GL_FRAGMENT_SHADER); vs=loadShaderFromFile("toon.vert"); fs=loadShaderFromFile("toon.frag"); fs2=loadShaderFromFile("toon2.frag"); const char* ff=fs; const char* ff2=fs2; const char* vv=vs; glShaderSource(v,1,&vv,NULL); //顶点着色器 glShaderSource(f,1,&ff,NULL); //片元着色器1 glShaderSource(f2,1,&ff2,NULL); //片元着色器2 free(vs); free(fs); glCompileShader(v); //编译shader glCompileShader(f); glCompileShader(f2); p=glCreateProgram(); glAttachShader(p,f); glAttachShader(p,f2); glAttachShader(p,v); glLinkProgram(p); glUseProgram(p); } int main(int argc,char* argv[]) { glutInit(&argc,argv); //初始化glut,必须调用,复制黏贴这句话即可 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); //设置显示方式,RGB、单缓冲。当然还有GLUT_INDEX索引颜色 GLUT_DOUBLE双缓冲(Qt中看到过双缓冲) glutInitWindowPosition(100,100); //位置 glutInitWindowSize(400,400);//窗口大小 glutCreateWindow("第一个OpenGL程序"); //创建窗口,设置标题 glutDisplayFunc(renderScene); // 当绘制窗口时调用myDisplay glutIdleFunc(renderScene); glutReshapeFunc(changeSize); glutKeyboardFunc(processNormalKeys); glEnable(GL_DEPTH_TEST); glClearColor(1.0,1.0,1.0,1.0); glewInit(); if(glewIsSupported("GL_VERSION_2_0")) { printf("Ready for OpenGL 2.0\n"); } else { printf("OpenGL 2.0 not supported\n"); exit(1); } setShaders(); glutMainLoop(); //消息循环 return 0; }
(1) 创建着色器
glCreateShader(GL_VERTEX_SHADER); //创建Shader
(2) 加载Shader内容
loadShaderFromFile("toon.vert"); //加载Shader内容
glShaderSource(v,1,&vv,NULL);
glCompileShader(v); //编译shader
p=glCreateProgram();
glAttachShader(p,f);
glLinkProgram(p);
glUseProgram(p);