基于OpenGL编写一个简易的2D渲染框架-10 重构渲染器-Pass
Pass,渲染通路,一个渲染通路指的是一次像素处理和一次顶点处理,也就是指的是一次绘制。简单来说就是顶点数据在渲染管线中走一遍最后绘制。
渲染粒子系统的粒子时,需要开启 OpenGL 的混合模式,并使两个颜色相加。如果同一时间进行多张图片的绘制,并且这些图片的渲染并不需要开启混合模式。这时渲染的最终结果就是图片的渲染出现问题,这并不是我们想要的结果。一个解决方法就是进行两次 draw,第一次开启混合模式渲染粒子系统的粒子,第二次则关闭混合模式渲染图片。
上面解决方法的实现可以通过两个 Pass 渲染,第一个 Pass 设置开启混模式,第二个 Pass 关闭混合模式,进行两个 Pass 的渲染就可以了。
Simple2D 的 Pass 设计比较简单,主要实现
1、裁剪测试、Alpha 测试、模板测试、深度测试和混合模式的设置。
2、填充模式、面剔除模式、顶点正面方向的设置。
Pass 的成员属性添加这些测试是否开启的开关量:
bool bEnableScissor; /* 裁剪测试 */
bool bEnableAlphaTest; /* Alpha 测试 */
bool bEnableStencilTest; /* 模板测试 */
bool bEnableDepthTest; /* 深度测试 */
bool bEnableBlend; /* 混合模式 */
bool bEnableCullFace;
接下来就是各种测试的属性变量:
/* 剔除模式 */
enum CullMode
{
CULL_MODE_BACK, /* 只剔除背面 */
CULL_MODE_FRONT, /* 只剔除正面 */
CULL_MODE_FRONT_AND_BACK /* 剔除背面和正面 */
}; /* 正面的顶点顺序 */
enum FrontFace
{
FRONT_FACE_CLOCK_WISE, /* 顺时针为正面 */
FRONT_FACE_COUNTER_CLOCK_WISE, /* 逆时针为正面 */
}; /* 填充模式 */
enum FillMode
{
FILL_LINE, /* 线框 */
FILL_POINT, /* 点 */
FILL_FILL /* 实体 */
}; /* 混合方程 */
enum BlendEquation
{
BLEND_ADD, /* 彼此元素相加 */
BLEND_SUNTRACT, /* 彼此元素相减 */
BLEND_REVERSE_SUBTRACT /* 彼此元素相减,但顺序相反 */
}; /* 混合因子 */
enum BlendFunc
{
BLEND_ZERO,
BLEND_ONE,
BLEND_SRC_COLOR,
BLEND_ONE_MINUS_SRC_COLOR,
BLEND_DST_COLOR,
BLEND_ONE_MINUS_DST_COLOR,
BLEND_SRC_ALPHA,
BLEND_ONE_MINUS_SRC_ALPHA,
BLEND_DST_ALPHA,
BLEND_ONE_MINUS_DST_ALPHA,
BLEND_CONSTANT_COLOR,
BLEND_ONE_MINUS_CONSTANT_COLOR,
BLEND_CONSTANT_ALPHA,
BLEND_ONE_MINUS_CONSTANT_ALPHA
}; /* 比较函数 */
enum CompareFunction
{
COMPARE_LESS, /* 在片段深度值小于缓冲区的深度时通过测试 */
COMPARE_LEQUAL, /* 在片段深度值小于等于缓冲区的深度时通过测试 */ COMPARE_GREATER, /* 在片段深度值大于缓冲区的深度时通过测试 */
COMPARE_GEQUAL, /* 在片段深度值大于等于缓冲区的深度时通过测试 */ COMPARE_EQUAL, /* 在片段深度值等于缓冲区的深度时通过测试 */
COMPARE_NOT_EQUAL, /* 在片段深度值不等于缓冲区的深度时通过测试 */ COMPARE_ALWAYS, /* 永远通过测试 */
COMPARE_NEVER /* 永远不通过测试 */
}; /* 模板操作 */
enum StencilOp
{
STENCIL_OP_KEEP, /* 不改变,这也是默认值 */
STENCIL_OP_ZERO, /* 回零 */
STENCIL_OP_REPLACE, /* 使用测试条件中的设定值来代替当前模板值 */
STENCIL_OP_INCR, /* 增加1,但如果已经是最大值,则保持不变 */
STENCIL_OP_INCR_WRAP, /* 增加1,但如果已经是最大值,则从零重新开始 */
STENCIL_OP_DECR, /* 减少1,但如果已经是零,则保持不变 */
STENCIL_OP_DECR_WRAP, /* 减少1,但如果已经是零,则重新设置为最大值 */
STENCIL_OP_INVERT /* 按位取反 */
};
/* 裁剪测试,能够被绘制像素的区域 */
int nScissorX, nScissorY, nScissorW, nScissorH; /* Alpha 测试 */
CompareFunction alphaCompareFunction;
float fClampRef; /* 模板测试 */
CompareFunction stencilCompareFunction;
unsigned int nStencilMask;
int nStencilRef; StencilOp failStencilFailDepth;
StencilOp passStencilFailDepth;
StencilOp passStencilPassDepth; /* 深度测试,比较函数 */
CompareFunction depthCompareFunction; /* 混合方程和混合因子 */
BlendEquation blendEquation;
BlendFunc blendSrc, blendDst, blendSrcAlpha, blendDstAlpha;
接下来是设置各个测试的变量值:
void enableScissor(bool enable) { bEnableScissor = enable; }
void enableAlphaTest(bool enable) { bEnableAlphaTest = enable; }
void enableStencilTest(bool enable) { bEnableStencilTest = enable; }
void enableDepthTest(bool enable) { bEnableDepthTest = enable; }
void enableBlend(bool enable) { bEnableBlend = enable; }
void enableCullFace(bool enable) { bEnableCullFace = enable; }
void setFillMode(FillMode fm) { fillMode = fm; }
void setCullMode(CullMode cm) { cullMode = cm; }
void setFrontFace(FrontFace ff) { frontFace = ff; }
/* 设置裁剪区域 */
void setScissorRect(int x, int y, int w, int h) { nScissorX = x; nScissorY = y; nScissorW = w; nScissorH = h; }
void setAlphaCompareFunc(CompareFunction compare) { alphaCompareFunction = compare; }
void setAlphaClamf(float clamf) { fClampRef = clamf; }
void setStencilCompareFunc(CompareFunction compare) { stencilCompareFunction = compare; }
void setStencilMask(unsigned int mask) { nStencilMask = mask; }
void setStencilRef(int ref) { nStencilRef = ref; }
/* 更新模板缓冲操作 */
void setStencilOp(StencilOp sfail, StencilOp dpfail, StencilOp dppass) {
failStencilFailDepth = sfail;
passStencilFailDepth = dpfail;
passStencilPassDepth = dppass;
}
/* 设置深度测试比较函数 */
void setDepthCompareFunc(CompareFunction compare) { depthCompareFunction = compare; }
/* 设置混合操作的混合方程 */
void setBlendEquation(BlendEquation equation) { blendEquation = equation; }
/* 设置混合模式的混合因子 */
void setBlendFunc(BlendFunc srcColor, BlendFunc dstColor, BlendFunc srcAlpha, BlendFunc dstAlpha) {
blendSrc = srcColor;
blendDst = dstColor;
blendSrcAlpha = srcAlpha;
blendDstAlpha = dstAlpha;
}
上面没有什么好说的,关键的地方在于如何设置 OpenGL 的状态,
static int toEnum(CullMode cullmode)
{
switch ( cullmode ) {
case Simple2D::CULL_MODE_BACK: return GL_BACK;
case Simple2D::CULL_MODE_FRONT: return GL_FRONT;
case Simple2D::CULL_MODE_FRONT_AND_BACK: return GL_FRONT_AND_BACK;
}
return GL_BACK;
} static int toEnum(FrontFace frontface)
{
switch ( frontface ) {
case Simple2D::FRONT_FACE_CLOCK_WISE: return GL_CW;
case Simple2D::FRONT_FACE_COUNTER_CLOCK_WISE: return GL_CCW;
}
return GL_CCW;
} static int toEnum(FillMode fillmode)
{
switch ( fillmode ) {
case Simple2D::FILL_LINE: return GL_LINE;
case Simple2D::FILL_POINT: return GL_POINT;
case Simple2D::FILL_FILL: return GL_FILL;
}
return GL_FILL;
} static int toEnum(BlendEquation equation)
{
switch ( equation ) {
case Simple2D::BLEND_ADD: return GL_FUNC_ADD;
case Simple2D::BLEND_SUNTRACT: return GL_FUNC_SUBTRACT;
case Simple2D::BLEND_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
}
return GL_FUNC_ADD;
} static int toEnum(BlendFunc func)
{
switch ( func ) {
case Simple2D::BLEND_ZERO: return GL_ZERO;
case Simple2D::BLEND_ONE: return GL_ONE;
case Simple2D::BLEND_SRC_COLOR: return GL_SRC_COLOR;
case Simple2D::BLEND_ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
case Simple2D::BLEND_DST_COLOR: return GL_DST_COLOR;
case Simple2D::BLEND_ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
case Simple2D::BLEND_SRC_ALPHA: return GL_SRC_ALPHA;
case Simple2D::BLEND_ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
case Simple2D::BLEND_DST_ALPHA: return GL_DST_ALPHA;
case Simple2D::BLEND_ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
case Simple2D::BLEND_CONSTANT_COLOR: return GL_CONSTANT_COLOR;
case Simple2D::BLEND_ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
case Simple2D::BLEND_CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
case Simple2D::BLEND_ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
}
return GL_ONE;
} static int toEnum(CompareFunction compare)
{
switch ( compare ) {
case Simple2D::COMPARE_LESS: return GL_LESS;
case Simple2D::COMPARE_LEQUAL: return GL_LEQUAL;
case Simple2D::COMPARE_GREATER: return GL_GREATER;
case Simple2D::COMPARE_GEQUAL: return GL_GEQUAL;
case Simple2D::COMPARE_EQUAL: return GL_EQUAL;
case Simple2D::COMPARE_NOT_EQUAL: return GL_NOTEQUAL;
case Simple2D::COMPARE_ALWAYS: return GL_ALWAYS;
case Simple2D::COMPARE_NEVER: return GL_NEVER;
}
return GL_LESS;
} static int toEnum(StencilOp stencilOp)
{
switch ( stencilOp ) {
case Simple2D::STENCIL_OP_KEEP: return GL_KEEP;
case Simple2D::STENCIL_OP_ZERO: return GL_ZERO;
case Simple2D::STENCIL_OP_REPLACE: return GL_REPLACE;
case Simple2D::STENCIL_OP_INCR: return GL_INCR;
case Simple2D::STENCIL_OP_INCR_WRAP: return GL_INCR_WRAP;
case Simple2D::STENCIL_OP_DECR: return GL_DECR;
case Simple2D::STENCIL_OP_DECR_WRAP: return GL_DECR_WRAP;
case Simple2D::STENCIL_OP_INVERT: return GL_INVERT;
}
return GL_KEEP;
}
void Pass::setOpenGLState()
{
/* 面剔除 */
if ( bEnableCullFace ) {
glEnable(GL_CULL_FACE);
glCullFace(toEnum(cullMode));
glFrontFace(toEnum(frontFace));
}
else {
glDisable(GL_CULL_FACE);
} /* 填充模式 */
glPolygonMode(GL_FRONT_AND_BACK, toEnum(fillMode)); /* 裁剪测试 */
if ( bEnableScissor ) {
glEnable(GL_SCISSOR_TEST);
/* 左下角为坐标原点 */
glScissor(nScissorX, nScissorY, nScissorW, nScissorH);
}
else {
glDisable(GL_SCISSOR_TEST);
} /* Alpha 测试 */
if ( bEnableAlphaTest ) {
glEnable(GL_ALPHA_TEST);
glAlphaFunc(toEnum(alphaCompareFunction), fClampRef);
}
else {
glDisable(GL_ALPHA_TEST);
} /* 模板测试 */
if ( bEnableStencilTest ) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(toEnum(stencilCompareFunction), nStencilRef, nStencilMask);
glStencilOp(toEnum(failStencilFailDepth), toEnum(passStencilFailDepth), toEnum(passStencilPassDepth));
}
else {
glDisable(GL_STENCIL_TEST);
} /* 深度测试 */
if ( bEnableDepthTest ) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(toEnum(depthCompareFunction));
}
else {
glDisable(GL_DEPTH_TEST);
} /* 混合模式 */
if ( bEnableBlend ) {
glEnable(GL_BLEND);
glBlendEquation(toEnum(blendEquation));
glBlendFuncSeparate(toEnum(blendSrc), toEnum(blendDst), toEnum(blendSrcAlpha), toEnum(blendDstAlpha));
}
else {
glDisable(GL_BLEND);
}
}
根据先前设计的类图

每个 Pass 都有一个 Shader 的成员变量,所以 Pass 类还要添加 Shader 的成员变量,不仅如此,绘制时的图元类型也被设计在 Pass 中:
PrimType primType;
Shader* pShader;
整个 Pass 类的设计比较简单,源码在完成重构渲染器后给出。
基于OpenGL编写一个简易的2D渲染框架-10 重构渲染器-Pass的更多相关文章
- 基于OpenGL编写一个简易的2D渲染框架-05 渲染文本
阅读文章前需要了解的知识:文本渲染 https://learnopengl-cn.github.io/06%20In%20Practice/02%20Text%20Rendering/ 简要步骤: 获 ...
- 基于OpenGL编写一个简易的2D渲染框架-06 编写一个粒子系统
在这篇文章中,我将详细说明如何编写一个简易的粒子系统. 粒子系统可以模拟许多效果,下图便是这次的粒子系统的显示效果.为了方便演示,就弄成了一个动图. 图中,同时显示了 7 种不同粒子效果,看上去效果挺 ...
- 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口
最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了. 如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/ 我用的 ...
- 基于OpenGL编写一个简易的2D渲染框架-08 重构渲染器-整体架构
事实上,前面编写的渲染器 Renderer 非常简陋,虽然能够进行一些简单的渲染,但是它并不能满足我们的要求. 当渲染粒子系统时,需要开启混合模式,但渲染其他顶点时却不需要开启混合模式.所以同时渲染粒 ...
- 基于OpenGL编写一个简易的2D渲染框架-04 绘制图片
阅读文章前需要了解的知识,纹理:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 过程简述:利用 FreeI ...
- 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader
Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...
- 基于OpenGL编写一个简易的2D渲染框架-03 渲染基本几何图形
阅读文章前需要了解的知识,你好,三角形:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 要 ...
- 基于OpenGL编写一个简易的2D渲染框架-02 搭建OpenGL环境
由于没有使用GLFW库,接下来得费一番功夫. 阅读这篇文章前请看一下这个网页:https://learnopengl-cn.github.io/01%20Getting%20started/02%20 ...
- 基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer
假如要渲染一个纯色矩形在窗口上,应该怎么做? 先确定顶点的格式,一个顶点应该包含位置信息 vec3 以及颜色信息 vec4,所以顶点的结构体定义可以这样: struct Vertex { Vec3 p ...
随机推荐
- stardog 基本试用(社区版)
stardog 是一个知识图谱的实现,实现了sparql 以及graphql 协议,使用起来也比较简单,官方文档挺全 下载 社区版,注册之后会有邮件通知,里面会包含license 以及软件包 下载地址 ...
- StreamSets sdc rpc 测试
一个简单的参考图 destination pipeline 创建 pipeline flow sdc destination 配置 origin sdc rpc pipeline pipeline f ...
- TensorFlow笔记-07-神经网络优化-学习率,滑动平均
TensorFlow笔记-07-神经网络优化-学习率,滑动平均 学习率 学习率 learning_rate: 表示了每次参数更新的幅度大小.学习率过大,会导致待优化的参数在最小值附近波动,不收敛:学习 ...
- Arrays、ArrayUtils 区别
Arrays java.util 包提供的静态类:java.util.Arrays 此静态类专门用来操作array ,提供搜索.排序.复制等静态方法. ArrayUtils apache 提供的类:o ...
- python值传递和指针传递
a= 1def change_integer(a): a=a+1 return a print change_integer(a)print a b= [1, 2, 3] ...
- SQL Server Management Studio (SSMS) 清除登录记录
对于 SQL Server 2005 Management Studio,可以删除以下文件清空该列表: WinXP: C:\Documents and Settings\<user>\Ap ...
- node基于express的socket.io
前一段事件,我一个同学给他们公司用融云搭建了一套web及时通信系统,然后之前我的公司也用过环云来实现web及时通信,本人对web及时通信还是非常感兴趣的.私下读了融云和环信的开发文档,然后发现如果注册 ...
- 终于完成了 源码 编译lnmp环境
经过了大概一个星期的努力,终于按照海生的编译流程将lnmp环境源码安装出来了 nginx 和php 主要参考 http://hessian.cn/p/1273.html mysql 主要参考 http ...
- 2018-2019学年第一学期Java课设--魔塔
目录 Magic-Towers 一.团队名称.团队成员介绍.任务分配 团队名称:MoTa 团队成员介绍 任务分配 二.项目简介 三.项目采用技术 四.项目亮点 主界面显示主要信息功能 游戏动画 五.项 ...
- 【Spring学习笔记-MVC-13.2】Spring MVC之多文件上传
作者:ssslinppp 1. 摘要 前篇文章讲解了单文件上传<[Spring学习笔记-MVC-13]Spring MVC之文件上传>http://www.cnblogs.co ...