Skip to content

Instantly share code, notes, and snippets.

@kurtdekker
Last active June 20, 2024 17:26
Show Gist options
  • Save kurtdekker/2b4c2076b201abb8955f7423006ba8cc to your computer and use it in GitHub Desktop.
Save kurtdekker/2b4c2076b201abb8955f7423006ba8cc to your computer and use it in GitHub Desktop.
Low-resolution (LORES) rendering in Unity3D
using UnityEngine;
// @kurtdekker - Cheesy quick way to do low-resolution in Unity3D:
//
// This script creates and controls the final Camera, not the Main Camera.
//
// Player Scene, when loaded, MUST have a Main Camera that we hijack.
//
// DO NOT DROP THIS ON A CAMERA!
//
// How to use: You have TWO choices. Do only ONE of the following:
//
// - from your own code call the static Create() method
//
// or...
//
// - drop this script on a blank GameObject (NOT the Camera!)
//
// You can even have your scene running already and add this in
// via either of the two above methods and it should Just Work(tm).
//
// In all cases it expects an Unlit/Texture Material asset to
// be located somewhere in Resources/LORES/Unlit.mat
//
public partial class LORES : MonoBehaviour
{
//--------------------------- BEGIN SOURCE DATA
public const int DefaultScanlines = 200;
public const FilterMode DefaultFilterMode = FilterMode.Point;
// This is just "kinda far away." If you prefer, use Layers and selective
// rendering and you can have it all physically in the same location.
Vector3 farawayDistantPoint = new Vector3( 500, 0, 0);
Material UnlitMaterial { get {
// this allows things like FLIR materials to be injected
if (injectedMtl)
{
return injectedMtl;
}
return Resources.Load<Material>( "LORES/Unlit");
}
}
//--------------------------- END SOURCE DATA
Material injectedMtl;
// alternate way of injecting a material such as for my FLIR package
public void InjectMaterial( Material m)
{
injectedMtl = m;
}
RenderTexture rt;
Camera mainCam;
Renderer rend;
Material mtl;
int scanLines = DefaultScanlines;
FilterMode filterMode = DefaultFilterMode;
public static LORES Create( int scanLines = DefaultScanlines, FilterMode filterMode = DefaultFilterMode)
{
var LR = new GameObject( "LORES.Create(" + scanLines + ");").AddComponent<LORES>();
LR.scanLines = scanLines;
LR.filterMode = filterMode;
LR.RemakeStage();
return LR;
}
void Reset()
{
name = GetType() + ".PlacedInScene";
}
void Start()
{
RemakeStage();
OrientationChangeSensor.Create( transform, RemakeStage);
}
GameObject container;
void RemakeStage()
{
mainCam = null;
if (container)
{
Destroy( container);
rend = null;
}
container = new GameObject("StageContainer");
container.transform.SetParent(transform);
container.transform.localPosition = Vector3.zero;
container.transform.localRotation = Quaternion.identity;
var stageCam = new GameObject(GetType() + ".Camera").AddComponent<Camera>();
stageCam.transform.SetParent( container.transform);
stageCam.transform.localPosition = Vector3.back * 2.0f;
stageCam.orthographic = true;
stageCam.orthographicSize = 0.5f;
stageCam.nearClipPlane = 1.0f;
stageCam.farClipPlane = 3.0f;
var quad = GameObject.CreatePrimitive( PrimitiveType.Quad);
quad.transform.SetParent( container.transform);
quad.transform.localPosition = Vector3.zero;
quad.transform.localScale = new Vector3( (float)Screen.width / Screen.height, 1.0f, 1.0f);
mtl = UnlitMaterial;
rend = quad.GetComponent<Renderer>();
rend.material = mtl;
// unhook
mtl.mainTexture = null;
stageCam.targetTexture = null;
container.transform.position = farawayDistantPoint;
}
void MakeRenderTexture()
{
if (rt)
{
Destroy(rt);
}
int height = scanLines;
int width = (height * Screen.width) / Screen.height;
rt = new RenderTexture( width, height, 32);
rt.filterMode = filterMode;
mainCam.targetTexture = rt;
mtl.mainTexture = rt;
rend.material = mtl; // JIC
}
void Update()
{
if (!mainCam)
{
mainCam = Camera.main;
if (mainCam)
{
MakeRenderTexture();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment