(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
#include
#include
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
#include
#include
#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);