Different sampler types for same sample texture unit in fragment shader.

这个问题是几个月前碰到的,现象是这样的,N卡和Intel核显上都正常的shader,跑到A卡上就出错了,使用了这个shader的物体不显示,并且提示Validation failed! - Different sampler types for same sample texture unit in fragment shader.在网络上搜索了一下,很多人说是纹理绑定出错了,一张纹理被绑定了多次,经过仔细的排查,我这里可以确定没有出现绑定错误。所以被这个问题卡了很久,好在影响不是很大。

今天又碰到了这个问题,多次测试发现是使用了sampler2DShadow对象之后才出现这个问题的,如果代码里同时使用了sampler2DShadow和sampler2D对象,且都没有绑定纹理的话,就会报这个错误,就算这些纹理的采样语句被跳过不执行,也是一样的报错。

猜测可能sampler2D跟sampler2DShadow对象的默认值是一样的,比如都是0,然后shader编译阶段并没有进行检查,运行时发现不同的采样器要对同一个纹理采样,于是导致了运行错误。

在CPU里面对所有sampler2DShadow对象显式的绑定一个值,有纹理的绑定对应的纹理层,没有纹理的就绑定一个不存在的纹理层,我用的是15. 问题解决,错误不再出现。

我这个shader是一个很大的shader,里面有不同的功能模块,根据需求决定是否启用,所以有些shader代码运行时会被IF跳过,被跳过的模块用到的纹理也就不会进行绑定,我觉得这种做法是很合理的,确定不会使用的纹理为什么还要去绑定一次啊?N卡和Intel核显上能正常运行,就A卡不行,所以这个问题要算是A卡驱动的Bug了。

以下是Unity Shader中使用CG语言实现SAMPLE_DEPTH_TEXTURE的示例代码。 在vertex shader中,我们需要将顶点坐标和投影矩阵相乘得到裁剪坐标,然后将裁剪坐标传递给fragment shader。 ``` v2f vert (appdata_base v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } ``` 在fragment shader中,我们首先需要从深度纹理中采样得到深度值,然后将其转换为线性深度值。转换方法可以根据具体场景进行调整。接着,我们可以根据深度值计算出该像素的位置,并将该位置作为颜色输出。 ``` half4 frag (v2f i) : SV_Target { float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UNITY_PROJ_COORD(i.vertex)).r); float linearDepth = 2.0 * _ZBufferParams.w / (_ZBufferParams.y + _ZBufferParams.x - depth * (_ZBufferParams.y - _ZBufferParams.x)); float4 clipPos = float4(ComputeGrabScreenPos(i.vertex.xy, linearDepth), linearDepth, 1.0); float4 viewPos = mul(_InvProjMatrix, clipPos); viewPos /= viewPos.w; return float4(viewPos.xyz, 1.0); } ``` 注意,这里我们还需要使用Unity提供的函数Linear01Depth将深度值从非线性转换为线性。同时,我们需要使用_ZBufferParams和_InvProjMatrix这两个Unity内置的变量来进行后续计算。 最后,在主程序中,我们需要将深度纹理绑定到对应的纹理单元,并将投影矩阵和_ZBufferParams传递给shader。 ``` Shader "Custom/DepthShader" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _CameraDepthTexture; float4 _ZBufferParams; float4x4 _InvProjMatrix; struct appdata_base { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert (appdata_base v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } half4 frag (v2f i) : SV_Target { float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UNITY_PROJ_COORD(i.vertex)).r); float linearDepth = 2.0 * _ZBufferParams.w / (_ZBufferParams.y + _ZBufferParams.x - depth * (_ZBufferParams.y - _ZBufferParams.x)); float4 clipPos = float4(ComputeGrabScreenPos(i.vertex.xy, linearDepth), linearDepth, 1.0); float4 viewPos = mul(_InvProjMatrix, clipPos); viewPos /= viewPos.w; return float4(viewPos.xyz, 1.0); } ENDCG } } FallBack "Diffuse" } ``` 注意,我们需要使用Unity内置的宏UNITY_PROJ_COORD来将裁剪坐标转换为纹理坐标。另外,由于_CameraDepthTexture是Unity自动渲染深度纹理的结果,因此无需手动绑定纹理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值