- Home /
Opengl es 2.0 Shader Vertex Rotation Issue
I have a simple custom shader that I wrote that takes in two 2D textures, rotates one of them and blends the result creating a mask.
Everything works fine until I ran the game on the 1st Gen iPad Mini which uses opengl es2.0. I am a beginner in writing shaders (this is the first one I've written), and was able to determine it had something to do with the way I was doing the rotation - it seemed like on my ipad that code was ignored completely.
Also, when running the shader in unity and simulating opengl es2.0, it works as expected. It's only when it is run on the device that things don't work correctly.
See the code below - the rotation is in the vert function and happens in the if statement block. Any help is appreciated!
Shader code:
Shader "Sprites/CullingMask" {
Properties{
_MainTex("Texture", 2D) = "white" {}
_Mask("Culling Mask", 2D) = "white" {}
_MaskRotationDegrees("Mask Rotation Degrees", float) = 0.0
}
SubShader {
Tags {
"RenderType" = "Transparent"
"Queue" = "Transparent"
"IgnoreProjector" = "True"
}
LOD 100
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma exclude_renderers ps3 xbox360 flash
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _Mask;
float4 _Mask_ST;
float _MaskRotationDegrees;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
if (_MaskRotationDegrees != 0.0 && abs(_MaskRotationDegrees / 360.0) != 1.0) {
float radians = _MaskRotationDegrees * (UNITY_PI * 2.0) / 360.0;
float s = sin(radians);
float c = cos(radians);
float2x2 rotationMatrix = float2x2(c, -s, s, c);
v.uv -= 0.5; // offset UV so we rotate around 0.5 and not 0.0
v.uv = mul(v.uv, rotationMatrix);
v.uv += 0.5; // offset UV again so UVs are in the correct location
}
o.uv2 = TRANSFORM_TEX(v.uv, _Mask);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return tex2D(_MainTex, i.uv) * tex2D(_Mask, i.uv2).a;
}
ENDCG
}
}
FallBack "Diffuse"
}
Answer by AndyJenkins30 · Dec 21, 2016 at 02:13 PM
Hi Dan,
I would advise removing the 'if' statement from your vertex function. There are a few threads you can read on why creating 'branches' in shader code is a bad idea: https://forum.unity3d.com/threads/branches-how-expensive-are-they.152411/ http://bps10.idav.ucdavis.edu/talks/03-fatahalian_gpuArchTeraflop_BPS_SIGGRAPH2010.pdf
There are a few things you could do instead:
Change '_MaskRotationDegrees' type from float to range, so you can guarantee it appears within the boundaries you set.
Take the modulo of your value to ensure it is between 1-360 ( _MaskRotationDegrees %= 360.0; )
Just let any value pass into your rotation code. You don't seem to ever be dividing by zero so this shouldn't ever compute an error.
I've tested your shader on an iPhone SE running OpenGL ES 2.0 and it rotates/looks as expected. Let me know if your issue still occurs on your iPad mini after removing the if statement.
Best Regards, Andy