Ogre3d / Delayed Rendering / Spot Light

I am trying to set up deferred rendering using the ogre compositor framework. I tried to implement a spotlight shader (as a full-screen four-dimensional effect, without fading or mirroring) in the code below:

Material that displays pending data in 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; } 

Description of the vertex program:

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

Description of the fragment program:

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

Lighting material script:

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

Light Shader:

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

This is how I declare the light in my .cpp file:

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

I get the output and everything works fine - except that I cannot get the lighting to work correctly. G Buffer contains real data - normals of the space of vision, linear z-depth, textures. I also get a bright position in the space of vision as a parameter - however, during vector computing, there are some problems and the output has nothing to do with point light. What am I doing wrong here?

Thanks!

PS I also tried to pass the lightPos parameter manually, through the composer listener, but then the light was more like directional light ...

+4
source share
1 answer

The problem was this:

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

It had to be multiplied by the farCorner value, which is the far-off camera truncation angle:

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

You can get it using

mCamera->getWorldSpaceCorners()[1];

and then connect it to the composer listener as follows:

 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]); } 
+1
source

All Articles