I already had this working, but with the upgrade to Unity 5, this is now broken.
The idea is to render my GUI at retina resolution, but the 3D world behind the game at half resolution.
This was fairly easy to do:
- change the camera’s viewport to make it render the scene to the bottom left quarter of the buffer
- use post processing to stretch the small image to the full screen size when blitting.
The script on the camera:
public float renderScale = 1.0f;
private Material cameraMaterial;
void OnPreRender() {
cameraMaterial.SetFloat("_InvRenderScale", renderScale);
GL.Viewport(new Rect(0, 0, Screen.width * renderScale,
Screen.height * renderScale));
}
void OnRenderImage(RenderTexture source, RenderTexture destination) {
Graphics.Blit(source, destination, cameraMaterial);
}
void OnPostRender() {
GL.Viewport(new Rect(0, 0, Screen.width, Screen.height));
}
And the relevant bits of the shader for cameraMaterial:
half _InvRenderScale;
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = half2(v.texcoord.x * _InvRenderScale,
v.texcoord.y * _InvRenderScale);
return o;
}
half4 frag (v2f i) : COLOR {
return tex2D(_MainTex, i.uv);
}
Finally the problem is that Unity doesn’t respect my call to GL.Viewport() in OnPreRender().
So instead of rendering the scene to the bottom left 1/4 of the screen then stretching it, it renders the scene full screen and then stretches the bottom left 1/4 to full screen.
How can I work around this issue?
And is this a bug, or by design?