看了康玉之大牛的《GPU 编程与CG 语言之阳春白雪下里巴人》,和放风筝的程序员的博客,自己也来写写光照模型
1. Lambert光照模型,也就是漫反射光照模型。它考虑的是ambient光和diffuse光对物体的综合影响
着色器程序
struct VertexIn
{
float4 position : POSITION;
float4 normal : NORMAL;
};
struct VertexScreen
{
float4 oPosition : POSITION;
float4 color : COLOR;
};
void main_v(VertexIn posIn,
out VertexScreen posOut,
uniform float3 globalAmbient,
uniform float3 lightPosition,
uniform float3 lightColor,
uniform float3 Kd)
{
// Get OpenGL state matrices
float4x4 modelViewProj = glstate.matrix.mvp;
float4x4 worldMatrix = glstate.matrix.modelview[0];
float4x4 worldMatrix_IT = glstate.matrix.invtrans.modelview[0];
posOut.oPosition = mul(modelViewProj, posIn.position);
float3 worldPos = mul(worldMatrix, posIn.position).xyz;
float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
N = normalize(N);
//计算入射光方向
float3 L = lightPosition - worldPos;
L = normalize(L);
//计算方向光漫反射光强
float3 diffuseColor = Kd*lightColor*max(dot(N, L), 0);
//计算环境光漫反射光强
float3 ambientColor = Kd*globalAmbient;
posOut.color.xyz = diffuseColor+ambientColor;
posOut.color.w = 1;
}
主程序
#include <stdio.h>
#include <gl/glut.h>
#include <cg/cg.h>
#include <cg/cgGL.h>
#pragma comment(lib,"cg.lib")
#pragma comment(lib,"cgGL.lib")
#define WINDOW_SIZE 800
static CGcontext Context = NULL;
static CGprogram VertexProgram = NULL;
static CGprofile VertexProfile;
static CGparameter globalAmbient = NULL;
static CGparameter lightPosition = NULL;
static CGparameter lightColor = NULL;
static CGparameter Kd = NULL;
void init()
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
//-------------------------------cg init-------------------------------------------------------
Context = cgCreateContext();
VertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
VertexProgram = cgCreateProgramFromFile(Context,CG_SOURCE, "lightmodle.cg",VertexProfile,"main_v", NULL);
cgGLLoadProgram(VertexProgram);
globalAmbient = cgGetNamedParameter(VertexProgram, "globalAmbient");
lightPosition = cgGetNamedParameter(VertexProgram, "lightPosition");
lightColor = cgGetNamedParameter(VertexProgram, "lightColor");
Kd = cgGetNamedParameter(VertexProgram, "Kd");
}
void display()
{
cgGLBindProgram(VertexProgram);
cgGLSetParameter3f(globalAmbient, 0.2, 0.2, 0.2);//环境光暗灰色
cgGLSetParameter3f(lightPosition, 0.0, 0.0, 1.0);//光源放在正前面
cgGLSetParameter3f(lightColor, 1.0, 1.0, 1.0);//明亮的白色的点光源
cgGLSetParameter3f(Kd, 0.8, 0.8, 0.8);//材料对光的反射属性
cgGLEnableProfile(VertexProfile);
static float rotate=0.0;
rotate+=0.1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0,0.0,-6.0);
glRotatef(30,1.0,0.0,0.0);
glRotatef(rotate,0.0,1.0,0.0);
glutSolidTeapot(1.0);
cgGLDisableProfile(VertexProfile);
glutSwapBuffers();
}
void reshape(int w,int h)
{
if (h==0) h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.01f,400.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
glutCreateWindow(argv[0]);
glutReshapeWindow(WINDOW_SIZE,WINDOW_SIZE);
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
cgDestroyProgram(VertexProgram);
cgDestroyContext(Context);
return 0;
}
效果图:
2. Phong光照模型,这个模型计算了镜面高光(Specular):
着色器程序
struct VertexIn
{
float4 position : POSITION;
float4 normal : NORMAL;
};
struct VertexScreen
{
float4 oPosition : POSITION;
float4 objectPos : TEXCOORD0;
float4 objectNormal : TEXCOORD1;
};
void main_v( VertexIn posIn,
out VertexScreen posOut)
{
float4x4 modelViewProj = glstate.matrix.mvp;
posOut.oPosition = mul(modelViewProj, posIn.position);
posOut.objectPos = posIn.position;
posOut.objectNormal = posIn.normal;
}
void main_f( VertexScreen posIn,
out float4 color : COLOR,
uniform float3 globalAmbient,
uniform float3 eyePosition,
uniform float3 lightPosition,
uniform float3 lightColor,
uniform float3 Kd,
uniform float3 Ks,
uniform float shininess)
{
float4x4 worldMatrix = glstate.matrix.modelview[0];
float4x4 worldMatrix_IT = glstate.matrix.invtrans.modelview[0];
float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;
float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;
N = normalize(N);
//计算入射光方向、视线方向、反射光线方向
float3 L = normalize(lightPosition - worldPos);
float3 V = normalize(eyePosition - worldPos);
float3 R = 2*max(dot(N, L), 0)*N-L;
R = normalize(R);
//计算漫反射分量
float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
//计算镜面反射分量
float3 specularColor = Ks * lightColor*pow(max(dot(V, R), 0), shininess);
color.xyz = diffuseColor + specularColor;
color.w = 1;
}
主程序
#include <stdio.h>
#include <gl/glut.h>
#include <cg/cg.h>
#include <cg/cgGL.h>
#pragma comment(lib,"cg.lib")
#pragma comment(lib,"cgGL.lib")
#define WINDOW_SIZE 800
static CGcontext Context = NULL;
static CGprogram VertexProgram = NULL;
static CGprogram FragementProgram = NULL;
static CGprofile VertexProfile;
static CGprofile FragementProfile;
static CGparameter globalAmbient = NULL;
static CGparameter eyePosition = NULL;
static CGparameter lightPosition = NULL;
static CGparameter lightColor = NULL;
static CGparameter Kd = NULL;
static CGparameter Ks = NULL;
static CGparameter shininess = NULL;
void init()
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
//-------------------------------cg init-------------------------------------------------------
Context = cgCreateContext();
//顶点程序
VertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
VertexProgram = cgCreateProgramFromFile(Context,CG_SOURCE, "lightmodle.cg",VertexProfile,"main_v", NULL);
cgGLLoadProgram(VertexProgram);
//片段程序
FragementProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
FragementProgram = cgCreateProgramFromFile(Context,CG_SOURCE, "lightmodle.cg",FragementProfile,"main_f", NULL);
cgGLLoadProgram(FragementProgram);
globalAmbient = cgGetNamedParameter(FragementProgram, "globalAmbient");
eyePosition = cgGetNamedParameter(FragementProgram, "eyePosition");
lightPosition = cgGetNamedParameter(FragementProgram, "lightPosition");
lightColor = cgGetNamedParameter(FragementProgram, "lightColor");
Kd = cgGetNamedParameter(FragementProgram, "Kd");
Ks = cgGetNamedParameter(FragementProgram, "Ks");
shininess = cgGetNamedParameter(FragementProgram, "shininess");
}
void display()
{
cgGLEnableProfile(VertexProfile);
cgGLEnableProfile(FragementProfile);
cgGLBindProgram(VertexProgram);
cgGLBindProgram(FragementProgram);
cgGLSetParameter3f(globalAmbient, 0.2, 0.2, 0.2);//环境光暗灰色
cgGLSetParameter3f(eyePosition, 0.0, 0.0, 0.0);//视点位置
cgGLSetParameter3f(lightPosition, 0.0, 0.0, 1.0);//光源放在正前面
cgGLSetParameter3f(lightColor, 1.0, 1.0, 1.0);//明亮的白色的点光源
cgGLSetParameter3f(Kd, 0.8, 0.8, 0.8);//材料对光的反射属性
cgGLSetParameter3f(Ks, 1.0, 1.0, 1.0);//材质的镜面反射系数
cgGLSetParameter1f(shininess, 20);//高光指数
cgGLEnableProfile(FragementProfile);
static float rotate=0.0;
rotate+=0.1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0,0.0,-6.0);
glRotatef(30,1.0,0.0,0.0);
glRotatef(rotate,0.0,1.0,0.0);
glutSolidTeapot(1.0);
cgGLDisableProfile(VertexProfile);
cgGLDisableProfile(FragementProfile);
glutSwapBuffers();
}
void reshape(int w,int h)
{
if (h==0) h=1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.01f,400.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
glutCreateWindow(argv[0]);
glutReshapeWindow(WINDOW_SIZE,WINDOW_SIZE);
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
init();
glutMainLoop();
cgDestroyProgram(VertexProgram);
cgDestroyProgram(FragementProgram);
cgDestroyContext(Context);
return 0;
}
效果图: