Ogre-Deferred Shading

1、简介:

在渲染场景中的所有objects,而不包含光照。而且这些objects并不是被渲染到back buffer中,而是使用multiple render targets(MRT)渲染到一些off-screen buffers中(离线的bufffers)。在这些render targets中存储了场景的geometry数据,包括object的position,normal,color(一般是从一个diffuse color texture中采样得到),specular power和specular intensity。前面已经讲过render targets其实就是2D textures,但是在这里这些 geometry buffers(也称为G-buffer) 并不是存储color值,而是存储影响objects的lighting passs数据用于计算场景中所有pixels的最终color值。

对于场景中的每一种光源,都是从geometry buffers中采样数据,并计算被该光源影响的每一个pixel的直接和间接光照值。最后使用场景中所有光源产生的影响组合成最终的图像数据,并映射到一个full-screen quad中。

由于光照是在screen space中进行计算,渲染每一帧的计算成本主要由光源的数量以及受光源影响的pixels数量决定。Geometry数据是每一帧渲染一次,并且只对真正受到光源影响的geometry才会执行高成本的光照运算。除了具有高性能的优点之外,deferred shading还能简单一个渲染引擎的架构设计,因为使用这种方法场景中的所有objects可以共用一个shader。经常切换shaders会产生较大的性能开销,因此使用forward rendering方法的渲染引擎通常会批量处理使用相同materials的objects。如果不使用deferred shading系统,就需要一个更复杂的引擎架构。

缺点:
第一:使用deferred shading只能共用一种materials。
第二:geometry buffers需要占用大量的内存。
第三:deferred shading无法处理transparency(透明),透明效果通常由一个排序步骤 单独处理(from back to front,也就是距离camera的距离由远到近),并对透明的objects使用forward rendering pass。
第四:把geometry和lighting阶段分开计算,就无法使用硬件的anti-aliasing功能,因此需要使用一个额外的post-processing technique处理边缘的光滑度。

2、步骤:

1. 创建G-Buffer:

compositor DeferredShading/GBuffer
{
	technique
	{
		// temporary textures
		texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope
		
		target mrt_output
		{
			input none
			pass clear
			{
			}
			
			shadows off
			material_scheme GBuffer
			
			// everything but the lights and their meshes
			// could do this with something like a visibility mask too
			pass render_scene
			{
				//These values are synchronized with the code
				first_render_queue 10
				last_render_queue  79	
			}
		}
	}
}
上面创建G-Buffer合成器注意事项:
  • mrt_output 创建是两个纹理(MRT)
  • mrt_output 访问范围同一合成器链的后续合成器可用(类型:chain_scope)
  • pass中只能将渲染队列是10-79中的对象信息渲染到纹理上。并且为每个对象手动创建一个将信息写到G-Buffer中的技术方案
  • 这个合成器没有target_output pass因为G-Buffer是用来存储计算光照信息而不是最终渲染的纹理
  • 两个纹理(RenderTexture)存储信息:
    第一个纹理RGB:漫反射光颜色(DiffuseColour) 。 A:强度值(Specularity)
    第二个纹理RGB:相机空间下法线 。A:深度值

2. 给满足渲染G-Buffer的对象生成技术方案:
  (1)、重写Ogre::MaterialManager::ListenerGBufferSchemeHandler对象因为每次遍历renderable设置技术方案时Ogre::MaterialManager会查找当前活动材质名(这里我们设置名GBuffer),如果没有就执行这句GBufferSchemeHandler::handleSchemeNotFound() ,在这个方法里将我们为每个对象单独创建的ToGBuffer技术方案设置为当前活动的方案,如果是透明对象则设置名“NoGBuffer”(这个对象不渲染到GBuffer中后期处理).
GBufferSchemeHandler::inspectPass() 这个方法是用来检测该对象是否透明、漫反射颜色是否是白色、纹理是否有法线纹理等

  (2)、GBufferMaterialGenerator 类对象是给每个对象创建生成GBuffer信息的技术方案,因为每个对象的存储信息可能不一样所以我们要单独为每个对象动态创建技术方案。
例如某个对象创建的shader:

//顶点着色器
Ogre: void ToGBufferVP(
 float4 iPosition : POSITION,
 float3 iNormal   : NORMAL,
 float2 iUV0 : TEXCOORD0,

 out float4 oPosition : POSITION,
 out float3 oViewPos : TEXCOORD0,
 out float3 oNormal : TEXCOORD1,
 out float2 oUV0 : TEXCOORD2,

 uniform float4x4 cWorldViewProj,
 uniform float4x4 cWorldView
 )
{
 oPosition = mul(cWorldViewProj, iPosition);
 oNormal = mul(cWorldView, float4(iNormal,0)).xyz;
 oViewPos = mul(cWorldView, iPosition).xyz;
 oUV0 = iUV0;
}
//片元着色器
Ogre: void ToGBufferFP(
 float3 iViewPos : TEXCOORD0,
 float3 iNormal   : TEXCOORD1,
 float2 iUV0 : TEXCOORD2,

 out float4 oColor0 : COLOR0,
 out float4 oColor1 : COLOR1,

 uniform sampler sTex0 : register(s0),
 uniform float4 cDiffuseColour,
 uniform float cFarDistance,
 uniform float cSpecularity
 )
{
 oColor0.rgb = tex2D(sTex0, iUV0).rgb;
 oColor0.rgb *= cDiffuseColour.rgb;
 oColor0.a = cSpecularity;
 oColor1.rgb = normalize(iNormal);
 oColor1.a = length(iViewPos) / cFarDistance;
}

Technique* GBufferSchemeHandler::handleSchemeNotFound(unsigned short schemeIndex, 
        const String& schemeName, Material* originalMaterial, unsigned short lodIndex, 
        const Renderable* rend)
{
    Ogre::MaterialManager& matMgr = Ogre::MaterialManager::getSingleton();
    String curSchemeName = matMgr.getActiveScheme();
    matMgr.setActiveScheme(MaterialManager::DEFAULT_SCHEME_NAME);
    Technique* originalTechnique = originalMaterial->getBestTechnique(lodIndex, rend);
    matMgr.setActiveScheme(curSchemeName);

    Technique* gBufferTech = originalMaterial->createTechnique();
    gBufferTech->removeAllPasses();
    gBufferTech->setSchemeName(schemeName);

#ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
    RTShader::ShaderGenerator& rtShaderGen = RTShader::ShaderGenerator::getSingleton();
    rtShaderGen.createShaderBasedTechnique(*originalMaterial, originalTechnique->getSchemeName(), "NoGBuffer");
#else
    Technique* noGBufferTech = originalMaterial->createTechnique();
    noGBufferTech->removeAllPasses();
    noGBufferTech->setSchemeName("NoGBuffer");
#endif

    for (unsigned short i=0; i<originalTechnique->getNumPasses(); i++)
    {
        Pass* originalPass = originalTechnique->getPass(i);
        PassProperties props = inspectPass(originalPass, lodIndex, rend);
        
        if (!props.isDeferred)
        {
#ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
            rtShaderGen.validateMaterial("NoGBuffer", originalMaterial->getName(), originalMaterial->getGroup());
#else
            //Just copy the technique so it gets rendered regularly
            Pass* clonePass = noGBufferTech->createPass();
            *clonePass = *originalPass;
#endif
            continue;
        }
        Pass* newPass = gBufferTech->createPass();
        MaterialGenerator::Perm perm = getPermutation(props);
        const Ogre::MaterialPtr& templateMat = mMaterialGenerator.getMaterial(perm);
        //We assume that the GBuffer technique contains only one pass. But its true.
        *newPass = *(templateMat->getTechnique(0)->getPass(0));
        fillPass(newPass, originalPass, props);    
    }
    
    return gBufferTech;
}

3. 计算光照显示结果:

compositor DeferredShading/ShowLit
{
	technique
	{
		//Reference the main Gbuffer texture
		texture_ref mrt_output DeferredShading/GBuffer mrt_output
		
        target_output
        {
			input none
			//We will dispatch the shadow texture rendering ourselves
			shadows off
			
			pass clear
			{
				
			}
			
			// render skies and other pre-gbuffer objects
			pass render_scene
			{
				first_render_queue 1
				last_render_queue  9			
			}
			
			//Render the lights and their meshes
			pass render_custom DeferredLight
			{
				input 0 mrt_output 0
				input 1 mrt_output 1
			}
			
			//Render the objects that skipped rendering into the gbuffer
			pass render_scene
			{
				material_scheme NoGBuffer
				first_render_queue 10
				last_render_queue 79
			}
			
			//Render the post-GBuffer render queue objects
			pass render_scene
			{
				//This value is synchronized with the code
				first_render_queue 80
			}
		}
	}
}

  (1)、这个合成器有target_output所以这个合成器输出的是我们最终的结果。前面两个pass先清空当前场景然后渲染队列1-9的对象(天空盒等)
  (2)、第三个pass 类型是render_custom 意思就是我们可以执行自己定义的Composition Pass。 分别定义了DeferredLightRenderOperationDeferredLightCompositionPass 对象 。输入GBuffer中的两个纹理。

class DeferredLightCompositionPass : public Ogre::CustomCompositionPass
{
public:

    /** 创建custom RenderSystemOperation*/
    virtual Ogre::CompositorInstance::RenderSystemOperation* createOperation(
        Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass)
    {
        return OGRE_NEW DeferredLightRenderOperation(instance, pass);
    }

protected:
    virtual ~DeferredLightCompositionPass() {}
};
class DeferredLightRenderOperation : public Ogre::CompositorInstance::RenderSystemOperation
{
public:
   //生成灯光的材质文件
    DeferredLightRenderOperation(Ogre::CompositorInstance* instance, const Ogre::CompositionPass* pass);
    
    /** @copydoc CompositorInstance::RenderSystemOperation::execute */
    virtual void execute(Ogre::SceneManager *sm, Ogre::RenderSystem *rs);
    virtual ~DeferredLightRenderOperation();
private:
    /** Create a new deferred light  */
    DLight *createDLight(Ogre::Light* light);
   
    //The texture names of the GBuffer components
    Ogre::String mTexName0;
    Ogre::String mTexName1;
    
    //The material generator for the light geometry
    MaterialGenerator* mLightMaterialGenerator;

    //The map of deferred light geometries already constructed
    typedef std::map<Ogre::Light*, DLight*> LightsMap;
    LightsMap mLights;

    //The ambient light used to render the scene
    AmbientLight* mAmbientLight;

    //The viewport that we are rendering to
    Ogre::Viewport* mViewport;
};

DeferredLightRenderOperation ::execute 方法中先设置AmbientLight的常量farCorner值和渲染环境光,然后遍历每个灯创建DLight对象,更新阴影纹理和调用方法SceneManager::_injectRenderWithPass渲染其光照。
  (3)、渲染透明对象和大于80渲染队列组中的对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值