我正在研究自己的deffered渲染引擎。我将场景渲染到包含漫反射颜色,视图空间法线和深度(现在)的g缓冲区。我为第二个渲染阶段实现了定向光,效果很好。现在我想渲染一个点光源,这有点难。
我需要在视图空间中着色器的点光位置,因为我只有g-buffer中的深度,我无法在每个像素中进行矩阵乘法。我采用了光位置并用同一个矩阵对其进行了变换,通过该矩阵我在着色器中变换每个顶点,因此它应该与场景中的谓词对齐(使用D3DXVec3Transform)。但情况并非如此:转换后的位置几乎根本不代表观看空间位置。它的x,y坐标不在图表中,它们通常超出(-1,1)范围。变换后的位置稍微偏向于摄像机方向,但是光线移动太快而y轴反转。仅当相机处于(0,0,0)时,灯光才会位于屏幕中央的(0,0)处。这是我每帧执行的相关渲染代码:
D3DXMATRIX matView; // the view transform matrix
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (x,y,z), // the camera position
&D3DXVECTOR3 (xt,yt,zt), // the look-at position
&D3DXVECTOR3 (0.0f, 0.0f, 1.0f)); // the up direction
D3DXMatrixPerspectiveFovLH(&matProjection,
fov, // the horizontal field of view
asp, // aspect ratio
znear, // the near view-plane
zfar); // the far view-plane
D3DXMATRIX vysl=matView*matProjection;
eff->SetMatrix("worldViewProj",&vysl); //vertices are transformed ok ín shader
//render g-buffer
D3DXVECTOR4 lpos; D3DXVECTOR3 lpos2(0,0,0);
D3DXVec3Transform(&lpos,&lpos2,&vysl); //transforming lpos into lpos2 using vysl, still the same matrix
eff->SetVector("poslight",&lpos); //but there is already a mess in lpos at this time
//render the fullscreen quad with wrong lighting
不是那个相关的着色器代码,但是,我仍然以这种方式看到光线位置(传递IN.texture只是我在偷懒):
float dist=length(float2(IN.texture0*2-1)-float2(poslight.xy));
OUT.col=tex2D(Sdiff,IN.texture0)/dist;
我试图仅在没有投影的情况下通过matView转换灯光,但问题仍然是相同的。如果我在着色器中变换光线,则结果相同,因此问题在于矩阵本身。但它与转换顶点的矩阵相同!顶点处理的方式有多么不同?
你能看一下代码并告诉我错误在哪里吗?在我看来它应该工作正常,但事实并非如此。提前谢谢。
答案 0 :(得分:0)
此变换的结果D3DXVec3Transform(&lpos,&lpos2,&vysl);
是均匀空间中的向量(即投影向量,但未除以w
)。但是在你的着色器中,你使用它的xy
组件而不尊重它(w
)。这(很可能)是问题所在。您可以自己将w
分割为矢量,也可以使用D3DXVec3Project
代替D3DXVec3Transform
。
顶点着色器中的mul
矩阵将它们viewproj
用于顶点并将顶点着色器中的xyz
矩阵传递给插值器,其中硬件最终将其分割为&#39 ; s {{1}}通过插值' w'。
答案 1 :(得分:0)
你不需要矩阵乘法来重建视图位置,这里是一个代码片段(来自andrew lauritzen deffered light示例)
tP是投影变换,位置屏幕是-1/1像素坐标,viewspaceZ是从纹理中采样的线性深度。
float3 ViewPosFromDepth(float2 positionScreen,
float viewSpaceZ)
{
float2 screenSpaceRay = float2(positionScreen.x / tP._11,
positionScreen.y / tP._22);
float3 positionView;
positionView.z = viewSpaceZ;
positionView.xy = screenSpaceRay.xy * positionView.z;
return positionView;
}