光強確定
要確定一個指定頂點上的光線的強度,需要兩個向量,一個是向量是光源的方向,用視覺座標光源位置減去定點位置確定;另一個向量是表面法線,注意兩個向量都要是單位向量。兩個向量點乘,會得到兩向量夾角的餘弦值,餘弦值越大,說明光照強度越強,當餘弦值爲1,說明光線正好照在頂點上。用點乘積的值與頂點的一個顏色值相乘,得到一個基於頂點光線強度的光照顏色值。具體見.vp
main.cp
#include<GLTools.h>
#include<GLMatrixStack.h>
#include<GLFrame.h>
#include<GLFrustum.h>
#include<GLMatrixStack.h>
#include<GLGeometryTransform.h>
#include<StopWatch.h>
#include<math.h>
#include<GLUT/GLUT.h>
GLFrame viewFrame;
GLFrustum viewFrustum;
GLTriangleBatch sphereBatch;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
GLuint diffuseLightShader;
GLint locColor;
GLint locLight;
GLint locMVP;
GLint locMV;
GLint locNM;
void SetupRC()
{
glClearColor(0.3f,0.3f,0.3f,1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
viewFrame.MoveForward(4.0f);
gltMakeSphere(sphereBatch,1.0f,26,13);
diffuseLightShader=gltLoadShaderPairWithAttributes("/Users/mac/Downloads/1/DiffuseLight.vp","/Users/mac/Downloads/1/DiffuseLight.fp",2,GLT_ATTRIBUTE_VERTEX,"vVertex",GLT_ATTRIBUTE_NORMAL,"vNormal");
locColor=glGetUniformLocation(diffuseLightShader,"diffuseColor");
locLight=glGetUniformLocation(diffuseLightShader,"vLightPosition");
locMVP=glGetUniformLocation(diffuseLightShader,"mvpMatrix");
locMV=glGetUniformLocation(diffuseLightShader,"mvMatrix");
locNM=glGetUniformLocation(diffuseLightShader,"normalMatrix");
}
void ShutdownRC(void)
{
}
void RenderScene(void)
{
static CStopWatch rotTimer;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix(viewFrame);
modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds()*222.0f,0.0f,1.0f,0.0f);
GLfloat vEyeLight[]={-100.0f,100.0f,10.0f};
GLfloat vDiffuseColor[]={1.0f,1.0,0.0f,1.0f};
glUseProgram(diffuseLightShader);
glUniform4fv(locColor,1,vDiffuseColor);
glUniform3fv(locLight,1,vEyeLight);
glUniformMatrix4fv(locMVP,1,GL_FALSE,transformPipeline.GetModelViewProjectionMatrix());
glUniformMatrix4fv(locMV,1,GL_FALSE,transformPipeline.GetModelViewMatrix());
glUniformMatrix3fv(locNM,1,GL_FALSE,transformPipeline.GetNormalMatrix());
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
void ChangeSize(int w,int h)
{
if(h==0)
h=1;
glViewport(0,0,w,h);
viewFrustum.SetPerspective(35.0f,float(w)/float(h),1.0f,100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(800, 600);
glutCreateWindow("Simple Diffuse Lighting");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}
.vp
#version 120
attribute vec4 vVertex;
attribute vec3 vNormal;
uniform vec4 diffuseColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
varying vec4 vVaryingColor;
void main(void)
{
// Get surface normal in eye coordinates
vec3 vEyeNormal = normalMatrix * vNormal;
// Get vertex position in eye coordinates
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Get vector to light source
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// Dot product gives us diffuse intensity
float diff = max(0.0, dot(vEyeNormal, vLightDir));
// Multiply intensity by diffuse color
vVaryingColor.rgb = diff * diffuseColor.rgb;
vVaryingColor.a = diffuseColor.a;
// Let's not forget to transform the geometry
gl_Position = mvpMatrix * vVertex;
}
.fp
#version 120
varying vec4 vVaryingColor;
void main(void)
{
gl_FragColor = vVaryingColor;
}