osg使用整理(11):延迟渲染

news/2025/4/3 5:05:13/文章来源:https://www.cnblogs.com/wangxydela/p/18229888

osg使用整理(11):延迟渲染

一、基础概念

  1. 前向渲染流程:顶点着色器->图元装配成点线三角形->几何着色器->裁剪剔除->光栅化(片元着色器)->透明度测试、深度测试。

  2. 延迟渲染流程:顶点着色器->图元装配成点线三角形->几何着色器->裁剪剔除->光栅化输出G-Buffer,存储每个像素的属性信息(位置、法线、颜色)->深度测试->光照计算->片元着色器->透明度测试。

  3. 渲染管线的差异:

    a. 延迟渲染需要两个pass,先生成G-Buffer后进行光照计算。

    b. 延迟渲染不能使用MSAA算法抗锯齿。

  4. 优劣势:

    a. 延迟渲染先进行深度测试,确定了可见像素后再进行光照计算,而不是对所有图元进行光栅化再光照计算,避免了大量无效计算。

    b. 延迟渲染在一个Pass中处理多光源计算,提高了渲染效率。

    c. 延迟渲染的G-Buffer占用带宽较大,需要合并一些纹理通道、减少buffer位数、将两个pass合并为OnePassDeferred。

    d. 延迟渲染通常只能使用相同光照的效果,灵活性低。

    e. 延迟渲染中透明物体需要单独的Pass来处理。

二、G-Buffer

​ 如下图所示,延迟渲染首先生成称为G-Buffer的一系列纹理,常包含世界坐标系下的位置向量、颜色向量、顶点法线向量等等。

​ osg中要实现延迟渲染,首先准备离屏相机:

osg::ref_ptr<RttCamera> createRTTCamera(osg::Camera::BufferComponent buffer,osg::Texture* tex,int width,int height)
{osg::ref_ptr<RttCamera> camera=new RttCamera(width,height);camera->setRenderTargetImplementation(osg::Camera::RenderTargetImplementation::FRAME_BUFFER_OBJECT);camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);camera->setPostDrawCallBack(new FBOPostDrawCallback);camera->setRenderOrder(osg::Camera::PRE_RENDER,20);camera->setViewPort(0,0,width,height);if(tex){tex->setFilter(osg::Texture::MIN_FILTER,osg::Texture;;LINER_MIPMAP);tex->setFilter(osg::Texture::MAG_FILTER,osg::Texture;;LINER_MIPMAP);camera->setViewPort(0,0,tex->getTextureWidth(),tex->getTextureHeight());camera->attach(buffer,tex);}return camera;
}

​ 注意到,离屏相机渲染目标设置为FBO,同时渲染次序设置为PRE_RENDER。然后准备附着在离屏相机上的颜色和深度纹理,简单认为有三维位置坐标纹理、法线方向纹理、基础颜色纹理三个。为了提高纹理精度,实现HDR渲染,我们可以使用浮点数缓冲,其内部格式通常设为GL_RGB16F, GL_RGBA16F, GL_RGB32F 或者GL_RGBA32F。浮点数缓冲可以存储超过0.0到1.0范围的浮点值。

//创建颜色附着纹理
osg::ref_ptr<osg::Texture2D> createColorTexture(int width,int height)
{osg::ref_ptr<osg::Texture2D> texture=new osg::Texture2D;texture->setTextureSize(width,height);texture->setInternalFormat(GL_RGBA32F);texture->setSourceFormat(GL_RGBA);texture->setSourceType(GL_FLOAT);//浮点数精度更高tex->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);tex->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);return texture;
}
//创建深度附着纹理
osg::ref_ptr<osg::Texture2D> createDepthTexture(int width,int height)
{osg::ref_ptr<osg::Texture2D> texture=new osg::Texture2D;texture->setTextureSize(width,height);texture->setInternalFormat(GL_DEPTH_COMPONENT32F);texture->setSourceFormat(GL_DEPTH_COMPONENT32F);texture->setSourceType(GL_FLOAT);tex->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);tex->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);return texture;	
}

​ 创建延迟渲染相机,首先渲染到G-buffer上,然后创建HUD相机渲染到和屏幕同样大小的矩形上。

/*延迟渲染相机*/
osg::ref_ptr<RttCamera> createDeferCamera(osg::Camera::BufferComponent buffer1,osg::Texture* tex1,osg::Camera::BufferComponent buffer2,osg::Texture* tex2,osg::Camera::BufferComponent buffer3,osg::Texture* tex3,int width,int height)
{osg::ref_ptr<RttCamera> camera=new RttCamera(width,height);camera->setRenderTargetImplementation(osg::Camera::RenderTargetImplementation::FRAME_BUFFER_OBJECT);camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);camera->setPostDrawCallBack(new FBOPostDrawCallback);camera->setRenderOrder(osg::Camera::PRE_RENDER,20);camera->setViewPort(0,0,width,height);if(tex1){tex1->setFilter(osg::Texture::MIN_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);tex1->setFilter(osg::Texture::MAG_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);camera->attach(buffer1,tex1);}if(tex2){tex2->setFilter(osg::Texture::MIN_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);tex2->setFilter(osg::Texture::MAG_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);camera->attach(buffer2,tex2);}if(tex3){tex3->setFilter(osg::Texture::MIN_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);tex3->setFilter(osg::Texture::MAG_FILTER,osg::Texture;;LINER_MIPMAP_NEAREST);camera->attach(buffer3,tex3);}///顶点着色器const char* vertCode=R"(#version 330layout(location = 0) in vec3 Position;layout(location = 2) in vec3 normal;layout(location = 3) in vec3 TexCoord;uniform mat4 osg_ModelViewProjectionMatrix;uniform mat4 osg_ModelViewMatrix;uniform mat4 osg_NormalMatrix;out vec3 vNormal;out vec2 texCoord;out vec4 fragPos;void main(){texCoord=TexCoord;fragPos=osg_ModelViewMatrix*vec4(Position,1.0);vec4 viewNorm=transpose(inverse(osg_ModelViewMatrix))*vec4(-normal,1.0);vNormal=normalize(viewNorm.xyz);gl_Position=osg_ModelViewProjectionMatrix*vec4(Position,1.0);})";const char* fragCode=R"(#version 330 coreuniform vec3 frontCol=vec3(1.0,0.0,0.2);layout (location = 0) out vec4 gColor;layout (location = 1) out vec4 gNormal;layout (location = 2) out vec4 gPosition;in vec2 texCoord;in vec4 fragPos;in vec3 vNormal;void main(){    // Store the fragment position vector in the first gbuffer texturegPosition.xyz = fragPos.xyz;// Also store the per-fragment normals into the gbuffergNormal = vec4(vNormal,1.0);          gColor=vec4(frontCol,1.0);})";osg::ref_ptr<osg::Shader> vertShader=new osg::Shader(osg::Shader::VERTEX,vertCode);osg::ref_ptr<osg::Shader> fragShader=new osg::Shader(osg::Shader::FRAGMENT,fragCode);osg::ref_ptr<osg::Program>  program=new osg::Program;program->addShader(vertShader);program->addShader(fragShader);camera->getOrCreateStateSet()->setAttributeAndModes(program,OVERRIDE_ON);return camera;
}

​ HUD相机用于将纹理混合结果输出到屏幕上,需要注意绑定一个矩形几何为子节点,并正确设置渲染目标,设置RenderOrder为POST_RENDER。

/*延迟HUD相机*/
osg::ref_ptr<RttCamera> createHUDCamera(osg::Texture* tex1,osg::Texture* tex2,int width,int height)
{osg::ref_ptr<RttCamera> camera=new RttCamera(width,height);camera->setClearMask(GL_DEPTH_BUFFER_BIT);camera->setPostDrawCallBack(new FBOPostDrawCallback);camera->setRenderOrder(osg::Camera::POST_RENDER,100);camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF)camera->setProjectMatrix(osg::Matrix::ortho2D(width,-width,-height,height))camera->setViewPort(0,0,width,height);camera->addChild(createQuadGeode(tex1,tex2,width,height));return camera;
}/*平铺的四边形几何*/
osg::ref_ptr<osg::Geode> createQuadGeode(osg::Texture* baseTexture,osg::Texture* modelTexture,int width,int height)
{///创建四边形顶点osg::ref_ptr<osg:Vec3Array> vertices= new osg::Vec3Array;vertices->push_back(osg::Vec3(-width,-height,0.f));vertices->push_back(osg::Vec3(width,-height,0.f));vertices->push_back(osg::Vec3(width,height,0.f));vertices->push_back(osg::Vec3(width,-height,0.f));///创建四边形法线osg::ref_ptr<osg:Vec3Array> normals= new osg::Vec3Array;normals->push_back(osg::Vec3(0.0,0.0,2.f));///创建四边形纹理坐标osg::ref_ptr<osg:Vec2Array> texCoords= new osg::Vec2Array;texCoords->push_back(osg::Vec2(1.0,0.f));texCoords->push_back(osg::Vec2(0.0,0.f));texCoords->push_back(osg::Vec2(0.0,1.f));texCoords->push_back(osg::Vec2(1.0,1.f));///创建四边形几何osg::ref_ptr<osg:Geometry> quad= new osg::Geometry;quad->setVertexArray(vertices);quad->setNormalArray(normals);quad->setTexCoordArray(0,texCoords);quad->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));///创建四边形节点osg::ref_ptr<osg::Geode> quadGeode=new osg::Geode;quadGeode->addDrawable(quad);quadGeode->getOrCreateStateSet()->addUniform(new osg::Uniform("baseTexture",0)));quadGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0,baseTexture);quadGeode->getOrCreateStateSet()->addUniform(new osg::Uniform("modelTexture",1)));quadGeode->getOrCreateStateSet()->setTextureAttributeAndModes(1,modelTexture);const char* vertCode=R"(#version 330layout(location = 0) in vec3 Position;layout(location = 2) in vec3 normal;layout(location = 3) in vec3 TexCoord;uniform mat4 osg_ModelViewProjectionMatrix;uniform mat4 osg_ModelViewMatrix;uniform mat4 osg_NormalMatrix;out vec2 texCoord;void main(){texCoord=TexCoord;gl_Position=osg_ModelViewProjectionMatrix*vec4(Position,1.0);})";const char* fragCode=R"(uniform sampler2D baseTexture;uniform sampler2D modelTexture;in vec2 texCoord;out vec4 fragColor;void main(){vec4 modelCol=texture(modelTexture,texCoord);vec4 baseCol=texture(baseTexture,texCoord);fragColor=vec4(mix(modelCol.rgb,baseCol.rgb,baseCol.a),baseCol.a+modelCol.a);})";osg::ref_ptr<osg::Shader> vertShader=new osg::Shader(osg::Shader::VERTEX,vertCode);osg::ref_ptr<osg::Shader> fragShader=new osg::Shader(osg::Shader::FRAGMENT,fragCode);osg::ref_ptr<osg::Program>  program=new osg::Program;program->addShader(vertShader);program->addShader(fragShader);quadGeode->getOrCreateStateSet()->setAttributeAndModes(program,OVERRIDE_ON);return quadGeode;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/719489.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

龙哥量化:期货软件中红红绿绿的多开,空开,空平,多平,多换,空换,双开,双平,换手是什么意思?(转载的)

期货投资者在看盘时,会看到红红绿绿的"多开,空开,空平,多平,多换,空换,双开,双平,换手",以快期专业版为例,如下图1所示:图1.红绿开平数据(快期专业版) 这些数据里面的红色和绿色是什么意思呢?红色表示主动买,绿色表示主动卖吗?多开,空开,多平,双…

6.3深圳安服面试

公司概况、企业文化、自己应聘职位的特点、工作内容 业务产品、研究领域,国家专精特新小巨人 安全咨询、培训、运营三位一体的网络安全综合服务,总部广州;业务: 等保,密评,风险评估,监测、巡检、渗透、应急、培训; 提供解决方案; 安全评估:包括主机漏扫、基线检查、渗…

CTFshow-Crypto(17-25)

17EZ_avbv(easy) 18贝斯多少呢 base62穷举分段 给了段编码,hint为base62 8nCDq36gzGn8hf4M2HJUsn4aYcYRBSJwj4aE0hbgpzHb4aHcH1zzC9C3IL随波逐流和Cyberchef都没梭哈出来 看了师傅们的wp大概意思是: 分组长度固定,但是不一定是被整除为整数,只要找到从头开始截取一个长度解…

平安-瀚景家族

三个月要求概要内容学习情况备注 三讲入司前:学习陈相妤(陈红梅)《讲“三讲”,赢得高端客户认同》 入司起第3个月:对所有人都适用的三讲,1分钟以上、3分钟以内,录视频发给推荐人 …

State设计模式上篇(理论篇)

State设计模式理论篇参考了王备战老师的ppt,相当于是一次期末复习总结吧 ⭐目标:目前的需求是我所制作的OJ项目在面临代码提交结果以及运行结果时对于其中的各个状态(如:通过!编译失败等等诸多状态进行代码开发时,很容易代码一不小心就写烂了,写到连自己都无法看懂的地步,所以尝…

vscode如何添加本地python解释器、解析器 Interpreter?(Python: Select Interpreter),并在vscode运行python代码

先安装python扩展 然后点ctrl+shift+p搜索python:select,选择解析器(或者也可以直接点左下方的) 然后360报毒了,允许通过,然后选择你想要的解释器 然后就好了 20230816 文章目录在VSCode中添加本地Python解释器 Python解释器简介为什么要在VSCode中设置Python解释器如…

红日靶场2

环境搭建 配置ip,web机有两张网卡,我对nat设置为192.168.11.0网段,仅主机为192.168.52.0网段,这三台机子都要改一下ip,官方给出要恢复快照3,恢复的时候有问题,不用恢复没有影响 web机的网络情况如下就可以了在这个目录下启动weblogic服务,以管理员身份运行startWebLogic…

C133 线段树分治 CF1681F Unique Occurrences

视频链接:C133 线段树分治 CF1681F Unique Occurrences_哔哩哔哩_bilibili Unique Occurrences - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) Problem - 1681F- Codeforces// 线段树分治 O(nlognlogn) #include <iostream> #include <cstring> #include <al…

P10536 [Opoi 2024] 二十六点 题解

比较直接的做法。 当 \(P_x = 1\) 时显然可以暴力 DP,设 \(f_{x,c}\) 表示 \(x\) 的子树中以 \(c\) 开头的最长不下降子序列的长度。直接转移即可。 \(P_x \neq 1\) 的时候呢?我们发现,所谓“忽略掉这些路径中的第 \(2\) 到第 \(P_x\) 个的点”,代表的就是按照深度转移,大…

数据对标?我搜集了7000+标准数据元分享给你

数据治理工作推进过程中比较关键的一步就是数据标准化,这里的数据标准化是指根据相关规范将数据达成统一技术要求的过程。 我国的主要标准分类包括国家标准、行业标准、地方标准和团体标准、企业标准。我们用的比较多的一般就是国标、行标和企业标准。 一、国家标准 国家标准,…

nrf24L01 check不通过问题分析

下面这段代码是有问题的,使nrf24L01 check不通过。 #include "stm32f10x.h" // Device header#include "spi.h" #include "OLED.h"/****** SPI2引脚连接 ******/ #define PA4_SPI1_NSS GPIO_Pin_4 #define PA5_SPI1_SCK GPIO_Pin_5 #define PA6…