I am developing for Mobile VR using GoogleVRSDK and Unity. My target platform is Android. I have a shader which displaces vertices to create a reverse lens distortion.
Following is my shader,
Shader "Unlit/Cube"
{
Properties {
_Color("Main Color", Color) = (1,1,1,1)
}
Category {
Tags { "Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Opaque" }
Blend Off
AlphaTest off
Cull off
Lighting Off
ZWrite On
ZTest LEqual
Fog { Mode Off }
SubShader {
Pass {
CGPROGRAM
// #pragma target 3.5
// #pragma target 2.0
// #pragma only_renderers gles2
// #pragma only_renderers gles
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#pragma multi_compile __ GVR_DISTORTION
#include "GvrDistortion.cginc"
struct VertexInput {
half4 vertex : POSITION;
half4 texcoord : TEXCOORD0;
};
struct v2f {
half4 vertex : SV_POSITION;
half4 uv : TEXCOORD0;
};
v2f VertexProgram (VertexInput v)
{
v2f o;
o.uv = v.texcoord;
o.vertex = undistortVertex(v.vertex);
return o;
};
fixed4 _Color;
fixed4 FragmentProgram (v2f fragment) : COLOR
{
return _Color;
}
ENDCG
}
}
}
Following is my GvrDistortion.cginc
#if defined(GVR_DISTORTION)
float4x4 _Undistortion;
float _MaxRadSq;
float _NearClip;
float4x4 _RealProjection;
float4x4 _FixProjection;
float distortionFactor(float rSquared) {
float ret = 0.0;
ret = rSquared * (ret + _Undistortion[1][1]);
ret = rSquared * (ret + _Undistortion[0][1]);
ret = rSquared * (ret + _Undistortion[3][0]);
ret = rSquared * (ret + _Undistortion[2][0]);
ret = rSquared * (ret + _Undistortion[1][0]);
ret = rSquared * (ret + _Undistortion[0][0]);
return ret + 1.0;
}
// Convert point from world space to undistorted camera space.
float4 undistort(float4 pos) {
// Go to camera space.
pos = mul(UNITY_MATRIX_MV, pos);
if (pos.z <= -_NearClip) { // Reminder: Forward is -Z.
// Undistort the point's coordinates in XY.
float r2 = clamp(dot(pos.xy, pos.xy) / (pos.z*pos.z), 0, _MaxRadSq);
pos.xy *= distortionFactor(r2);
}
return pos;
}
// Multiply by no-lens projection matrix after undistortion.
float4 undistortVertex(float4 pos) {
return mul(_RealProjection, undistort(pos));
}
// Surface shader hides away the MVP multiplication, so we have
// to multiply by _FixProjection = inverse(VP)*_RealProjection
// and then by inverse(M), in order to cancel it out and leave our
// own transform in place.
float4 undistortSurface(float4 pos) {
float4 proj = mul(_FixProjection, undistort(pos));
return mul(unity_WorldToObject, proj);
}
#else
// Distortion disabled.
// Just do the standard MVP transform.
float4 undistortVertex(float4 pos) {
return mul(UNITY_MATRIX_MVP, pos);
}
// Surface shader hides away the MVP multiplication, so just return pos.
float4 undistortSurface(float4 pos) {
return pos;
}
#endif
This shader works completely as excepted in Samsung S6 and LG G3 and the Unity Editor.
But we are working for a phone named Venus. In that phone shader renders but the displacement of vertices doesn't happen.
I tried disabling conditional compiling. I tried changing render targets and forcing different OpenGL versions in render.
Nothing worked. I would love to hear a solution. Thank you.
The specs of the Venus,
GPU Adreno(TM) 405 Runs OpenGL ES 3.0 GPU SM:4.0 and VRAM 512MB RM 2gigs Screen 1080x1920 60hz dpi 480 Android 5.1 API-22 CPU is ARMv7 VFPv3 NEON (8 cores)