2012-12-25 3 views
4

Je tente de configurer le rendu différé en utilisant le framework ogre compositor. J'ai essayé de mettre en œuvre un shader point de lumière (comme un effet de quad en plein écran, sans atténuation ou calculs spéculaires) dans le code ci-dessous:Ogre3d/Rendu différé/Point lumineux

Matériel qui fournit en sortie différée des données à GBuffer:

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 Description du programme:

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 Description du programme:

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

script matériau léger:

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

shaders lumière:

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

Voici comment je déclare la lumière dans mon fichier .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); 

je reçois la sortie et tout fonctionne très bien - sauf que je ne peux pas obtenir l'éclairage pour fonctionner correctement. G Buffer contient des données valides - normales de l'espace de vue, profondeur z linéaire, textures. J'ai aussi la position de la lumière dans l'espace de vue en tant que paramètre - cependant, il y a quelques problèmes lors des calculs vectoriels - et la sortie n'a rien à voir avec la lumière ponctuelle. Qu'est-ce que je fais mal ici?

Merci!

P.S. J'ai aussi essayé de passer manuellement le paramètre lightPos, par l'intermédiaire d'écoute typographe, mais la lumière ressemblait plus à une lumière directionnelle ...

Répondre

1

Le problème était dans l'équation:

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

Il devait être multiplié par farCorner valeur, ce qui est un coin de la caméra frustum:

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

Vous pouvez l'obtenir en utilisant

mCamera->getWorldSpaceCorners()[1];

puis le brancher à l'auditeur de typographe comme ceci:

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]); 
} 
Questions connexes