- 环境
- 目的
- 问题
- 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"
}
优化后,可读性会高很多,而且浪费性能的运算也会少很多