华为手机Shader出错水面呈条纹状解决方案(深水坑)

本文介绍了一款水面shader在华为手机上出现的问题及其解决方法。通过调整shader中关于深度的计算,解决了在华为设备上的异常显示,并分享了修改后的shader代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       我们知道华为手机是自研内核,其GPU的算法不清楚是否与正常的骁龙内核相同,我们项目场景里面水面shader在普通手机上显示正常,但是在华为的手机里面,shader却会出错。后来,经过对此shader各种计算的逻辑,最终找到了问题所在,shader深度计算在华为手机有可能出错

================================================================================================

对比:

首先,正常的设备效果(可以看到这是个深水)

然后,这是华为手机的效果

    看效果,一层叠一层,猜测要么是渐变纹理出错,要么是深度计算出错。

-----------------------------------------------------------------------------------------------------------------------------------------------------

下面我们看一下这个shader:

Shader "Water/SeaWave" {
	Properties {
		_WaterTex ("WaterTex", 2D) = "black" {} 
		_BumpTex ("BumpTex", 2D) = "bump" {} 
		_GTex ("Gradient", 2D) = "white" {} //海水渐变
		_WaterSpeed ("WaterSpeed", float) = 0.74  //海水速度
		_NoiseRange ("NoiseRange", float) = 6.43
		_Refract ("Refract", float) = 0.07
		_Specular ("Specular", float) = 1.86
		_Gloss ("Gloss", float) = 0.71
		_SpecColor ("SpecColor", color) = (1, 1, 1, 1)
		_Range ("Range", vector) = (0.13, 1.53, 0.37, 0.78)
	}
	CGINCLUDE 
	fixed4 LightingWaterLight(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) {
		half3 halfVector = normalize(lightDir + viewDir);
		float diffFactor = max(0, dot(lightDir, s.Normal)) * 0.8 + 0.2;
		float nh = max(0, dot(halfVector, s.Normal));
		float spec = pow(nh, s.Specular * 128.0) * s.Gloss;
		fixed4 c;
		c.rgb = (s.Albedo * _LightColor0.rgb * diffFactor + _SpecColor.rgb * spec * _LightColor0.rgb) * (atten);
		c.a = s.Alpha + spec * _SpecColor.a;
		return c;
	}
	ENDCG
	SubShader {
		Tags { "RenderType"="Transparent" "Queue"="Transparent"}
		LOD 200

		GrabPass{}
		zwrite off
		
		CGPROGRAM
		#pragma surface surf WaterLight vertex:vert alpha noshadow
		#pragma target 3.0

		sampler2D _GTex;
		sampler2D _WaterTex;
		sampler2D _BumpTex;
		sampler2D _CameraDepthTexture;
		sampler2D _GrabTexture;
		half4 _GrabTexture_TexelSize;
		float4 _Range;
		half _WaterSpeed;
		fixed _Refract;
		half _Specular;
		fixed _Gloss;
		half _NoiseRange;
		float4 _WaterTex_TexelSize;

		struct Input {
			float2 uv_WaterTex;
			float4 proj;
			float3 viewDir;
		};

		void vert (inout appdata_full v, out Input i) {
			UNITY_INITIALIZE_OUTPUT(Input, i);

			i.proj = ComputeScreenPos(UnityObjectToClipPos(v.vertex));
			COMPUTE_EYEDEPTH(i.proj.z);
		}

		void surf (Input IN, inout SurfaceOutput o) {
			float2 uv = IN.proj.xy/IN.proj.w;
			#if UNITY_UV_STARTS_AT_TOP
			if(_WaterTex_TexelSize.y<0)
			uv.y = 1 - uv.y;
			#endif
			fixed4 water = (tex2D(_WaterTex, IN.uv_WaterTex + float2(_WaterSpeed*_Time.x,0))+tex2D(_WaterTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x) + float2(_WaterSpeed*_Time.x,0)))/2;
			float4 offsetColor = (tex2D(_BumpTex, IN.uv_WaterTex + float2(_WaterSpeed*_Time.x,0))+tex2D(_BumpTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x) + float2(_WaterSpeed*_Time.x,0)))/2;
			half2 offset = UnpackNormal(offsetColor).xy * _Refract;
			half m_depth = LinearEyeDepth(tex2Dproj (_CameraDepthTexture, IN.proj).r);
			half deltaDepth = m_depth - IN.proj.z;
			half4 bott = tex2D(_GrabTexture, uv+offset);
			fixed4 waterColor = tex2D(_GTex, float2(min(_Range.y, deltaDepth)/_Range.y,1));
			half water_A = 1-min(_Range.z, deltaDepth)/_Range.z;
			half water_B = min(_Range.w, deltaDepth)/_Range.w;
			float4 bumpColor = (tex2D(_BumpTex, IN.uv_WaterTex+offset + float2(_WaterSpeed*_Time.x,0))+tex2D(_BumpTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x)+offset + float2(_WaterSpeed*_Time.x,0)))/2;
			o.Normal = UnpackNormal(bumpColor).xyz;
			o.Specular = _Specular;
			o.Gloss = _Gloss;
			o.Albedo = bott.rgb * (1 - water_B) + waterColor.rgb * water_B;
			o.Albedo = o.Albedo * (1 - water.a*water_A) + water.rgb * water.a*water_A;
			o.Alpha = min(_Range.x, deltaDepth)/_Range.x;
		}
		ENDCG
	} 
}

可以看到这是个深度水。

处理办法:删掉不同的计算,然后打包看效果(虽然蠢但是找不到更好的办法)

后来去掉了根据深度进行透明值处理:

Shader "Water/SeaWave" {
	Properties {
		_WaterTex ("WaterTex", 2D) = "black" {} 
		_BumpTex ("BumpTex", 2D) = "bump" {} 
		_GTex ("Gradient", 2D) = "white" {} //海水渐变
		_WaterSpeed ("WaterSpeed", float) = 0.74  //海水速度
		_Refract ("Refract", float) = 0.07
		_Specular ("Specular", float) = 1.86
		_Gloss ("Gloss", float) = 0.71
		_SpecColor ("SpecColor", color) = (1, 1, 1, 1)
		_Range ("Range", vector) = (0.13, 1.53, 0.37, 0.78)
	}
	CGINCLUDE 
	fixed4 LightingWaterLight(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) {
		half3 halfVector = normalize(lightDir + viewDir);
		float diffFactor = max(0, dot(lightDir, s.Normal)) * 0.8 + 0.2;
		float nh = max(0, dot(halfVector, s.Normal));
		float spec = pow(nh, s.Specular * 128.0) * s.Gloss;
		fixed4 c;
		c.rgb = (s.Albedo * _LightColor0.rgb * diffFactor + _SpecColor.rgb * spec * _LightColor0.rgb) * (atten);
		c.a = s.Alpha + spec * _SpecColor.a;
		return c;
	}
	ENDCG
	SubShader {
		Tags { "RenderType"="Transparent" "Queue"="Transparent"}
		LOD 200

		GrabPass{}
		zwrite off
		
		CGPROGRAM
		#pragma surface surf WaterLight vertex:vert alpha noshadow
		#pragma target 3.0

		sampler2D _GTex;
		sampler2D _WaterTex;
		sampler2D _BumpTex;
		sampler2D _GrabTexture;
		half4 _GrabTexture_TexelSize;
		float4 _Range;
		half _WaterSpeed;
		fixed _Refract;
		half _Specular;
		fixed _Gloss;

		float4 _WaterTex_TexelSize;

		struct Input {
			float2 uv_WaterTex;
			float4 proj;
			float3 viewDir;
		};

		void vert (inout appdata_full v, out Input i) {
			UNITY_INITIALIZE_OUTPUT(Input, i);
			i.proj = ComputeScreenPos(UnityObjectToClipPos(v.vertex));
		}

		void surf (Input IN, inout SurfaceOutput o) {
			float2 uv = IN.proj.xy/IN.proj.w;
			fixed4 water = (tex2D(_WaterTex, IN.uv_WaterTex + float2(_WaterSpeed*_Time.x,0))+tex2D(_WaterTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x) + float2(_WaterSpeed*_Time.x,0)))/2;
			float4 offsetColor = (tex2D(_BumpTex, IN.uv_WaterTex + float2(_WaterSpeed*_Time.x,0))+tex2D(_BumpTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x) + float2(_WaterSpeed*_Time.x,0)))/2;
			half2 offset = UnpackNormal(offsetColor).xy * _Refract;
			half4 bott = tex2D(_GrabTexture, uv+offset);
			fixed4 waterColor = tex2D(_GTex, float2(_Range.y,1));
			float4 bumpColor = (tex2D(_BumpTex, IN.uv_WaterTex+offset + float2(_WaterSpeed*_Time.x,0))+tex2D(_BumpTex, float2(1-IN.uv_WaterTex.y,IN.uv_WaterTex.x)+offset + float2(_WaterSpeed*_Time.x,0)))/2;
			o.Normal = UnpackNormal(bumpColor).xyz;
			o.Specular = _Specular;
			o.Gloss = _Gloss;
			o.Albedo = bott.rgb + waterColor.rgb;
			o.Albedo = o.Albedo * (1 - water.a) + water.rgb * water.a;
			o.Alpha = _Range.x;
		}
		ENDCG
	} 
	//FallBack "Diffuse"
}

打包,效果图如下:

没错了!(当然效果也差了许多,但是节约性能了,效果差就甩给美术吧)

得出结论,深度测试在华为设备上可能出错。

而且强烈建议在设备上不要使用深度的计算,性能节省一点是一点。

要是非要使用深度水,这里有个链接模拟深水  https://blog.youkuaiyun.com/baicaishisan/article/details/79061739

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值