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的更多相关文章

  1. 基于OpenGL编写一个简易的2D渲染框架-05 渲染文本

    阅读文章前需要了解的知识:文本渲染 https://learnopengl-cn.github.io/06%20In%20Practice/02%20Text%20Rendering/ 简要步骤: 获 ...

  2. 基于OpenGL编写一个简易的2D渲染框架-06 编写一个粒子系统

    在这篇文章中,我将详细说明如何编写一个简易的粒子系统. 粒子系统可以模拟许多效果,下图便是这次的粒子系统的显示效果.为了方便演示,就弄成了一个动图. 图中,同时显示了 7 种不同粒子效果,看上去效果挺 ...

  3. 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口

    最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了. 如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/ 我用的 ...

  4. 基于OpenGL编写一个简易的2D渲染框架-08 重构渲染器-整体架构

    事实上,前面编写的渲染器 Renderer 非常简陋,虽然能够进行一些简单的渲染,但是它并不能满足我们的要求. 当渲染粒子系统时,需要开启混合模式,但渲染其他顶点时却不需要开启混合模式.所以同时渲染粒 ...

  5. 基于OpenGL编写一个简易的2D渲染框架-04 绘制图片

    阅读文章前需要了解的知识,纹理:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 过程简述:利用 FreeI ...

  6. 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader

    Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...

  7. 基于OpenGL编写一个简易的2D渲染框架-03 渲染基本几何图形

    阅读文章前需要了解的知识,你好,三角形:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 要 ...

  8. 基于OpenGL编写一个简易的2D渲染框架-02 搭建OpenGL环境

    由于没有使用GLFW库,接下来得费一番功夫. 阅读这篇文章前请看一下这个网页:https://learnopengl-cn.github.io/01%20Getting%20started/02%20 ...

  9. 基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer

    假如要渲染一个纯色矩形在窗口上,应该怎么做? 先确定顶点的格式,一个顶点应该包含位置信息 vec3 以及颜色信息 vec4,所以顶点的结构体定义可以这样: struct Vertex { Vec3 p ...

随机推荐

  1. hasura 的3factor 架构结论

    hasura 是一个很不错的开发团队,开发了好几款,不错的产品,最近的graphql engine 是很热的一款 graphql 引擎,同时团队提出了3factor 系统架构理论 参考网站 https ...

  2. WebForm使用FileUpload控件上传压缩二进制图片

    fuImage 是FileUpload页面控件 ImageHelper.CompressionImage(fuImage.FileBytes, quality); /// <summary> ...

  3. zz 【见闻八卦】《金融时报》年度商业书单:互联网题材占一半

    [见闻八卦]<金融时报>年度商业书单:互联网题材占一半 文 / 见闻学堂 2014年12月18日 09:47:38 0   中国最好的金融求职培训:见闻学堂(微信号:top-elites) ...

  4. Centos7安装killall,fuser, killall,pstree和pstree.x11

    centos7精简安装后,使用中发现没有killall命令. 经查找,可以通过以下命令解决: yum -y install psmisc 简单介绍一下 psmisc : Psmisc软件包包含三个帮助 ...

  5. Application 应用对象

    在整个服务器运行过程中,application对象只有一个 下面的例子是访问次数的统计 <%@ page language="java" contentType=" ...

  6. github高效搜索使用总结

    swoole 普通搜索 in:name swoole 搜索仓库的名称,搜索仓库名称包含swoole关键字的所有项目 in:description swoole 搜索描述中包含swoole关键字的项目 ...

  7. 【python】重定向输出

    重定向的理解:就是把所要输出的结果输出到其他的地方.常用方法:"print >>",(若有其他方法后续补充) 举个例子: __author__ = 'paulwinfl ...

  8. mysql九大类常用函数

    一.数学函数 ABS(x) 返回x的绝对值BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制)CEILING(x) 返回大于x的最小整数值EXP(x) 返回值e(自然对数的底)的x次方 ...

  9. fiddler工具能干啥

    1.通过模拟弱网进行测试(试了木有效果) http://www.cnblogs.com/LanTianYou/p/7095174.html (试了貌似没反应) http://caibaojian.co ...

  10. HDU 2063 过山车(匈牙利算法)

    过山车 Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submissio ...