渲染世界的OPENGL<11>模拟光线
(1)简单漫反射光 表面法线 顶点照明 float intensity=dot(vSurfaceNormal,vLightDirection); (2)点光源漫反射着色器 // Simple Diffuse lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
//首先是顶点渲染器
// 输入顶点和法向量
in vec4 vVertex;
in vec3 vNormal;
//注意:典型情况下,表面法线作为1个顶点属性提交,表面法线必须
//进行旋转从而使得他的方向在视觉空间以内。我们常常传递1个法向矩阵
//这个值只包括模型视图矩阵的旋转份量。
//可以通过GLTransformation当中的GetNormalMatrix函数返回这个值。
// 设置每一个批次
uniform vec4 diffuseColor; //球体的色彩
uniform vec3 vLightPosition;//光源位置的视觉坐标
uniform mat4 mvpMatrix;//模型视图投影矩阵
uniform mat4 mvMatrix;//模型视图矩阵
uniform mat3 normalMatrix;//
// 片断程序所需要的色彩,经过平滑着色的色彩值。
smooth out vec4 vVaryingColor;
void main(void)
{
// 得到视觉坐标系的表面法线向量
vec3 vEyeNormal = normalMatrix * vNormal;
// 得到视觉坐标系的顶点坐标
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// 得到光源的向量
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// 得到点乘积所得到的漫反射强度
float diff = max(0.0,dot(vEyeNormal,vLightDir));
// 强度乘以漫反射色彩,得到漫反射光线色彩
vVaryingColor.rgb = diff * diffuseColor.rgb;
vVaryingColor.a = diffuseColor.a;
// 最后对多边形进行变换,让模型透视投影矩阵对当前
//顶点进行变换。
gl_Position = mvpMatrix * vVertex;
} 点渲染shader程序,在主程序工程文件下,以vp格式的文件存在。 #version 130
out vec4 vFragColor;
smooth in vec4 vVaryingColor;
void main(void)
{
//将点着色器当中的输出vVaryingColor直接分配给输出
//片断色彩。
vFragColor = vVaryingColor;
} 片断着色器如上,只需要对其的片断色彩进行赋值就能够了。 #pragma comment(lib,"GLTools.lib")
#include <GLTools.h> // OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>
#include <GL/glut.h>
GLFrame viewFrame;
GLFrustum viewFrustum;
GLTriangleBatch sphereBatch;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
GLuint diffuseLightShader; // The diffuse light shader
GLint locColor; // The location of the diffuse color
GLint locLight; // The location of the Light in eye coordinates
GLint locMVP; // The location of the ModelViewProjection matrix uniform
GLint locMV; // The location of the ModelView matrix uniform
GLint locNM; // The location of the Normal matrix uniform
//任务:设置背景色彩
//加载渲染框架、加载渲染器程序代码、得到统1值的location
void SetupRC(void)
{
// 背景色彩的设置
glClearColor(0.3f,0.3f,1.0f);
//遮挡剔除和深度测试
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
shaderManager.InitializeStockShaders();
viewFrame.MoveForward(4.0f);
// 创造1个球体
gltMakeSphere(sphereBatch,1.0f,26,13);
//加载渲染框架,同时加载渲染器代码,并且将两个基本点的属性传入到顶点着色器中。
diffuseLightShader = shaderManager.LoadShaderPairWithAttributes("DiffuseLight.vp","DiffuseLight.fp",2,GLT_ATTRIBUTE_VERTEX,"vVertex",GLT_ATTRIBUTE_NORMAL,"vNormal");
//对统1值的取值,得到对应的统1值的位置
locColor = glGetUniformLocation(diffuseLightShader,"diffuseColor");
locLight = glGetUniformLocation(diffuseLightShader,"vLightPosition");
locMVP = glGetUniformLocation(diffuseLightShader,"mvpMatrix");
locMV = glGetUniformLocation(diffuseLightShader,"mvMatrix");
locNM = glGetUniformLocation(diffuseLightShader,"normalMatrix");
}
// Cleanup
void ShutdownRC(void)
{
}
// 任务:硬编码需要传入渲染器的两个值、激活shader程序、对对应的统1值矩阵进行赋值
void RenderScene(void)
{
static CStopWatch rotTimer;
// 清除当前色彩缓冲区和深度缓冲区的数据
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//对模型视图矩阵压入视图帧
modelViewMatrix.PushMatrix(viewFrame);
modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f,0.0f,0.0f);
//硬编码需要传入渲染器程序当中的值
GLfloat vEyeLight[] = { -100.0f,100.0f,100.0f };
GLfloat vDiffuseColor[] = { 0.0f,1.0f };
//激活shader程序
glUseProgram(diffuseLightShader);
//对对应的属性进行赋值
glUniform4fv(locColor,1,vDiffuseColor);
glUniform3fv(locLight,vEyeLight);
glUniformMatrix4fv(locMVP,GL_FALSE,transformPipeline.GetModelViewProjectionMatrix());
glUniformMatrix4fv(locMV,transformPipeline.GetModelViewMatrix());
glUniformMatrix3fv(locNM,transformPipeline.GetNormalMatrix());
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
void ChangeSize(int w,int h)
{
// Prevent a divide by zero
if (h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0,0,w,h);
//设置透视模式
viewFrustum.SetPerspective(35.0f,float(w) / float(h),100.0f);
//加载透视投影矩阵
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//渲染管线的设置矩阵堆栈,加载模型视图矩阵和透视矩阵
transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}
///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
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: %sn",glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}
主程序,对漫反射渲染器的使用和操作。 (3)ADS光照模型 环境光 uniform vec3 vAmbientMaterial;
uniform vec3 vAmbientLight;
vec3 vAmbientColor = vAmbientMaterial * vAmbientLight;
漫射光 uniform vec3 vDiffuseMaterial;
uniform vec3 vDiffuseLight;
float fDotProduct = max(0.0,dot(vNormal,vLightDir));
vec3 vDiffuseColor = vDiffuseMaaterial * vDiffuseLight * fDotProduct;
镜面光 uniform vec3 vSpecularMaterial;
uniform vec3 vSpecularLight;
float shininess=128f;
vec3 vReflection= reflect(-vLightDir,vEyeNormal);
fSpec = pow(EyeReflectionAngle,shininess);
vec3 vSpecularColor= vSpecularLight*vSpecularMaaterial*fSpec;
注意,和其他参数1样,反光度参数也能够是统1值,最高的镜面指数设置为128,大于这个数字,这个值将会逐步减弱。 // ADS Point lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
// 输入的数据,依然是点坐标和点的法向量
in vec4 vVertex;
in vec3 vNormal;
// 设置批次
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
// 终究传递给片元渲染器的color
smooth out vec4 vVaryingColor;
void main(void)
{
// 得到视觉坐标系的法向量
vec3 vEyeNormal = normalMatrix * vNormal;
// 得到视觉坐标系的坐标
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// 得到光源向量
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// 点乘得到1个漫反射强度
float diff = max(0.0,vLightDir));
// 强度乘以漫反射色彩
vVaryingColor = diff * diffuseColor;
// 在此基础上加上环境光
vVaryingColor += ambientColor;
// 镜面光
//得到光源的反射向量
vec3 vReflection = normalize(reflect(-vLightDir,vEyeNormal));
//得到反射角的cos值
float spec = max(0.0,vReflection));
if(diff != 0) {
float fSpec = pow(spec,128.0);
vVaryingColor.rgb += vec3(fSpec,fSpec,fSpec);
}
//终究利用几何变换
gl_Position = mvpMatrix * vVertex;
} ADS的顶点渲染器代码如上。 #version 130
out vec4 vFragColor;
smooth in vec4 vVaryingColor;
void main(void)
{
vFragColor = vVaryingColor;
} 片元着色器如上。 (4)Phong着色 3角形之间的不连续会致使上面所渲染的球体会产生亮线星光的效果。这类不连续则是由于色彩值在空间中进行的是线性插值的缘由。亮线就是两个独立3角形之间的缝隙。 // ADS Point lighting Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
//输入每一个顶点和每一个顶点的法线
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
// 片断程序色彩
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
void main(void)
{
// 获得表面法线的视觉坐标
vVaryingNormal = normalMatrix * vNormal;
// 获得顶点位置的视觉坐标
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// 获得到光源的方向
vVaryingLightDir = normalize(vLightPosition - vPosition3);
// 最后对多边形进行变换
gl_Position = mvpMatrix * vVertex;
} Phong顶点着色器,把具体的操作几近都转移到片元着色器上了。 #version 130
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
void main(void)
{
// 点乘得到漫反射的强度
float diff = max(0.0,dot(normalize(vVaryingNormal),normalize(vVaryingLightDir)));
// 用强度去乘以漫反射色彩将色彩设置为1.0
vFragColor = diff * diffuseColor;
// 增加环境光
vFragColor += ambientColor;
// 镜面光
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),normalize(vVaryingNormal)));
float spec = max(0.0,vReflection));
if(diff != 0) {
float fSpec = pow(spec,128.0);
vFragColor.rgb += vec3(fSpec,fSpec);
}
}
如上所示为片元着色器,大量的操作从顶点着色器转移到片元着色器当中,但是代码几近完全没有改变,仅仅转移了计算位置。这样算是高质量渲染了,会影响性能。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |