OpenGL中使用Shader

(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();
}

片元着色器toon.frag

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;
}

在代码里使用 loadShaderFromFile 来加载Shader内容


(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;
}

如何使用Shader?

(1)  创建着色器

glCreateShader(GL_VERTEX_SHADER); //创建Shader

(2) 加载Shader内容

loadShaderFromFile("toon.vert");  //加载Shader内容

(3) 对不同类型的着色器绑定不同的Shader内容,比如这里对顶点着色器v 绑定了顶点shader内容 vv

glShaderSource(v,1,&vv,NULL);  

(4) 编译Shader

glCompileShader(v);   //编译shader

(5) 创建着色器程序

p=glCreateProgram();

(6) 向程序中加入着色器

glAttachShader(p,f);

(7) 连接程序

glLinkProgram(p);

(8)加载并使用连接好的程序

glUseProgram(p);


你可能感兴趣的:(OpenGL中使用Shader)