- Home /
Why does this IOS / OGLES shader not match PC version?
I've got a CG shader which does some UV distortion in the vertex program. It works fine on PC, and it compiles without complaining to IOS. However the IOS version appears not to be sampling the uV's correcty; as far as I can see the whole mesh is sampling the same UV coordinate on IOS.
The original cg is here:
Pass {
Blend srcAlpha One // Alpha blending
ZWrite Off
cull Front
CGPROGRAM
#include "UnityCG.cginc"
#include "Assets/Shaders/FX/fx_include.cginc"
#pragma target 3.0
// #pragma glsl
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers ps3 flash d3d11 xbox360 opengl
uniform sampler2D _MainTex;
uniform half _Softness;
uniform fixed _BackScale;
uniform half4 _Scroll;
uniform fixed _Noise;
uniform fixed _Sharpen;
uniform half4 _Volume;
int _CellsU;
int _CellsV;
uniform fixed _Balance;
half _Distort;
half4 _BackTint;
half _BackPower;
uniform half4x4 _UOffsetMatrix;
uniform half4x4 _VOffsetMatrix;
struct vertexInput {
float4 vertex : POSITION;
half4 tex : TEXCOORD0;
half4 tex1: TEXCOORD1;
half4 normal:NORMAL;
half4 vertColor:COLOR;
};
struct vertexOutput {
half4 pos : SV_POSITION;
half4 vertColor: COLOR;
half4 uv_map : TEXCOORD0;
half4 secondary_map: TEXCOORD1;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
float2 scaled_coord = input.tex.xy * -1 * float2(_CellsU , _CellsV);
float2 fracuv = frac(scaled_coord) - float2(.5);
int2 cell = floor(scaled_coord);
int idx = (cell.y * _CellsU) + cell.x;
idx = idx % 16;
half2 tx_offset = cell_lookup(idx, _UOffsetMatrix, _VOffsetMatrix);
tx_offset *= pow((.707 - length(fracuv)),2);
tx_offset *= _Distort;
output.uv_map = scrolled(mul(input.tex, UNITY_MATRIX_TEXTURE0), _Scroll.xyxy) /_BackScale;
output.uv_map += float4(tx_offset, 0,0) / float4(_CellsU, _CellsV, 1, 1);
output.secondary_map = scrolled(mul(input.tex1, UNITY_MATRIX_TEXTURE0), _Scroll.zwzw) /_BackScale;
output.secondary_map += float4(tx_offset, 0,0) / float4(_CellsU, _CellsV, 1, 1) ;
// float4 vert_offset;
// vert_offset.xz += (pow(tx_offset,.95) * _Noise );
// vert_offset *= _SinTime.wwxx;
// vert_offset += (_CosTime * _Noise) / 100;
half4 worldpos = mul(_Object2World, input.vertex);// + vert_offset);
half4 worldnormal = mul (_Object2World, input.normal);
worldnormal = normalize(half4 (worldnormal.xyz,0));
output.pos = mul(UNITY_MATRIX_VP, worldpos) ;
float3 osvd = normalize(ObjSpaceViewDir (input.vertex));
float3 osn = normalize(input.normal.xyz);
output.vertColor = input.vertColor * pow(dot(osvd, osn),_Softness);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
half4 c = tex2D(_MainTex, input.secondary_map.xy);//* input.secondary_map.w;
half4 d = tex2D(_MainTex, input.uv_map.xy);
return saturate(_BackTint * _BackPower * input.vertColor * pow( lerp(d, c, _Balance), _Sharpen));
}
ENDCG
}
and the compiled ARB I get from unity is here:
SubProgram "gles " {
Keywords { }
"!!GLES
#ifdef VERTEX
varying mediump vec4 xlv_TEXCOORD1;
varying mediump vec4 xlv_TEXCOORD0;
varying mediump vec4 xlv_COLOR;
uniform mediump mat4 _VOffsetMatrix;
uniform mediump mat4 _UOffsetMatrix;
uniform mediump float _Distort;
uniform int _CellsV;
uniform int _CellsU;
uniform mediump vec4 _Scroll;
uniform lowp float _FrontScale;
uniform mediump float _Softness;
uniform highp mat4 unity_MatrixVP;
uniform highp mat4 glstate_matrix_texture0;
uniform highp vec4 unity_Scale;
uniform highp mat4 _World2Object;
uniform highp mat4 _Object2World;
uniform highp vec3 _WorldSpaceCameraPos;
uniform highp vec4 _Time;
attribute vec4 _glesMultiTexCoord1;
attribute vec4 _glesMultiTexCoord0;
attribute vec3 _glesNormal;
attribute vec4 _glesColor;
attribute vec4 _glesVertex;
void main ()
{
vec4 tmpvar_1;
tmpvar_1.w = 0.0;
tmpvar_1.xyz = normalize(_glesNormal);
highp vec3 osn_2;
mediump vec4 worldnormal_3;
mediump vec4 worldpos_4;
mediump vec2 tx_offset_5;
mediump vec4 tmpvar_6;
mediump vec4 tmpvar_7;
mediump vec4 tmpvar_8;
highp vec2 tmpvar_9;
tmpvar_9.x = float(_CellsU);
tmpvar_9.y = float(_CellsV);
highp vec2 tmpvar_10;
tmpvar_10 = (_glesMultiTexCoord0.xy * tmpvar_9);
highp vec2 tmpvar_11;
tmpvar_11 = (fract(tmpvar_10) - vec2(0.5, 0.5));
ivec2 tmpvar_12;
tmpvar_12 = ivec2(floor(tmpvar_10));
int tmpvar_13;
tmpvar_13 = int((float(mod (float(((tmpvar_12.y * _CellsU) + tmpvar_12.x)), 16.0))));
lowp vec2 tmpvar_14;
lowp mat4 uTable_15;
uTable_15 = (_UOffsetMatrix);
lowp mat4 vTable_16;
vTable_16 = (_VOffsetMatrix);
mediump float voff_17;
mediump float uoff_18;
int tmpvar_19;
tmpvar_19 = (tmpvar_13 / 4);
int tmpvar_20;
tmpvar_20 = int((float(mod (float(tmpvar_13), 4.0))));
bvec4 tmpvar_21;
tmpvar_21.x = (tmpvar_20 == 0);
tmpvar_21.y = (tmpvar_20 == 1);
tmpvar_21.z = (tmpvar_20 == 2);
tmpvar_21.w = (tmpvar_20 == 3);
bvec4 tmpvar_22;
tmpvar_22.x = (tmpvar_19 == 0);
tmpvar_22.y = (tmpvar_19 == 1);
tmpvar_22.z = (tmpvar_19 == 2);
tmpvar_22.w = (tmpvar_19 == 3);
highp float tmpvar_23;
tmpvar_23 = dot ((uTable_15 * vec4(tmpvar_21)), vec4(tmpvar_22));
uoff_18 = tmpvar_23;
highp float tmpvar_24;
tmpvar_24 = dot ((vTable_16 * vec4(tmpvar_21)), vec4(tmpvar_22));
voff_17 = tmpvar_24;
mediump vec2 tmpvar_25;
tmpvar_25.x = uoff_18;
tmpvar_25.y = voff_17;
tmpvar_14 = tmpvar_25;
tx_offset_5 = tmpvar_14;
highp vec2 tmpvar_26;
tmpvar_26 = (tx_offset_5 * (_Distort * pow ((0.707 - sqrt(dot (tmpvar_11, tmpvar_11))), 2.0)));
tx_offset_5 = tmpvar_26;
highp vec4 tmpvar_27;
tmpvar_27 = (((_glesMultiTexCoord0 * glstate_matrix_texture0) + ((-1.0 * _Scroll.xyxy) * _Time.y)) / _FrontScale);
tmpvar_7 = tmpvar_27;
mediump vec4 tmpvar_28;
tmpvar_28.zw = vec2(0.0, 0.0);
tmpvar_28.xy = tx_offset_5;
highp vec4 tmpvar_29;
tmpvar_29.zw = vec2(1.0, 1.0);
tmpvar_29.x = float(_CellsU);
tmpvar_29.y = float(_CellsV);
highp vec4 tmpvar_30;
tmpvar_30 = (tmpvar_7 + (tmpvar_28 / tmpvar_29));
tmpvar_7 = tmpvar_30;
highp vec4 tmpvar_31;
tmpvar_31 = (((_glesMultiTexCoord1 * glstate_matrix_texture0) + ((-1.0 * _Scroll.zwzw) * _Time.y)) / _FrontScale);
tmpvar_8 = tmpvar_31;
mediump vec4 tmpvar_32;
tmpvar_32.zw = vec2(0.0, 0.0);
tmpvar_32.xy = tx_offset_5;
highp vec4 tmpvar_33;
tmpvar_33.zw = vec2(1.0, 1.0);
tmpvar_33.x = float(_CellsU);
tmpvar_33.y = float(_CellsV);
highp vec4 tmpvar_34;
tmpvar_34 = (tmpvar_8 + (tmpvar_32 / tmpvar_33));
tmpvar_8 = tmpvar_34;
highp vec4 tmpvar_35;
tmpvar_35 = (_Object2World * _glesVertex);
worldpos_4 = tmpvar_35;
highp vec4 tmpvar_36;
tmpvar_36 = (_Object2World * tmpvar_1);
worldnormal_3 = tmpvar_36;
mediump vec4 tmpvar_37;
tmpvar_37.w = 0.0;
tmpvar_37.xyz = worldnormal_3.xyz;
worldnormal_3 = normalize(tmpvar_37);
highp vec4 tmpvar_38;
tmpvar_38.w = 1.0;
tmpvar_38.xyz = _WorldSpaceCameraPos;
mediump vec3 tmpvar_39;
tmpvar_39 = normalize(tmpvar_1.xyz);
osn_2 = tmpvar_39;
highp vec4 tmpvar_40;
tmpvar_40 = (_glesColor * pow (dot (normalize((((_World2Object * tmpvar_38).xyz * unity_Scale.w) - _glesVertex.xyz)), osn_2), _Softness));
tmpvar_6 = tmpvar_40;
gl_Position = (unity_MatrixVP * worldpos_4);
xlv_COLOR = tmpvar_6;
xlv_TEXCOORD0 = tmpvar_7;
xlv_TEXCOORD1 = tmpvar_8;
}
#endif
#ifdef FRAGMENT
varying mediump vec4 xlv_TEXCOORD1;
varying mediump vec4 xlv_TEXCOORD0;
varying mediump vec4 xlv_COLOR;
uniform mediump float _Power;
uniform mediump vec4 _Tint;
uniform lowp float _Balance;
uniform lowp float _Sharpen;
uniform sampler2D _MainTex;
void main ()
{
highp vec4 tmpvar_1;
mediump vec4 d_2;
mediump vec4 c_3;
lowp vec4 tmpvar_4;
tmpvar_4 = texture2D (_MainTex, xlv_TEXCOORD1.xy);
c_3 = tmpvar_4;
lowp vec4 tmpvar_5;
tmpvar_5 = texture2D (_MainTex, xlv_TEXCOORD0.xy);
d_2 = tmpvar_5;
mediump vec4 tmpvar_6;
tmpvar_6 = clamp ((((_Tint * _Power) * xlv_COLOR) * pow (mix (d_2, c_3, vec4(_Balance)), vec4(_Sharpen))), 0.0, 1.0);
tmpvar_1 = tmpvar_6;
gl_FragData[0] = tmpvar_1;
}
#endif"
}
the 'cell_lookup' function in the CG version is in an include: it uses dotproducts to find a value out of a 4x4 matrix (since I can't pass a plain old array in OGL);.
One odd thing I've noticed is that the pixel shader with this line in the ARB version:
tmpvar_6 = clamp ((((_Tint _Power) xlv_COLOR) * pow (mix (d_2, c_3, vec4(_Balance)), vec4(_Sharpen))), 0.0, 1.0);
which comes from the cg line:
return saturate(_BackTint * _BackPower * input.vertColor * pow( lerp(d, c, _Balance), _Sharpen));
which doesn't seem right - why is unity turning _Sharpen ( a float that applies a power falloff to the calculated pixel color) into a float4?
Anyway my main question is : why doesn't the IOS version read the texture the same way. The other vertex processing works, but the UVs are borked.
Further wierdness: I rewrote lines 70 -76 in the CG version so they deform the verts again:
fixed4 vert_offset = input.normal * sin(tx_offset.x) * _Noise;
half4 worldpos = mul(_Object2World, input.vertex + vert_offset);
... and now the textures scroll. WTH????
That seems to fix the texture scrolling reliably. Why, I don't know.
sigh