Screen Space Reflection 学习笔记

[来源 by kode80]

原始的做法


经典的对图像的光线追踪的做法是从镜头处发射一条射线,当其与物体相交时,计算这个点的颜色,并作为这条射线最近的像素的颜色值。通常来说光线追踪会需要获取场景中所有几何体、材质、光照的信息,并使用一个完整的Rendering pipeline来达成。我们也能使用类似的方法, 利用延迟渲染中的GBuffers来达成期望的效果。
在Unity中我们可以获得所有所需的信息。我们可以将Camera的depthTextureMode设为DepthTextureMode.DepthNormals,从而使得任何这个镜头调用到的Shader都会获得一个sampler2D _CameraDepthNormalsTexture,这其中包含了当前镜头渲染图片的normal和depth信息;由此我们可以构建出每个像素对应的到三维空间中的位置,再使用reflect(lightDir, normal)可以得到反射方向向量;
在Unity中的后处理效果都是通过渲染一个屏幕的四边形来实现的,我们可以在vert函数中获得对应的UV,将其转化为NDC坐标,再右乘一个inverse projection matrix,就可以获得到远裁剪面的四个顶点(在观察空间下)。将这个方向向量传给frag函数,我们便可以得到一个插值后的结果,这个结果就是对应各个像素的镜头到远裁剪面的射线。将这个射线乘以depth,我们便可以得到像素对应在三维空间中的位置。
// Calculate camera to far plane ray in vertex shader
float4 cameraRay = float4( vertex.uv * 2.0 - 1.0, 1.0, 1.0);
cameraRay = mul( _CameraInverseProjectionMatrix, cameraRay);
output.cameraRay = cameraRay.xyz / cameraRay.w;
// Calculate camera space pixel position in fragment shader
float3 decodedNormal;
float decodedDepth;
DecodeDepthNormal( tex2D( _CameraDepthNormalsTexture, input.uv), decodedDepth, decodedNormal);
float3 pixelPosition = input.cameraRay * decodedDepth;

Camera vs GBuffer Normal

_CameraDepthNormalsTexture是一个32bit的图像,其中depth和normal各占用16bit,使用它会使得两者的精度下降。我们可以使用GBuffer中的_CameraGBufferTexture2来获取世界空间的normal,再通过传入一个转换为观察空间的矩阵(camera.worldToCameraMatrix)将其转到观察空间,从而获得normal,这样我们就能使用32bit来存储一个完整的depth图像,从而提高精度(将Camera的depthTextureMode设为DepthTextureMode.Depth );
// In C# script
material.SetMatrix( "_NormalMatrix", camera.worldToCameraMatrix);
// In fragment shader
float3 worldSpaceNormal = tex2D( _CameraGBufferTexture2, i.uv).rgb * 2.0 - 1.0;
float3 cameraSpaceNormal = m
  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值