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. stardog 基本试用(社区版)

    stardog 是一个知识图谱的实现,实现了sparql 以及graphql 协议,使用起来也比较简单,官方文档挺全 下载 社区版,注册之后会有邮件通知,里面会包含license 以及软件包 下载地址 ...

  2. StreamSets sdc rpc 测试

    一个简单的参考图 destination pipeline 创建 pipeline flow sdc destination 配置 origin sdc rpc pipeline pipeline f ...

  3. TensorFlow笔记-07-神经网络优化-学习率,滑动平均

    TensorFlow笔记-07-神经网络优化-学习率,滑动平均 学习率 学习率 learning_rate: 表示了每次参数更新的幅度大小.学习率过大,会导致待优化的参数在最小值附近波动,不收敛:学习 ...

  4. Arrays、ArrayUtils 区别

    Arrays java.util 包提供的静态类:java.util.Arrays 此静态类专门用来操作array ,提供搜索.排序.复制等静态方法. ArrayUtils apache 提供的类:o ...

  5. python值传递和指针传递

    a= 1def change_integer(a):        a=a+1        return a print change_integer(a)print a b= [1, 2, 3] ...

  6. SQL Server Management Studio (SSMS) 清除登录记录

    对于 SQL Server 2005 Management Studio,可以删除以下文件清空该列表: WinXP: C:\Documents and Settings\<user>\Ap ...

  7. node基于express的socket.io

    前一段事件,我一个同学给他们公司用融云搭建了一套web及时通信系统,然后之前我的公司也用过环云来实现web及时通信,本人对web及时通信还是非常感兴趣的.私下读了融云和环信的开发文档,然后发现如果注册 ...

  8. 终于完成了 源码 编译lnmp环境

    经过了大概一个星期的努力,终于按照海生的编译流程将lnmp环境源码安装出来了 nginx 和php 主要参考 http://hessian.cn/p/1273.html mysql 主要参考 http ...

  9. 2018-2019学年第一学期Java课设--魔塔

    目录 Magic-Towers 一.团队名称.团队成员介绍.任务分配 团队名称:MoTa 团队成员介绍 任务分配 二.项目简介 三.项目采用技术 四.项目亮点 主界面显示主要信息功能 游戏动画 五.项 ...

  10. 【Spring学习笔记-MVC-13.2】Spring MVC之多文件上传

    作者:ssslinppp       1. 摘要 前篇文章讲解了单文件上传<[Spring学习笔记-MVC-13]Spring MVC之文件上传>http://www.cnblogs.co ...