基于OpenGL编写一个简易的2D渲染框架-10 重构渲…
2018-06-17 22:19:05来源:未知 阅读 ()
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 类的设计比较简单,源码在完成重构渲染器后给出。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:P1629 邮递员送信
- C++冒泡排序 (基于函数模板实现) 2020-05-31
- Android P HIDL demo代码编写 (原创) 2020-05-07
- Window中的shellcode编写框架(入门篇) 2020-03-31
- C++抓图服务 2020-03-31
- #《Essential C++》读书笔记# 第四章 基于对象的编程风格 2020-02-08
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash