OpenGL固定管线着色器
2019-05-15 本文已影响16人
聪莞
OpenGL固定管线下的着色器包括:
- 单元着色器(GLT_SHADER_IDENTITY)
- 平面着色器(GLT_SHADER_FLAT)
- 上色着色器(GLT_SHADER_SHADED)
- 默认光源着色器(GLT_SHADER_DEFAULT_LIGHT)
- 点光源着色器(GLT_SHADER_POINT_LIGHT_DIEF)
- 纹理替换矩阵着色器(GLT_SHADER_TEXTURE_REPLACE)
- 纹理调整着色器(GLT_SHADER_TEXTURE_MODULATE)
- 纹理光源着色器(GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF)
了解几个概念:
模型视图投影矩阵的作用,就是将顶点从局部坐标系转化到规范立方体中,总而言之, 模型视图投影矩阵 = 模型矩阵视图矩阵投影矩阵;
模型矩阵: 将顶点从局部坐标系转换到世界坐标系中;
视图矩阵: 将顶点从世界坐标转化到视图坐标系下;
投影矩阵: 将顶点从视图坐标系转换到规范立方体中(即屏幕中);
再来熟悉几个头文件:
//包含了大部分GLTool中类似C语言的独立函数
#include "GLTools.h"
//矩阵工具类,可以利用GLMatrixStack加载单元矩阵/矩阵/矩阵相乘/压栈/出栈/缩放/平移/旋转
#include "GLMatrixStack.h"
//矩阵工具类,表示位置。通过设置vOrigin,vForward,vUp
#include "GLFrame.h"
//矩阵工具类,用来快速设置 正/透 投影矩阵,完成坐标从3d->2d的映射
#include "GLFrustum.h"
//批次类,帮助类,可以传输顶点/光照/纹理/颜色等数据到着色器中
#include "GLBatch.h"
//变换管道类:用来快速在代码中传输视图矩阵/投影矩阵/视图投影变换矩阵等
#include "GLGeometryTransform.h"
//数学库
#include <math.h>
平面着色器实现一个金字塔的效果
着色器的种类很多,这里就不一一举例了,用法都是流程都是一样的,只是根据不同的需求选择不同的着色器跟不同的算法。
定义一些变量:
GLShaderManager shaderManager; //着色器管理类
GLMatrixStack modelViewMatrix; //模型视图矩阵堆栈
GLMatrixStack projectionMatrix; //透视矩阵堆栈
GLFrame cameraFrame; //观察者位置
GLFrame objectFrame; //物体本身的位置
GLFrustum viewFrustum; //投影矩阵
GLBatch triangleBatch; //批次类
GLGeometryTransform transformPipeline; //几何变换的管道
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f }; //金字塔颜色
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f }; //金字塔分割线的颜色
具体项目源码看附件Demo,这里只写关键代码
初始化准备
void SetupRC()
{
//清屏并设置背影颜色
glClearColor(0.3f,0.3f,0.3f,1.0f);
//初始化着色管理器
shaderManager.InitializeStockShaders();
//开始深度测试
glEnable(GL_DEPTH_TEST);
//设置变换管线以使用两个矩阵
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
//移动观察者的位置 :-15表示离观察者的距离,设置为-30则离观察者更远,看到的图形效果就小一些
cameraFrame.MoveForward(-15);
//定义一些点表示金字塔的顶点
GLfloat vPyramid[12][3] = {
-2.0f, 0.0f, -2.0f,
2.0f, 0.0f, -2.0f,
0.0f, 4.0f, 0.0f,
2.0f, 0.0f, -2.0f,
2.0f, 0.0f, 2.0f,
0.0f, 4.0f, 0.0f,
2.0f, 0.0f, 2.0f,
-2.0f, 0.0f, 2.0f,
0.0f, 4.0f, 0.0f,
-2.0f, 0.0f, 2.0f,
-2.0f, 0.0f, -2.0f,
0.0f, 4.0f, 0.0f
};
//批次处理
triangleBatch.Begin(GL_TRIANGLES,12);
triangleBatch.CopyVertexData3f(vPyramid);
triangleBatch.End();
}
changeSize回调
//窗口大小改变时接受新的宽度和高度,其中0,0代表窗口中视口的左下角坐标,w,h代表像素
void ChangeSize(int w,int h)
{
glViewport(0,0, w, h);
/* 创建投影矩阵,并把它加入到投影矩阵堆栈
* 参数说明 : 垂直方向视场角度、窗口宽度与高度的纵横比、近裁剪面距离、远裁剪面距离
*/
viewFrustum.SetPerspective(40.0f, float(w) / float(h), 1.0f, 500.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//载入单元矩阵、单元矩阵的话可以不写
modelViewMatrix.LoadIdentity();
}
特殊键位来控制金字塔的旋转
//特殊键位处理
void SpecialKeys(int key ,int x ,int y)
{
if(key == GLUT_KEY_UP)
//围绕一个指定的X,Y,Z轴旋转。
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_DOWN)
objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_LEFT)
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
if(key == GLUT_KEY_RIGHT)
objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
glutPostRedisplay();
}
RenderScene开始渲染场景
void RenderScene(void)
{
//清除一个或一组特定的缓冲区 执行
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//将当前变换矩阵(单位矩阵)压入堆栈 glPushMatrix的目的是让各次变换相互独立 push跟pop对应
modelViewMatrix.PushMatrix();
//获得观察者的矩阵堆栈
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
//压栈:视图矩阵 ,也可以直接矩阵相乘 ,如果是push的话,后面就需要另外一个pop
// modelViewMatrix.PushMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
M3DMatrix44f mObjectFrame;
//获取模型矩阵
objectFrame.GetMatrix(mObjectFrame);
modelViewMatrix.MultMatrix(mObjectFrame);
//使用平面着色器
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
//开始画金字塔
DrawGoldTowerBatch(&triangleBatch);
modelViewMatrix.PopMatrix();
//将在后台缓冲区进行渲染,然后在结束时交换到前台
glutSwapBuffers();
}
开始画金字塔
void DrawGoldTowerBatch(GLBatch* pBatch)
{
/*------------画青色部分----------------*/
/* GLShaderManager 中的Uniform 值——平面着色器
参数1:平面着色器
参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
--transformPipeline 变换管线(指定了2个矩阵堆栈)
参数3:颜色值
*/
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
pBatch->Draw();
/*-----------边框部分-------------------*/
/*
glEnable(GLenum mode); 用于启用各种功能。功能由参数决定
参数列表:http://blog.csdn.net/augusdi/article/details/23747081
注意:glEnable() 不能写在glBegin() 和 glEnd()中间
GL_POLYGON_OFFSET_LINE 根据函数glPolygonOffset的设置,启用线的深度偏移
GL_LINE_SMOOTH 执行后,过虑线点的锯齿
GL_BLEND 启用颜色混合。例如实现半透明效果
GL_DEPTH_TEST 启用深度测试 根据坐标的远近自动隐藏被遮住的图形(材料
glDisable(GLenum mode); 用于关闭指定的功能 功能由参数决定
*/
//画黑色边框
//偏移深度,在同一位置要绘制填充和边线,会产生z冲突,所以要偏移
glPolygonOffset(-1.0f, -1.0f);
glEnable(GL_POLYGON_OFFSET_LINE);
// 画反锯齿,让黑边好看些
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//绘制线框几何黑色版 三种模式,实心,边框,点,可以作用在正面,背面,或者两面
//通过调用glPolygonMode将多边形正面或者背面设为线框模式,实现线框渲染
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//设置线条宽度
glLineWidth(2.5f);
/* GLShaderManager 中的Uniform 值——平面着色器
参数1:平面着色器
参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
--transformPipeline.GetModelViewProjectionMatrix() 获取的
GetMatrix函数就可以获得矩阵堆栈顶部的值
参数3:颜色值(黑色)
*/
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw();
// 复原原本的设置
////通过调用glPolygonMode将多边形正面或者背面设为全部填充模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
运行效果如下:
jzt.gif
demo链接:https://download.csdn.net/download/zc971188623/11180298