顶点shader代码:
float LightIntensity;//光照属性
void main()
{
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex);//将物体进行模型视图中的一些变换(旋转 缩放 平移)
vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);//将顶点法线转换到模型视图中,因为对于法线没有缩放操作,所以不能使用gl_ModelViewMatrix矩阵,使用gl_NormalMatrix
vec3 lightVec = normalize(gl_LightSource[0].position.xyz - ecPosition);//顶点到光源位置的单位向量L
vec3 reflectVec = lightVec+ecPosition;//L和顶点指向观察点的向量和==S半向量
vec3 viewVec = normalize(reflectVec);//单位化
//可以直接使用viewVec = gl_LightSource[0].halfVector.xyz;
float diffuse = max(dot(lightVec, tnorm), 0.0);//散射光计算公式=(max{L*n,0})*diffuseLight*diffuseMatrial
float spec = 0.0;
if (diffuse > 0.0)//如果L*n<=0,顶点就不存在镜面光(光线位于表面的另一面)
{
spec = max(dot(viewVec, tnorm), 0.0);//计算公式=(max{S*n,0}^shiness)*specularLight*specularMaterial
spec = pow(spec, 0.0);
}
LightIntensity = gl_LightModel.ambient+gl_LightSource[0].ambient*gl_FrontMaterial.ambient+gl_LightSource[0].diffuse*gl_FrontMaterial.diffuse*diffuse+gl_LightSource[0].specular*gl_FrontMaterial.specular*spec;
gl_Position = ftransform();
gl_FrontColor = gl_Color * LightIntensity;
}
片元shader
void main()
{
gl_FragColor = gl_Color;
}
效果:
完整程序:
#include<stdio.h>
#include<stdlib.h>
#include<gl\glew.h>
#include <gl\glut.h>
//#pragma comment(lib,"GLAUT.lib")
#pragma comment(lib,"glew32.lib")
#pragma comment(lib,"glew32s.lib")
char *vdata = NULL;
char *fdata = NULL;
GLuint v,f,p;
float a = 0;
GLfloat position[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat ambient[] = { 0.0, 0.0, 0.0, 0.0 };
GLfloat ambient2[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat specular[] = { 1.0, 0.0, 0.0, 0.0 };
void init()
{
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1);
glColor3f(1, 1, 1);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2);
glLightModeli(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
}
char* ReadFile(char *filename)
{
FILE *file = NULL;
fopen_s(&file, filename, "rb");
if (file == NULL)
{
return NULL;
}
fseek(file, 0, SEEK_END);
long count = ftell(file);
rewind(file);
char *fileData = NULL;
if (count > 0)
{
fileData = new char[count + 1];
fread(fileData, sizeof(char), count, file);
fileData[count] = '\0';
}
return fileData;
}
void setShader()//设置着色器
{
glewInit();
v = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
f = glCreateShader(GL_FRAGMENT_SHADER);//创建片元着色器
vdata = ReadFile("vertex.v");//读取顶点着色器内容
fdata = ReadFile("fragment.f");//读取片元着色器内容
char *vv = vdata;
char *ff = fdata;
glShaderSource(v, 1, &vv, NULL);//添加到着色器中
glShaderSource(f, 1, &ff, NULL);
glCompileShader(v);//编译着色器
glCompileShader(f);
p = glCreateProgram();//创建程序处理着色器
glAttachShader(p, v);//将待处理着色器添加到程序中
glAttachShader(p, f);
glLinkProgram(p);//链接
int result;
glGetProgramiv(p, GL_LINK_STATUS, &result);//获取程序编译状态
if (result != GL_TRUE)//如果失败获取失败信息
{
GLsizei length;
glGetProgramiv(p, GL_INFO_LOG_LENGTH, &length);
char *info = new char [length];
glGetProgramInfoLog(p, 255, &length, info);
fprintf(stderr, "link log = '%s'\n", info);
delete[]info;
}
glUseProgram(p);//使用着色器程序
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3d(-10, 0, 0);//X轴
glVertex3d(10, 0, 0);
glColor3f(0, 1, 0);//Y轴
glVertex3d(0, -10, 0);
glVertex3d(0, 10, 0);
glColor3f(0, 0, 1);//Z轴
glVertex3d(0, 0, -10);
glVertex3d(0, 0, 10);
glEnd();
glRotatef(a, 0, 1, 0);
glColor3f(1, 0, 1);
glutSolidTeapot(1);
a += 1;
glutSwapBuffers();
}
void reshape(int w, int h)
{
if (h == 0) h = 1;
float ratio = 1.0*w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
init();
glewInit();
setShader();
glutMainLoop();
return 0;
}