hello guys, Yesterday I was messing around with this shader: Spoiler: shader code Code (CSharp): Shader "Sprites/Outline" { Properties { [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} _Color("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap("Pixel snap", Float) = 0 // Add values to determine if outlining is enabled and outline color. [PerRendererData] _Outline("Outline", Float) = 0 [PerRendererData] _OutlineColor("Outline Color", Color) = (1,1,1,1) [PerRendererData] _OutlineSize("Outline Size", int) = 1 [PerRendererData] _Rect ("Rect Display", Vector) = (0,0,1,1) } SubShader { Tags { /// "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile _ PIXELSNAP_ON #pragma shader_feature ETC1_EXTERNAL_ALPHA #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; }; fixed4 _Color; float _Outline; fixed4 _OutlineColor; int _OutlineSize; fixed4 _Rect; v2f vert(appdata_t IN) { v2f OUT; OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap(OUT.vertex); #endif return OUT; } sampler2D _MainTex; sampler2D _AlphaTex; float4 _MainTex_TexelSize; fixed4 SampleSpriteTexture(float2 uv) { fixed4 color = tex2D(_MainTex, uv); #if ETC1_EXTERNAL_ALPHA // get the color from an external texture (usecase: Alpha support for ETC1 on android) color.a = tex2D(_AlphaTex, uv).r; #endif //ETC1_EXTERNAL_ALPHA return color; } fixed4 frag(v2f IN) : SV_Target { fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color; // If outline is enabled and there is a pixel, try to draw an outline. if (_Outline > 0 && c.a != 0) { float totalAlpha = 1.0; if (IN.texcoord.x < _Rect.x + _OutlineSize*_MainTex_TexelSize.x || IN.texcoord.y < _Rect.y + _OutlineSize*_MainTex_TexelSize.y || IN.texcoord.x > _Rect.z - _OutlineSize*_MainTex_TexelSize.x || IN.texcoord.y > _Rect.w - _OutlineSize*_MainTex_TexelSize.y) { totalAlpha = 0; } else { [unroll(16)] for (int i = 1; i < _OutlineSize + 1; i++) { fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y)); fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, i * _MainTex_TexelSize.y)); fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0)); fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0)); totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a; } } if (totalAlpha == 0) { c.rgba = fixed4(1, 1, 1, 1) * _OutlineColor; } } c.rgb *= c.a; return c; } ENDCG } } }
It's an awfully not optimized shader but I don't see any error here, can you explain what's your problem ?
missing part: (the forum does not let me edit the first post don't know why) it works like a charm in the editor, but when I try to compile the project the console returns this: "Shader error in 'Sprites/Outline': '[' : syntax error syntax error at line 107 (on gles)" this is the first time that I try to use a custom shader and I have not Idea why this error occurs I know what this error means of course, but I can't see any problem in the code. can someone enlight me, please? Ps: this shader is not mine, I found it surfing the internet
I never had to use a "for" instruction neither unroll into a shader but after a fast research, DirectX 9 does not support well "for" instruction, that's why "unroll" exist, it will remove the for instruction and unroll it like you have wrote every step of it. "unroll" instruction is for DirectX only and it seems that Unity didn't convert it to an OpenGL equivalent shader code (it seems that the way to do it in opengl is very different).
yes the strange thing is that it does not give me an error every time I try to build and sometimes it still give me an error but it compiles anyway and if i try to run the .apk it works fine. I will try to write my own shader, this one doesn't seem to be the right choice
It is not indeed. Anyway, avoid the usage of "if" statements when you can, it can be replaced most of the time with a lerp or a step function. GPUs are really bad with multi branching code. When a shader give multi possibilities like yours with the "Outline enabled or not check" it's better to have a compilation condition instead, This way Unity will compile multiple version of your shader.
FYI step() is an if. Also gles can't do loops, it always unrolls, but it also doesn't have a [unroll] command which is what it's failing on as it doesn't see that as proper syntax. You're better off using Unity's built in UNITY_UNROLL macro, or using: #if defined(UNITY_COMPILER_HLSL) [unroll(16)] #endif Or just remove that and let the shader compiler do it on it's own.
Yes, step is an if but one if is not really a problem anymore. My point was about the fact that using a step avoid the usage of "else" or another "if" inside an if, a complex branching.