- 环境
- 目的
- 问题
-
- DX 没有问题
- OpenGLES 就全黑色
- 分析
-
- DX 的
- OpenGLES 的
- 问题所在
- 注意
- 修复
- 优化
Unity : 2018.2.11f11 Pipeline : Built-In
目的今天合作部门的某位程序同学可能对 shader 不熟悉 他是在省外的(异地) 但是公司没有了解 shader 的同学(-_- ~~!!) 所以有比较多的一些效果问题、兼容性问题,都只能找到我~ (-_- ~~!!)
问题 DX 没有问题
很有可能就是平台设置问题
然后我使用 frame debug 查看绘制区别
DX 的
看着和 DX 的差别非常大,而且很多参数、状态值都没对上,如下:Queue的设置都无效了
主要的是我们 shader 的"Queue"="Transparent",按正常情况下,会再Render.TransparentGeometry列队中,但是 Frame Debug 面板中可以看到他是在Render.OpaqueGeometry队列里绘制的
所以非常有可能就是平台不兼容,直接跳过了 正常的变量、参数应用
// Shader created with Shader Forge v1.38 // Shader Forge (c) Neat Corporation / Joachim Holmer - http://www.acegikmo.com/shaderforge/ // Note: Manually altering this data may prevent you from opening it in Shader Forge /*SF_DATA;ver:1.38;sub:START;pass:START;ps:flbk:,iptp:0,cusa:False,bamd:0,cgin:,lico:0,lgpr:1,limd:0,spmd:1,trmd:0,grmd:0,uamb:True,mssp:True,bkdf:False,hqlp:False,rprd:False,enco:False,rmgx:True,imps:True,rpth:0,vtps:0,hqsc:True,nrmq:1,nrsp:0,vomd:0,spxs:False,tesm:0,olmd:1,culm:2,bsrc:0,bdst:1,dpts:2,wrdp:True,dith:0,atcv:False,rfrpo:True,rfrpn:Refraction,coma:15,ufog:False,aust:False,igpj:True,qofs:0,qpre:3,rntp:2,fgom:False,fgoc:False,fgod:False,fgor:False,fgmd:0,fgcr:0.5,fgcg:0.5,fgcb:0.5,fgca:1,fgde:0.01,fgrn:0,fgrf:300,stcl:False,atwp:False,stva:128,stmr:255,stmw:255,stcp:6,stps:0,stfa:0,stfz:0,ofsf:0,ofsu:0,f2p0:False,fnsp:False,fnfb:False,fsmp:False;n:type:ShaderForge.SFN_Final,id:4013,x:33414,y:32662,varname:node_4013,prsc:2|emission-2850-OUT,alpha-8675-OUT,clip-8675-OUT;n:type:ShaderForge.SFN_Tex2d,id:8569,x:32586,y:32713,ptovrint:False,ptlb:mask,ptin:_mask,varname:node_8569,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,tex:e3ecf11490c25124ab2cd8b4631fc9c3,ntxv:0,isnm:False;n:type:ShaderForge.SFN_VertexColor,id:4253,x:32311,y:32623,varname:node_4253,prsc:2;n:type:ShaderForge.SFN_Multiply,id:6979,x:32893,y:32668,varname:node_6979,prsc:2|A-4253-RGB,B-8569-RGB;n:type:ShaderForge.SFN_Multiply,id:8675,x:32893,y:32790,varname:node_8675,prsc:2|A-8569-A,B-9765-OUT;n:type:ShaderForge.SFN_OneMinus,id:3587,x:32325,y:32777,varname:node_3587,prsc:2|IN-4253-A;n:type:ShaderForge.SFN_Tex2d,id:9067,x:31855,y:32896,ptovrint:False,ptlb:wenli,ptin:_wenli,varname:node_9067,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,tex:28c7aad1372ff114b90d330f8a2dd938,ntxv:0,isnm:False|UVIN-8700-UVOUT;n:type:ShaderForge.SFN_TexCoord,id:8700,x:31483,y:32896,varname:node_8700,prsc:2,uv:0,uaff:False;n:type:ShaderForge.SFN_Panner,id:626,x:31669,y:32896,varname:node_626,prsc:2,spu:0,spv:0|UVIN-8700-UVOUT;n:type:ShaderForge.SFN_If,id:9765,x:32586,y:32875,varname:node_9765,prsc:2|A-2909-OUT,B-3587-OUT,GT-1324-OUT,EQ-9084-OUT,LT-9084-OUT;n:type:ShaderForge.SFN_Vector1,id:1324,x:32325,y:33024,varname:node_1324,prsc:2,v1:1;n:type:ShaderForge.SFN_Vector1,id:9084,x:32325,y:33093,varname:node_9084,prsc:2,v1:0;n:type:ShaderForge.SFN_Add,id:9052,x:32048,y:32896,varname:node_9052,prsc:2|A-3427-OUT,B-9067-R;n:type:ShaderForge.SFN_OneMinus,id:3427,x:32048,y:32760,varname:node_3427,prsc:2|IN-4253-A;n:type:ShaderForge.SFN_OneMinus,id:2909,x:32325,y:32902,varname:node_2909,prsc:2|IN-9052-OUT;n:type:ShaderForge.SFN_Multiply,id:385,x:32893,y:32920,varname:node_385,prsc:2|A-9765-OUT,B-3931-OUT;n:type:ShaderForge.SFN_Vector1,id:3931,x:32586,y:33011,varname:node_3931,prsc:2,v1:0.1;n:type:ShaderForge.SFN_ValueProperty,id:7697,x:32881,y:33105,ptovrint:False,ptlb:glow,ptin:_glow,varname:node_7697,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,v1:5;n:type:ShaderForge.SFN_Multiply,id:2850,x:33202,y:32952,varname:node_2850,prsc:2|A-6979-OUT,B-7697-OUT,C-385-OUT;proporder:8569-9067-7697;pass:END;sub:END;*/ Shader "LJShader_Dev/Effect/Dissove blend" { Properties { _mask ("mask", 2D) = "white" {} _wenli ("wenli", 2D) = "white" {} _glow ("glow", Float ) = 5 [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 } SubShader { Tags { "IgnoreProjector"="True" "Queue"="Transparent" "RenderType"="Transparent" } Pass { Name "FORWARD" Tags { "LightMode"="ForwardBase" } Cull Off
CGPROGRAM #pragma vertex vert #pragma fragment frag //#define UNITY_PASS_FORWARDBASE #include "UnityCG.cginc" #pragma multi_compile_fwdbase #pragma only_renderers d3d9 d3d11 glcore #pragma target 3.0 uniform sampler2D _mask; uniform float4 _mask_ST; uniform sampler2D _wenli; uniform float4 _wenli_ST; uniform float _glow; struct VertexInput { float4 vertex : POSITION; float2 texcoord0 : TEXCOORD0; float4 vertexColor : COLOR; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; float4 vertexColor : COLOR; }; VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; o.uv0 = v.texcoord0; o.vertexColor = v.vertexColor; o.pos = UnityObjectToClipPos( v.vertex ); return o; } float4 frag(VertexOutput i, float facing : VFACE) : COLOR { float4 _mask_var = tex2D(_mask,TRANSFORM_TEX(i.uv0, _mask)); float4 _wenli_var = tex2D(_wenli,TRANSFORM_TEX(i.uv0, _wenli)); float node_9765_if_leA = step((1.0 - ((1.0 - i.vertexColor.a)+_wenli_var.r)),(1.0 - i.vertexColor.a)); float node_9765_if_leB = step((1.0 - i.vertexColor.a),(1.0 - ((1.0 - i.vertexColor.a)+_wenli_var.r))); float node_9084 = 0.0; float node_9765 = lerp((node_9765_if_leA*node_9084)+(node_9765_if_leB*1.0),node_9084,node_9765_if_leA*node_9765_if_leB); float node_8675 = (_mask_var.a*node_9765); clip(node_8675 - 0.5); // Lighting: // Emissive: float3 emissive = ((i.vertexColor.rgb*_mask_var.rgb)*_glow*(node_9765*0.1)); float3 finalColor = emissive; return fixed4(finalColor,node_8675); } ENDCG } } FallBack "Diffuse" CustomEditor "ShaderForgeMaterialInspector" }
留意其中的
#pragma only_renderers d3d9 d3d11 glcore
这是仅仅只对 dx9, dx11, opengl core版本的 渲染器才有效的 而我们要是设置在 OpenGLES2 下,那么效果肯定是有问题的
而这句话一般我们如果知道我们的程序运行平台只有那么几个平台,那么可以用这个指令指定平台 然后可以使用这些平台的一些高级特性
从上面的 shader 可以看出来,这 shader 是 shader forge 连连看生成的 除了 可读性、和性能问题不说,还有上面的only_renderers也是自动添加的
这在 shader forge 论坛上已经有人吐槽过:Can’t permanently turn off #pragma only_renderers
从上图可以了解到,如果将only_renderers删除了,这时再用 shader forge 打开此 shader,又会添加only_renderers的指令回去
关于 only_renderers 和 exclude_renderers 可以参考:Writing vertex and fragment shaders 或是可以参考我之前翻译的:Unity Shader - Writing vertex and fragment shader 编写顶点和片段着色器
#pragma only_renderers d3d9 d3d11 glcore // 这里仅仅只对 dx9,dx11, glcore 有效,那么其他的渲染系统将会 输出全是黑色的像素,如果这么用,手机上就没法兼容了
你可以使用 #pragma exclude_renderers gles // 这里可以测试 排除掉 gl es 的,同样可以参考我上面的链接了解 exclude_renderers 原来的 shaderlab 还设置了 #pragma target 3.0 // 使用不了高级特性,可以不设置 target,默认是 target 2.5
target 设置可以参考我之前翻译的:Unity Shader - Shader Compilation Target Levels 着色器编译目标级别
注意除了渲染异常,我们还使用了 asset studio 工具反编译了 shader ab 包资源,发现对应的 shader 中的 subprogram 都是没有生成
因此我们在开发跨平台的 shader 尽量不使用 only_renderers 指令
修复所以我们只需要将#pragma only_renderers d3d9 d3d11 glcore这句代码注释即可
修复归修复,但是啊,shader forge 生产的代码可读性太低了那么下面顺便优化
优化优化前:可以发现可读性超级差,而且 uniform 的变量命名也是渣渣,应该是美术同学使用 shader forge 的连连看产物 优化后:
经过重命名变量名 了解用意 发现一段没用的写法 原因就是 上面很有可能是对 图形学基础没了解过的 美术同学编辑的 shader forge 连连看 或是对节点了解程度不够深,才会有一堆没有用的操作
Shader "xxx" { Properties{ _MaskTex1("Mask1", 2D) = "white" {} _MaskTex2("Mask2", 2D) = "white" {} _Brightness("Brightness", Float) = 5 [HideInInspector]_Cutoff("Alpha cutoff", Range(0,1)) = 0.5 } SubShader{ Tags { "IgnoreProjector" = "True" "Queue" = "Transparent" "RenderType" = "Transparent" } Pass { Name "FORWARD" Tags { "LightMode" = "ForwardBase" } Cull Off
CGPROGRAM #pragma vertex vert #pragma fragment frag //#define UNITY_PASS_FORWARDBASE #include "UnityCG.cginc" #pragma multi_compile_fwdbase // only_renderers 和 exclude_renderers 可以参考:https://docs.unity3d.com/2019.3/Documentation/Manual/SL-ShaderPrograms.html // 或是可以参考我之前翻译的:https://blog.csdn.net/linjf520/article/details/94378653 //#pragma only_renderers d3d9 d3d11 glcore // 这里仅仅只对 dx9,dx11, glcore 有效,那么其他的渲染系统将会 输出全是黑色的像素,如果这么用,手机上就没法兼容了 //#pragma exclude_renderers gles // 这里可以测试 排除掉 gl es 的 // target 可以参考:https://docs.unity3d.com/2019.3/Documentation/Manual/SL-ShaderCompileTargets.html //#pragma target 3.0 // 使用不了高级特性,可以不设置 target uniform sampler2D _MaskTex1; uniform float4 _MaskTex1_ST; uniform sampler2D _MaskTex2; uniform float4 _MaskTex2_ST; uniform float _Brightness; struct VertexInput { float4 vertex : POSITION; float2 texcoord0 : TEXCOORD0; float4 vertexColor : COLOR; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; float4 vertexColor : COLOR; }; VertexOutput vert(VertexInput v) { VertexOutput o = (VertexOutput)0; o.uv0 = v.texcoord0; o.vertexColor = v.vertexColor; o.pos = UnityObjectToClipPos(v.vertex); return o; } float4 frag(VertexOutput i, float facing : VFACE) : COLOR { float4 _maskCol = tex2D(_MaskTex1,TRANSFORM_TEX(i.uv0, _MaskTex1)); float4 _wenliCol = tex2D(_MaskTex2,TRANSFORM_TEX(i.uv0, _MaskTex2)); float doubleVertexColMinusTex2AlphaMinusOne = step(0, 2 * i.vertexColor.a - _wenliCol.r - 1.0); float alpha = (_maskCol.a * doubleVertexColMinusTex2AlphaMinusOne); clip(alpha - 0.5); float3 finalColor = ((i.vertexColor.rgb * _maskCol.rgb) * (_Brightness* doubleVertexColMinusTex2AlphaMinusOne * 0.1)); return fixed4(finalColor, alpha); } ENDCG } } FallBack "Diffuse" CustomEditor "ShaderForgeMaterialInspector" }
优化后,可读性会高很多,而且浪费性能的运算也会少很多
