UNITY SHADER学习笔记2(unity 5.6)

来源:互联网 发布:第一网红 知乎 编辑:程序博客网 时间:2024/06/16 01:56

方法

UNITY_PROJ_COORD

老实说,不太理解PSP2,哈哈

#if defined(SHADER_API_PSP2)#define UNITY_BUGGY_TEX2DPROJ4#define UNITY_PROJ_COORD(a) (a).xyw#else#define UNITY_PROJ_COORD(a) a#endif

SAMPLE_DEPTH_TEXTURE_PROJ

由这些顺带回顾一下深度和法线纹理的东西
1.深度图里面存储的是NDC坐标,因为NDC坐标的范围是-1到1,到存为0到1,大家都懂的,会用映射的方法,法线图里面是观察空间下的法线信息(同时生成深度和法线,法线在RG 深度在BA)
2.得到的深度图是非线性的,原来是来自投影矩阵的变换
3.如何得到正确的深度:
延迟渲染路径(包含遗留的延迟路径),本身就会产出深度图(延迟渲染会把这些信息放在G-buffer中),其他的路径,会通过一个单独的Pass渲染得到
获得的方法是使用着色器替换技术选择那些SubShader的RenderType标签为Opaque并且队列小于等于2500的,渲染到深度或者法线贴图中
4.让摄像机生成一张深度或者一张深度和法线纹理,前一个,unity会用3中的方法找到物体,在前向中,并用他的投射阴影的pass(LightMode = ShadowCaster)来得到,如果没有,也获取不到深度,后一个除了深度如果在延迟渲染中,可以很容易得到法线信息,但在前向中,会用一个pass把整个场景再渲染一次
5.shader中用_CameraDepthTexture访问深度纹理,用_CameraDepathNormalsTexture访问深度法线纹理
6.大部分,其实用tex2D也是可以采样,但是在如PS3和PSP2上会有错(又是这两个),所以基本上要养成用这些方法的习惯,这里还是提醒一下,UNITY提供了特定方法来采样的,都要养成用这些方法的习惯,会减少很多问题
7.SAMPLE_DEPTH_TEXTURE SAMPLE_DEPTH_TEXTURE_PROJ SAMPLE_DEPTH_TEXTURE_LOD
这三个方法都接受两个参数,前一个就不说了,后一个是一个float3或者float4,方法里面会用前两个除以最后一个分量,所以直接用顶点里面的ComputeScreenPos方法的结果就可以了,不需要先齐次除法

// Depth texture sampling helpers.// On most platforms you can just sample them, but some (e.g. PSP2) need special handling.//// SAMPLE_DEPTH_TEXTURE(sampler,uv): returns scalar depth// SAMPLE_DEPTH_TEXTURE_PROJ(sampler,uv): projected sample// SAMPLE_DEPTH_TEXTURE_LOD(sampler,uv): sample with LOD level#if defined(SHADER_API_PSP2) && !defined(SHADER_API_PSM)#   define SAMPLE_DEPTH_TEXTURE(sampler, uv) (tex2D<float>(sampler, uv))#   define SAMPLE_DEPTH_TEXTURE_PROJ(sampler, uv) (tex2DprojShadow(sampler, uv))#   define SAMPLE_DEPTH_TEXTURE_LOD(sampler, uv) (tex2Dlod<float>(sampler, uv))#   define SAMPLE_RAW_DEPTH_TEXTURE(sampler, uv) SAMPLE_DEPTH_TEXTURE(sampler, uv)#   define SAMPLE_RAW_DEPTH_TEXTURE_PROJ(sampler, uv) SAMPLE_DEPTH_TEXTURE_PROJ(sampler, uv)#   define SAMPLE_RAW_DEPTH_TEXTURE_LOD(sampler, uv) SAMPLE_DEPTH_TEXTURE_LOD(sampler, uv)#else    // Sample depth, just the red component.#   define SAMPLE_DEPTH_TEXTURE(sampler, uv) (tex2D(sampler, uv).r)#   define SAMPLE_DEPTH_TEXTURE_PROJ(sampler, uv) (tex2Dproj(sampler, uv).r)#   define SAMPLE_DEPTH_TEXTURE_LOD(sampler, uv) (tex2Dlod(sampler, uv).r)    // Sample depth, all components.#   define SAMPLE_RAW_DEPTH_TEXTURE(sampler, uv) (tex2D(sampler, uv))#   define SAMPLE_RAW_DEPTH_TEXTURE_PROJ(sampler, uv) (tex2Dproj(sampler, uv))#   define SAMPLE_RAW_DEPTH_TEXTURE_LOD(sampler, uv) (tex2Dlod(sampler, uv))#endif// Deprecated; use SAMPLE_DEPTH_TEXTURE & SAMPLE_DEPTH_TEXTURE_PROJ instead#if defined(SHADER_API_PSP2)#   define UNITY_SAMPLE_DEPTH(value) (value).r#else#   define UNITY_SAMPLE_DEPTH(value) (value).r#endif

阴影

阴影计算在不同的版本方法不同,根据AutoLight.cginc中的注释,在4.x的版本中,采用的是在顶点计算阴影坐标,然后传给片元着色器,在5.6+的版本中,阴影的坐标计算放在了片元着色器中,准确的说是用一个接口,传入lightmapUV, 世界坐标,屏幕坐标(unity shader里面提到的屏幕坐标,基本都是ComputeScreenPos计算的结果),然后会得到阴影衰减系数

不过最常用的还是4.x中开始的方法,主要使用三个宏

SHADOW_COORDS SHADOW_ATTENUATION TRANSFER_SHADOW

#define SHADOW_COORDS(idx1) unityShadowCoord4 _ShadowCoord : TEXCOORD##idx1;

这个方法主要是定义一个阴影坐标,unityShadowCoord4 定义为float4,唯一有差别的是在点光源中,