Here you go:
DrawFullscreenOrthographicQuad.cs
using System;
using UnityEngine;
[ExecuteInEditMode]
public class DrawFullscreenOrthographicQuad : MonoBehaviour
{
[SerializeField] Camera _camera;
[SerializeField] Rect _worldRect = new Rect( Vector2.zero , new Vector2(80,40) );
[SerializeField] Vector2 _quadSize = new Vector2(32,16);
[SerializeField] Material _quadMaterial;
[SerializeField][Range(0,1)] float _quadDepth = 0.99f;
Mesh _quadMesh;
Vector2 _quadSizeCorrected, _quadPos, _camSize;
Vector3 _camPos;
void Awake ()
{
_quadMesh = Resources.GetBuiltinResource<Mesh>("Quad.fbx");
}
void Update ()
{
if( _camera!=null )
{
float camOrthoSize = _camera.orthographicSize;
float camAspect = _camera.aspect;
_camSize = new Vector2( camOrthoSize*2f*camAspect , camOrthoSize*2f );
Vector2 camSizeHalf = _camSize * 0.5f;
_camPos = _camera.transform.position;
// correct for scenario when camera aspect is larger than provided quad size
_quadSizeCorrected = new Vector2(
Math.Max( _quadSize.x , camOrthoSize*2f*camAspect ) ,
Math.Max( _quadSize.y , camOrthoSize*2f )
);
Vector2 quadSizeHalf = _quadSizeCorrected * 0.5f;
// find quad position:
Vector2 srcmin = _worldRect.min + camSizeHalf;
Vector2 srcmax = _worldRect.max - camSizeHalf;
Vector2 dstmin = _worldRect.min + quadSizeHalf;
Vector2 dstmax = _worldRect.max - quadSizeHalf;
Vector2 t = new Vector2(
Mathf.InverseLerp( srcmin.x , srcmax.x , _camPos.x ) ,
Mathf.InverseLerp( srcmin.y , srcmax.y , _camPos.y )
);
_quadPos = new Vector2(
Mathf.Lerp( dstmin.x , dstmax.x , t.x ) ,
Mathf.Lerp( dstmin.y , dstmax.y , t.y )
);
float quadPosZ = _camPos.z + _camera.farClipPlane * _quadDepth;
// correct for out of world bounds situations:
_quadPos = Vector2.Max( _quadPos , (Vector2)_camPos-quadSizeHalf+camSizeHalf );
_quadPos = Vector2.Min( _quadPos , (Vector2)_camPos+quadSizeHalf-camSizeHalf );
// draw a quad:
Graphics.DrawMesh(
_quadMesh ,
new Matrix4x4(
new Vector4( _quadSizeCorrected.x , 0 , 0 , 0 ) ,
new Vector4( 0 , _quadSizeCorrected.y , 0 , 0 ) ,
new Vector4( 0 , 0 , 1 , 0 ) ,
new Vector4( _quadPos.x , _quadPos.y , quadPosZ , 1 )
) ,
_quadMaterial ,
1
);
}
}
#if UNITY_EDITOR
void OnDrawGizmos ()
{
// world bounds:
Gizmos.color = Color.red;
Gizmos.DrawWireCube( _worldRect.center , _worldRect.size );
if( _camera!=null )
{
// camera rect:
Gizmos.color = Color.cyan;
Gizmos.DrawWireCube( (Vector2)_camPos , _camSize );
// quad rect:
Gizmos.color = Color.yellow;
Gizmos.DrawWireCube( _quadPos , _quadSizeCorrected );
}
}
#endif
}
The way it works it renders a quad with given material at some depth
The main problem here was how to calculate this quad’s center. Tried few ugly solutions that didn’t work at all. After drawing these gizmos I realized that the nicest solution should be to linearly interpolate between some min and max points - this is what I ended up doing.