首页 > 其他分享 >osg使用整理(11):延迟渲染

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

时间:2024-06-03 23:11:34浏览次数:24  
标签:11 渲染 Texture camera new ref ptr osg

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_NEAREST);
		tex->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINER_MIPMAP_NEAREST);
		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 330
		layout(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 core
		uniform 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 texture
            gPosition.xyz = fragPos.xyz;
            // Also store the per-fragment normals into the gbuffer
            gNormal = 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 330
		layout(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;
}

标签:11,渲染,Texture,camera,new,ref,ptr,osg
From: https://www.cnblogs.com/wangxydela/p/18229888

相关文章

  • [C++] 小游戏 斗破苍穹 2.2.1至2.11.5所有版本(下) zty出品
    2.10.6#include<stdio.h>#include<iostream>#include<ctime>#include<bits/stdc++.h>#include<time.h>#include<windows.h>//SLEEP函数usingnamespacestd;intboss1=0,boss2=0;structPlayer{//玩家结构体,并初始化playercharname[21......
  • ABC 311 C Find it!
    题意给定一个有向图,其中有N个顶点和N条边。保证其中有一个环,请找出这个环并且输出环上的点。思路我们先将图dfs一遍,遍历到的点我们用map进行标记一下,并且储存在一个数组里面,当我们dfs到一个已经标记过的点时,此时则出现了环。那么如何将这个环输出出来呢?我们这个时候扫一遍刚刚......
  • 1120大整数加法
    没有多组输入 (还得是y总)QAQ//1.大整数加法#include<iostream>#include<vector>usingnamespacestd;vector<int>add(vector<int>&A,vector<int>&B){ vector<int>C; intt=0; for(inti=0;i<A.size()||i<B.size();i......
  • 1134高精度阶乘(数组)
    #include<stdio.h>#defineN3000//定义数组长度intmain(){inta[N],i,j,k,n;while(scanf("%d",&n)!=EOF){ for(i=0;i<N;i++)//初始化数组 a[i]=0; a[0]=1;//第一位设为1 k=0;//记录进位坐标 for(i=1;i<=n;i++)//计算阶乘......
  • Vue渲染函数与JSX指南
    title:Vue渲染函数与JSX指南date:2024/6/3下午6:43:53updated:2024/6/3下午6:43:53categories:前端开发tags:Vue渲染JSX基础性能优化组件对比ReactJSX大项目测试策略第1章:Vue.js入门Vue.js的历史和背景Vue.js是一个用于构建用户界面的JavaScript框架,旨......
  • error:connot bind non-const lvalue reference of type ‘std::__cxx11::string& {ak
    实习记录犯错日志:std::stringutf8_str=gbk_to_utf8((char*)struCIDAlarmInfo.sCIDCode);代码这样写则报如题所示的错误,error:connotbindnon-constlvaluereferenceoftype'std::__cxx11::string&{akastd::cxx11::basic_string<char>&}toanrvalueoftype'......
  • 云渲染农场什么是线程模式?
    ​许多设计师在选择云渲染农场时,常常会遇到48线程、56线程、72线程等选项,然而,不少新手在面对这些选择时,往往无法直观地感受到不同线程数量之间的差异。接下来,我们将共同探讨线程的作用和影响,帮助大家更好地理解这些选择。一、CPU线程的意思CPU线程是计算机处理器的基本工作单元......
  • vue项目,在切换分页时,render不重新渲染的问题
    在vue项目过程中,遇到table切换分页,数据已修改但页面没有渲染的情况。是因为数据层次太多,没有触发render函数进行自动更新。需要减少嵌套层级。九代码:render:function(h,data){if(data.row.uploadStatus===0&&(_this.data_permissions.includes(_this.all_data_......
  • 统计学研硕大数据统计练手11
    统计学Python练手作业11题目AI绘图仅供欣赏题目2024年的《政府工作报告》中提出“深化大数据、人工智能等研发应用,开展“人工智能+”行动,打造具有国际竞争力的数字产业集群”,请同学们结合自己工作的所在行业或领域谈一谈大数据技术在人工智能时代下的应用现状、......
  • 西屋1C31164G01
    抗干扰导航定位板卡Septentrio高精度卫星定位定向2024-04-0908:28安徽一、抗干扰导航定位板卡的介绍抗干扰导航定位板卡是一种能够有效应对外部干扰的定位设备,它可以在复杂的环境中提供精准的导航和定位服务。这种板卡能够通过内部的技术,在信号受到干扰时依然保持稳定并提......