草庐IT

c++ - Ogre3d/延迟渲染/点光源

coder 2024-02-25 原文

我正在尝试使用 ogre 合成器框架设置延迟渲染器。我尝试在下面的代码中实现一个点光源着色器(作为全屏四边形效果,没有衰减或镜面反射计算):

将延迟数据输出到GBuffer的 Material :

void ToGBufferVP
                (
                    float4 iPosition : POSITION,
                    float3 iNormal : NORMAL,
                    float2 iUV0 : TEXCOORD,

                    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;
}

void ToGBufferFP
                (
                    float3 iViewPos : TEXCOORD0,
                    float3 iNormal : TEXCOORD1,
                    float2 iUV0 : TEXCOORD2,

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

                    uniform sampler2D sTex : register(s0),
                    uniform sampler2D sSpec : register(s1),

                    uniform float cFarDistance
                )
{
    oColor0.rgb = tex2D(sTex, iUV0);
    oColor0.a = tex2D(sSpec, iUV0);
    oColor1.rgb = normalize(iNormal);
    oColor1.a = length(iViewPos) / cFarDistance;
}

顶点程序说明:

vertex_program ScreenQuadDebugLight_VS cg
{
    source MyDeferredPostShader.hlsl
    profiles vs_1_1 arbvp1
    entry_point ScreenQuadDebugLight_VS

    default_params
    {
        param_named_auto worldViewProj worldviewproj_matrix
    }
}

片段程序说明:

fragment_program ScreenQuadDebugLight_PS cg
{
    source MyDeferredPostShader.hlsl
    profiles ps_2_0 arbfp1
    entry_point ScreenQuadDebugLight_PS

    default_params
    {
        param_named_auto vpWidth viewport_width
        param_named_auto vpHeight viewport_height       

        param_named_auto flip render_target_flipping
        param_named_auto farClipDistance far_clip_distance

        param_named_auto lightPos light_position_view_space 0
    }
}

灯光 Material 脚本:

material DeferredShadingPostQuadLight
{
    technique
    {
        pass
        {
            cull_hardware none
            cull_software none

            depth_func always_pass

            vertex_program_ref ScreenQuadDebugLight_VS
            {
            }

            fragment_program_ref ScreenQuadDebugLight_PS
            {
            }

            texture_unit
            {
                tex_coord_set 0
                tex_address_mode clamp
                filtering none
            }

            texture_unit
            {
                tex_coord_set 1
                tex_address_mode clamp
                filtering none
            }
        }
    }
}

光着色器:

void ScreenQuadDebugLight_VS
    (
        float4 Pos: POSITION,   
        out float4 oPos: POSITION,
        out float4 oTexCoord : TEXCOORD0,   
        uniform float4x4 worldViewProj
    )
{
    float4 projPos = mul(worldViewProj, Pos);
    oTexCoord = projPos;    
    oPos = projPos;
}

float4 ScreenQuadDebugLight_PS
    (
        float4 projPos : TEXCOORD0,
        uniform sampler Tex0: register(s0),
        uniform sampler Tex1: register(s1),

        uniform float vpWidth,
        uniform float vpHeight,

        uniform float flip,
        uniform float farClipDistance,

        uniform float3 lightPos
    ) : COLOR 
{
    // Get homogenous coordinates
    projPos.xy /= projPos.w;

    // Compensate texture coordinate half pixel jitter
    float2 texCoord = 0.5f * (float2(projPos.x, -projPos.y) + 1);
    float2 halfPixel = float2(0.5/vpWidth, 0.5/vpHeight);
    texCoord += halfPixel;

    float3 ray = float3(projPos.x, projPos.y * flip, 1);

    float4 a0 = tex2D(Tex0, texCoord); // Albedo and Specularity
    float4 a1 = tex2D(Tex1, texCoord); // Normal and Depth

    // Attributes
    float3 colour = a0.rgb;
    float specularity = a0.a;
    float distance = a1.w;
    float3 normal = a1.xyz;

    float3 viewPos = normalize(ray);
    viewPos.z = distance;

    float3 objToLightVec =  lightPos - viewPos;
    float len_sq = dot(objToLightVec, objToLightVec);
    float len = sqrt(len_sq);
    float3 objToLightDir = normalize(objToLightVec);

    float3 total_light_contrib;
    total_light_contrib = max(0.0, dot(objToLightDir, normal));

    return float4(total_light_contrib, 0.0);
}

这就是我在 .cpp 文件中声明光的方式:

lLightSceneNodeHolder = mSceneMgr->getRootSceneNode()->createChildSceneNode();

Ogre::Light *light;
light = mSceneMgr->createLight();
light->setType(Ogre::Light::LT_POINT);
light->setPosition(Ogre::Vector3(0, 0, -0.7f));
light->setVisible(true);
light->setDiffuseColour(Ogre::ColourValue::White);
light->setSpecularColour(Ogre::ColourValue::White);
lLightSceneNodeHolder->attachObject(light);

我得到了输出并且一切正常 - 除了我无法让照明正常工作。 G 缓冲区包含有效数据 - View 空间法线、线性 z 深度、纹理。我还将 View 空间中的光位置作为参数 - 但是在 vector 计算过程中存在一些问题 - 并且输出与点光源完全不同。我在这里做错了什么?

谢谢!

附言我还尝试通过合成器监听器手动传递 lightPos 参数,但随后灯光看起来更像是定向光...

最佳答案

问题出在等式中:

float3 ray = float3(projPos.x, projPos.y * flip, 1);

它必须乘以 farCorner 值,这是相机平截头体的远角:

float3 ray = float3(projPos.x, projPos.y * flip, 1) * farCorner;

你可以通过使用得到它

mCamera->getWorldSpaceCorners()[1];

然后像这样将它插入到合成器监听器中:

void LightListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
    vpParams = mat->getBestTechnique()->getPass(0)->getVertexProgramParameters();
    fpParams = mat->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
}

void LightListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
    vpParams->setNamedConstant("lightPos", lightPos);
    fpParams->setNamedConstant("farCorner", mCamera->getWorldSpaceCorners()[1]);
}

关于c++ - Ogre3d/延迟渲染/点光源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14032696/

有关c++ - Ogre3d/延迟渲染/点光源的更多相关文章

  1. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  7. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  8. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

随机推荐