├── .gitignore ├── LICENSE ├── LICENSE.meta ├── PixelCamDrawer.cs ├── PixelCamDrawer.cs.meta ├── PixelCamFallback.shader ├── PixelCamFallback.shader.meta ├── PixelCamera.cs ├── PixelCamera.cs.meta ├── README.md └── README.md.meta /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | *.unitypackage 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jeiel Aranal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79f9d5cb70ce03f4986e605d1583609e 3 | timeCreated: 1488381179 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /PixelCamDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace SubjectNerd.Utilities 4 | { 5 | [ExecuteInEditMode] 6 | [AddComponentMenu("")] 7 | public class PixelCamDrawer : MonoBehaviour 8 | { 9 | /* 10 | This class sits on a hidden camera that draws nothing, the pixel camera output 11 | is being redirected to a render texture, so we need a camera context to draw into 12 | */ 13 | public PixelCamera SourceCamera { get; set; } 14 | 15 | private void OnPostRender() 16 | { 17 | if (SourceCamera == null) return; 18 | DrawQuad(); 19 | SourceCamera.CheckCamera(); 20 | } 21 | 22 | public void DrawQuad() 23 | { 24 | if (SourceCamera == null || SourceCamera.CameraMaterial == null) 25 | return; 26 | 27 | Vector2 min = SourceCamera.QuadMin; 28 | Vector2 max = SourceCamera.QuadMax; 29 | 30 | float zOffset = -0.1f; 31 | 32 | Material renderMat = SourceCamera.CameraMaterial; 33 | GL.PushMatrix(); 34 | GL.LoadOrtho(); 35 | for (int i = 0; i < renderMat.passCount; i++) 36 | { 37 | renderMat.SetPass(i); 38 | 39 | GL.Begin(GL.QUADS); 40 | 41 | GL.TexCoord2(0.0f, 0.0f); 42 | GL.Vertex3(min.x, min.y, zOffset); 43 | GL.TexCoord2(0.0f, 1.0f); 44 | GL.Vertex3(min.x, max.y, zOffset); 45 | GL.TexCoord2(1.0f, 1.0f); 46 | GL.Vertex3(max.x, max.y, zOffset); 47 | GL.TexCoord2(1.0f, 0.0f); 48 | GL.Vertex3(max.x, min.y, zOffset); 49 | 50 | GL.End(); 51 | } 52 | GL.PopMatrix(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /PixelCamDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a7cc3004c6416db4980b6c46de6bd972 3 | timeCreated: 1488381179 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /PixelCamFallback.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/SubjectNerd/PixelCamFallback" 2 | { 3 | // Simple unlit shader with fog removed 4 | Properties 5 | { 6 | _MainTex ("Texture", 2D) = "white" {} 7 | } 8 | SubShader 9 | { 10 | Tags { "RenderType"="Opaque" } 11 | LOD 100 12 | 13 | Pass 14 | { 15 | CGPROGRAM 16 | #pragma vertex vert 17 | #pragma fragment frag 18 | 19 | #include "UnityCG.cginc" 20 | 21 | struct appdata 22 | { 23 | float4 vertex : POSITION; 24 | float2 uv : TEXCOORD0; 25 | }; 26 | 27 | struct v2f 28 | { 29 | float2 uv : TEXCOORD0; 30 | float4 vertex : SV_POSITION; 31 | }; 32 | 33 | sampler2D _MainTex; 34 | float4 _MainTex_ST; 35 | 36 | v2f vert (appdata v) 37 | { 38 | v2f o; 39 | o.vertex = UnityObjectToClipPos(v.vertex); 40 | o.uv = TRANSFORM_TEX(v.uv, _MainTex); 41 | return o; 42 | } 43 | 44 | fixed4 frag (v2f i) : SV_Target 45 | { 46 | // sample the texture 47 | fixed4 col = tex2D(_MainTex, i.uv); 48 | return col; 49 | } 50 | ENDCG 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /PixelCamFallback.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 549026f9040c7234f9c316d29194b4eb 3 | timeCreated: 1488381182 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /PixelCamera.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace SubjectNerd.Utilities 5 | { 6 | [ExecuteInEditMode] 7 | [RequireComponent(typeof(Camera))] 8 | public class PixelCamera : MonoBehaviour 9 | { 10 | [Serializable] 11 | protected class AdvancedSettings 12 | { 13 | [Tooltip("Material to draw output render with")] 14 | public Material cameraMaterial; 15 | [Tooltip("Stretches output display, for non square pixels")] 16 | public Vector2 aspectStretch = Vector2.one; 17 | [Tooltip("Scales down camera render size")] 18 | public float downSample = 1; 19 | [Tooltip("Z distance to draw as pixel perfect for perspective camera.")] 20 | public float perspectiveZ = 10; 21 | } 22 | 23 | protected struct CamSettings 24 | { 25 | public int[] screenSize; 26 | public Vector2 aspect; 27 | public float zoomLevel; 28 | public float pixelsPerUnit; 29 | public float zDistance; 30 | public float downsample; 31 | public float fieldOfView; 32 | public float farPlane; 33 | public bool isOrtho; 34 | 35 | public CamSettings(PixelCamera pixelCam, Camera cam) 36 | { 37 | screenSize = new[] {Screen.width, Screen.height}; 38 | this.aspect = pixelCam.AspectStretch; 39 | this.zoomLevel = pixelCam.ZoomLevel; 40 | this.pixelsPerUnit = pixelCam.pixelsPerUnit; 41 | this.zDistance = pixelCam.PerspectiveZ; 42 | this.downsample = pixelCam.DownSample; 43 | this.fieldOfView = cam.fieldOfView; 44 | this.isOrtho = cam.orthographic; 45 | this.farPlane = cam.farClipPlane; 46 | } 47 | 48 | public bool Equals(CamSettings other) 49 | { 50 | bool equalScreen = other.screenSize[0] == screenSize[0] && 51 | other.screenSize[1] == screenSize[1]; 52 | bool equalAspect = other.aspect == aspect; 53 | 54 | bool isEqual = other.isOrtho == isOrtho && 55 | equalScreen && 56 | equalAspect && 57 | Mathf.Approximately(other.zoomLevel, zoomLevel) && 58 | Mathf.Approximately(other.pixelsPerUnit, pixelsPerUnit) && 59 | Mathf.Approximately(other.downsample, downsample); 60 | 61 | if (isEqual && isOrtho == false) 62 | { 63 | isEqual &= Mathf.Approximately(other.zDistance, zDistance) && 64 | Mathf.Approximately(other.fieldOfView, fieldOfView) && 65 | Mathf.Approximately(other.farPlane, farPlane); 66 | } 67 | 68 | return isEqual; 69 | } 70 | } 71 | 72 | [SerializeField] protected Camera cam; 73 | [SerializeField] protected float pixelsPerUnit = 100; 74 | [SerializeField] protected float zoomLevel = 1f; 75 | [Space] 76 | [SerializeField] protected AdvancedSettings advancedSettings; 77 | 78 | protected RenderTexture renderTexture; 79 | 80 | protected GameObject falseCamGO; 81 | protected Camera falseCam; 82 | protected PixelCamDrawer camDraw; 83 | 84 | protected Shader fallbackShader; 85 | protected Material fallbackMaterial; 86 | 87 | protected CamSettings lastSettings; 88 | 89 | protected Vector2 quadOffset; 90 | public Vector2 QuadMin { get; protected set; } 91 | public Vector2 QuadMax { get; protected set; } 92 | 93 | /// 94 | /// Material to draw output render with 95 | /// 96 | public Material CameraMaterial 97 | { 98 | get 99 | { 100 | Material useMaterial = fallbackMaterial; 101 | if (advancedSettings != null && advancedSettings.cameraMaterial != null) 102 | useMaterial = advancedSettings.cameraMaterial; 103 | return useMaterial; 104 | } 105 | set 106 | { 107 | if (advancedSettings.cameraMaterial != null) 108 | advancedSettings.cameraMaterial.SetTexture("_MainTex", null); 109 | 110 | advancedSettings.cameraMaterial = value; 111 | if (advancedSettings.cameraMaterial == null) return; 112 | 113 | if (renderTexture != null) 114 | advancedSettings.cameraMaterial.SetTexture("_MainTex", renderTexture); 115 | } 116 | } 117 | 118 | public float ZoomLevel 119 | { 120 | get { return zoomLevel; } 121 | set { zoomLevel = value; } 122 | } 123 | 124 | public float PixelsPerUnit 125 | { 126 | get { return pixelsPerUnit; } 127 | set { pixelsPerUnit = value; } 128 | } 129 | 130 | /// 131 | /// For perspective cameras. Z distance between near and far plane to scale as pixel perfect. 132 | /// 133 | public float PerspectiveZ 134 | { 135 | get 136 | { 137 | if (advancedSettings == null) 138 | return cam.farClipPlane*0.5f; 139 | advancedSettings.perspectiveZ = Mathf.Clamp(advancedSettings.perspectiveZ, cam.nearClipPlane, cam.farClipPlane); 140 | return advancedSettings.perspectiveZ; 141 | } 142 | set 143 | { 144 | if (advancedSettings == null) 145 | return; 146 | advancedSettings.perspectiveZ = Mathf.Clamp(value, cam.nearClipPlane, cam.farClipPlane); ; 147 | } 148 | } 149 | 150 | /// 151 | /// Stretches output display, for non square pixels 152 | /// 153 | public Vector2 AspectStretch 154 | { 155 | get 156 | { 157 | if (advancedSettings == null) 158 | return Vector2.one; 159 | return advancedSettings.aspectStretch; 160 | } 161 | set 162 | { 163 | if (advancedSettings == null) 164 | return; 165 | advancedSettings.aspectStretch = value; 166 | } 167 | } 168 | 169 | /// 170 | /// Scales down camera render size. Clamped at minimum value of 1. 171 | /// 172 | public float DownSample 173 | { 174 | get 175 | { 176 | if (advancedSettings == null) 177 | return 1f; 178 | advancedSettings.downSample = Mathf.Max(1f, advancedSettings.downSample); 179 | return advancedSettings.downSample; 180 | } 181 | set 182 | { 183 | if (advancedSettings == null) 184 | return; 185 | advancedSettings.downSample = Mathf.Max(1f, value); 186 | } 187 | } 188 | 189 | /// 190 | /// The render texture camera is being drawn into 191 | /// 192 | public RenderTexture RenderTexture { get { return renderTexture; } } 193 | 194 | /// 195 | /// Pixel size of the camera 196 | /// 197 | public int[] CameraSize 198 | { 199 | get 200 | { 201 | if (renderTexture == null) 202 | return new[] {0, 0}; 203 | 204 | return new[] {renderTexture.width, renderTexture.height}; 205 | } 206 | } 207 | 208 | private void Reset() 209 | { 210 | cam = GetComponent(); 211 | float cameraPixelHeight = Mathf.FloorToInt(cam.aspect*2*pixelsPerUnit); 212 | zoomLevel = Screen.height/cameraPixelHeight; 213 | } 214 | 215 | private void Start() 216 | { 217 | // Disable if we don't support image effects 218 | if (!SystemInfo.supportsImageEffects) 219 | enabled = false; 220 | 221 | if (cam == null) 222 | cam = GetComponent(); 223 | if (cam == null) 224 | enabled = false; 225 | 226 | OnDisable(); // Force cleanup 227 | if (enabled) 228 | OnEnable(); 229 | } 230 | 231 | protected virtual void OnEnable() 232 | { 233 | lastSettings = new CamSettings(this, cam) 234 | { 235 | screenSize = new []{0, 0} 236 | }; 237 | ForceRefresh(); 238 | 239 | falseCamGO = new GameObject("False Camera") {hideFlags = HideFlags.HideAndDontSave}; 240 | falseCam = falseCamGO.AddComponent(); 241 | falseCam.cullingMask = LayerMask.GetMask(); 242 | 243 | camDraw = falseCamGO.AddComponent(); 244 | camDraw.SourceCamera = this; 245 | 246 | fallbackShader = Shader.Find("Hidden/SubjectNerd/PixelCamFallback"); 247 | if (fallbackShader != null) 248 | { 249 | fallbackMaterial = new Material(fallbackShader) 250 | { 251 | hideFlags = HideFlags.DontSave 252 | }; 253 | } 254 | else 255 | { 256 | Debug.Log("Couldn't find fall back shader, material not created"); 257 | enabled = false; 258 | } 259 | } 260 | 261 | protected virtual void OnDisable() 262 | { 263 | if (fallbackMaterial != null) 264 | DestroyImmediate(fallbackMaterial); 265 | fallbackShader = null; 266 | cam.targetTexture = null; 267 | cam.ResetAspect(); 268 | if (renderTexture != null) 269 | DestroyImmediate(renderTexture); 270 | if (falseCamGO != null) 271 | DestroyImmediate(falseCamGO); 272 | falseCam = null; 273 | } 274 | 275 | private void SetupCamera(CamSettings settings) 276 | { 277 | var aspect = settings.aspect; 278 | 279 | zoomLevel = Mathf.Max(0.05f, Mathf.Abs(zoomLevel))*Math.Sign(zoomLevel); 280 | // "Physical" pixel render size 281 | Vector2 screenRenderSize = GetScreenRenderSize(); 282 | // Pixel render size 283 | int[] pixelRenderSize = GetRenderTextureSize(screenRenderSize, settings.aspect); 284 | 285 | float targetAspect = (float)pixelRenderSize[0] / (float)pixelRenderSize[1]; 286 | cam.aspect = targetAspect; 287 | 288 | if (cam.orthographic) 289 | { 290 | // Orthographic camera needs to use screen size when calculating quad offset 291 | screenRenderSize = new Vector2(Screen.width, Screen.height); 292 | 293 | // Set the camera's size, according to pixel size 294 | float targetHeight = pixelRenderSize[1]; 295 | // Use pixel density to convert to world units 296 | targetHeight /= pixelsPerUnit; 297 | targetHeight /= 2f; 298 | // Change orthographic size so camera is sized to world unit 299 | cam.orthographicSize = targetHeight; 300 | } 301 | 302 | // Find the settings to be used for drawing the GL quad 303 | CalculateQuad(screenRenderSize, pixelRenderSize); 304 | 305 | // Important to release current render texture 306 | cam.targetTexture = null; 307 | fallbackMaterial.SetTexture("_MainTex", null); 308 | if (advancedSettings != null && advancedSettings.cameraMaterial != null) 309 | advancedSettings.cameraMaterial.SetTexture("_MainTex", null); 310 | if (renderTexture != null) 311 | renderTexture.Release(); 312 | 313 | // Create new render texture 314 | Vector2 renderSize = new Vector2(pixelRenderSize[0], pixelRenderSize[1]) / settings.downsample; 315 | int[] actualRenderSize = GetRenderTextureSize(renderSize, Vector2.one); 316 | renderTexture = new RenderTexture(actualRenderSize[0], actualRenderSize[1], 0) 317 | { 318 | useMipMap = true, 319 | filterMode = FilterMode.Point, 320 | wrapMode = TextureWrapMode.Clamp 321 | }; 322 | // Make main camera render into it 323 | cam.targetTexture = renderTexture; 324 | 325 | // Set render texture as _MainTex on materials 326 | fallbackMaterial.SetTexture("_MainTex", renderTexture); 327 | if (advancedSettings != null) 328 | CameraMaterial = advancedSettings.cameraMaterial; 329 | 330 | lastSettings = settings; 331 | 332 | cam.Render(); 333 | camDraw.DrawQuad(); 334 | } 335 | 336 | private float GetPerspectiveHeight(float z) 337 | { 338 | var frustumHeight = 2.0f * z * Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad); 339 | return frustumHeight; 340 | } 341 | 342 | protected Vector2 GetScreenRenderSize() 343 | { 344 | // For orthographic camera, physical render size is based on screen pixels 345 | Vector2 screenRenderSize = new Vector2(Screen.width, Screen.height); 346 | screenRenderSize /= zoomLevel; 347 | 348 | // For perspective camera, physical render is based on world unit height 349 | // in terms of fustrum distance, converted to pixels 350 | if (cam.orthographic == false) 351 | { 352 | cam.aspect = (float) Screen.width / Screen.height; 353 | 354 | float scale = Mathf.InverseLerp(cam.nearClipPlane, cam.farClipPlane, PerspectiveZ); 355 | float maxHeight = GetPerspectiveHeight(cam.farClipPlane); 356 | float minHeight = GetPerspectiveHeight(cam.nearClipPlane); 357 | 358 | float height = Mathf.Lerp(minHeight, maxHeight, scale); 359 | float width = height*cam.aspect; 360 | 361 | screenRenderSize.x = width; 362 | screenRenderSize.y = height; 363 | screenRenderSize *= pixelsPerUnit; 364 | } 365 | 366 | return screenRenderSize; 367 | } 368 | 369 | /// 370 | /// The integer width and height of the texture to render to 371 | /// 372 | /// 373 | protected int[] GetRenderTextureSize(Vector2 size, Vector2 aspect) 374 | { 375 | int width = Mathf.FloorToInt(Mathf.Abs(size.x / aspect.x)); 376 | int height = Mathf.FloorToInt(Mathf.Abs(size.y / aspect.y)); 377 | 378 | // Size is not integer, add padding 379 | if (Math.Abs(size.x - width) > float.Epsilon) 380 | width += 2; 381 | if (Mathf.Abs(size.y - height) > float.Epsilon) 382 | height += 2; 383 | // Make sure this isn't an odd number 384 | if (width%2 > 0) 385 | width += 1; 386 | if (height%2 > 0) 387 | height += 1; 388 | 389 | // Just in case 390 | width = Mathf.Clamp(width, 2, 4096); 391 | height = Mathf.Clamp(height, 2, 4096); 392 | 393 | return new[] {width, height}; 394 | } 395 | 396 | private void CalculateQuad(Vector2 screenRenderSize, int[] pixelRenderSize) 397 | { 398 | Vector2 pixelSize = new Vector2(pixelRenderSize[0], pixelRenderSize[1]) * zoomLevel; 399 | quadOffset = pixelSize - screenRenderSize; 400 | quadOffset /= 2; 401 | quadOffset.x /= Screen.width; 402 | quadOffset.y /= Screen.height; 403 | 404 | Vector2 min = Vector2.zero - quadOffset; 405 | Vector2 max = Vector2.one + quadOffset; 406 | if (advancedSettings == null) 407 | { 408 | QuadMin = min; 409 | QuadMax = max; 410 | return; 411 | } 412 | 413 | Vector2 aspectStretch = advancedSettings.aspectStretch; 414 | if (aspectStretch.x < float.Epsilon || aspectStretch.y < float.Epsilon) 415 | return; 416 | 417 | Vector2 center = (min + max) / 2; 418 | min -= center; 419 | max -= center; 420 | 421 | min.x *= aspectStretch.x; 422 | max.x *= aspectStretch.x; 423 | 424 | min.y *= aspectStretch.y; 425 | max.y *= aspectStretch.y; 426 | 427 | min += center; 428 | max += center; 429 | 430 | QuadMin = min; 431 | QuadMax = max; 432 | } 433 | 434 | public void ForceRefresh() 435 | { 436 | lastSettings.screenSize = new [] {0, 0}; 437 | } 438 | 439 | public bool CheckCamera() 440 | { 441 | var currentSettings = new CamSettings(this, cam); 442 | bool didChange = currentSettings.Equals(lastSettings) == false; 443 | if (didChange) 444 | SetupCamera(currentSettings); 445 | return didChange; 446 | } 447 | } 448 | } -------------------------------------------------------------------------------- /PixelCamera.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1480e3aaaeec2f144a53c656b42fa9d4 3 | timeCreated: 1488381179 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Pixel Camera 2 | 3 | A resolution independent pixel perfect camera for Unity. 4 | 5 | This package simplifies making a Unity camera render to exact pixel units, for use with pixel art or similar art styles where blockiness is part of the aesthetic. 6 | 7 | ## Features ## 8 | 9 | * Simple setup 10 | * Experimental perspective camera support 11 | 12 | *Standard unity camera* 13 | 14 | ![Standard camera](http://i.imgur.com/pye9clh.gif) 15 | 16 | *Pixel perfect camera* 17 | 18 | ![Pixel camera](http://i.imgur.com/VKhQrfu.gif) 19 | 20 | ## Installation ## 21 | 22 | Clone the repository or download the UnityPackage of the [latest release](https://github.com/ChemiKhazi/UnityPixelCamera/releases/latest). The `PixelCamera` directory can be moved to your location of choice in your unity project. 23 | 24 | ## Basic Usage ## 25 | 26 | 1. Attach the `Pixel Camera` script to an existing camera. 27 | 2. Set `Pixels Per Unit` to an appropriate value, usually matching the settings used for your assets. 28 | 3. Set the `Zoom Level` for the camera. 29 | 30 | ## Advanced Settings ## 31 | 32 | * __Camera Material__ - A material applied to the camera output, allows shaders to modify the image. The camera output is set as the `_MainTex` of the material. 33 | * __Aspect Stretch__ - Apply a stretch to the output, allows the display to be non square pixels. 34 | * __Down Sample__ - Scales down the render resolution, making the output blockier. 35 | * __Perspective Z__ - Only for perspective cameras. The Z distance between the near and far clip planes, that is rendered as pixel perfect. 36 | 37 | ## Caveats ## 38 | 39 | * If a camera or sprite is out of alignment with the pixel grid, unwanted artifacts may occur. 40 | * Pixel Camera will not automatically zoom in or out according to the window/viewport size. 41 | * Camera `Viewport Rect` settings are not taken into account. 42 | 43 | ## Perspective Camera Notes ## 44 | * A zoom level below 1 will leave a border on the edge of the screen. 45 | * Perspective camera is unoptimized. A high `Field of View` setting will generate unreasonably large RenderTextures. Use with caution. 46 | 47 | ## Technical Details ## 48 | 49 | Pixel camera takes the size of the screen and finds the render size required to cover the screen in a pixel perfect manner, at the given settings. 50 | 51 | A `RenderTexture` of the calculated render size is created, and if needed the camera settings are modified so the render fits the calculated size. 52 | 53 | The camera output is sent to the `RenderTexture`. 54 | 55 | A dummy camera that renders nothing is created, and the `OnPostRender()` function is used to draw the output of the attached camera onto the screen using GL commands. 56 | 57 | ## API ## 58 | 59 | ### Properties ### 60 | 61 | __ZoomLevel__ : float 62 | 63 | The pixel zoom scale used by the camera. 64 | 65 | __PixelsPerUnit__ : float 66 | 67 | The pixels per unit value used by the camera. 68 | 69 | __CameraMaterial__ : Material 70 | 71 | The Material used to render the camera output, setting to `null` will use the default material. Pixel Camera sets the camera output as the `_MainTex` texture of the given material. 72 | 73 | __AspectStretch__ : Vector2 74 | 75 | An additional stretch applied to the camera, allows camera to render as non square pixels. 76 | 77 | __DownSample__ : float 78 | 79 | Scales down the render resolution, makes the output blockier. Minimum value is clamped at 1. 80 | 81 | __PerspectiveZ__ : float 82 | 83 | With a perspective camera, the distance between the camera near and far planes that is rendered as pixel perfect. Value is clamped between the near and far plane values. 84 | 85 | __RenderTexture__ : RenderTexture, read only 86 | 87 | Access the RenderTexture used as the camera output. 88 | 89 | __CameraSize__ : int[], read only 90 | 91 | Actual pixel size of the camera, as an integer array. 92 | 93 | ### Methods ### 94 | 95 | __ForceRefresh()__ : void 96 | 97 | Force the camera to recalculate rendering sizes. 98 | 99 | __CheckCamera()__ : bool 100 | 101 | Checks camera settings. If different from the last camera settings used, camera will be setup again. Returns `true` when settings have changed. 102 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 97d97f703fdb57f428e07cf5469942dc 3 | timeCreated: 1488381179 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | --------------------------------------------------------------------------------