[英]Ogre3d / Deferred rendering / Point light
Im trying to set up deferred renderer using ogre compositor framework. 我试图使用ogre compositor框架设置延迟渲染器。 I tried to implement a point-light shader (as a fullscreen quad effect, without attenuation or specular calculations) in the code below:
我尝试在下面的代码中实现一个点光着色器(作为全屏四边形效果,没有衰减或镜面反射计算):
Material that outputs deferred data to GBuffer: 将延迟数据输出到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 program description: 顶点程序说明:
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 description: 片段程序说明:
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
}
}
Light 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 light in my .cpp file: 这就是我在.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);
I get the output and everything works fine - except i cant get lighting to work correctly. 我得到输出,一切正常 - 除了我不能让灯光正常工作。 G Buffer contains valid data - view-space normals, linear z-depth, textures.
G Buffer包含有效数据 - 视图空间法线,线性z深度,纹理。 I also get light position in view space as a parameter - however there are some problems during vector calculations - and the output is nothing like point light should be.
我也将视图空间中的光位置作为参数 - 但是在矢量计算期间存在一些问题 - 并且输出与点光源不同。 What am i doing wrong here?
我在这做错了什么?
Thanks! 谢谢!
PS I also tried to pass lightPos parameter manually, via compositor listener, but then the light looked more like a directional light... PS我也尝试通过合成器监听器手动传递lightPos参数,但随后灯光看起来更像是定向灯......
The problem was in the equation: 问题在于:
float3 ray = float3(projPos.x, projPos.y * flip, 1);
It had to be multiplied by farCorner
value, which is far corner of the camera frustum: 它必须乘以
farCorner
值,这是相机视锥的远角:
float3 ray = float3(projPos.x, projPos.y * flip, 1) * farCorner;
You can get it by using 你可以通过使用获得它
mCamera->getWorldSpaceCorners()[1];
and then plugging it in the compositor listener like this: 然后将它插入到compositor侦听器中,如下所示:
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]);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.