Last active
August 10, 2019 21:00
-
-
Save Lunchbox4K/20e061241f0e89a4969a64574d0fac9e to your computer and use it in GitHub Desktop.
Unity Component Based Instanced Sprite Sheet Renderer (2019.1) Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************************************************************** | |
* Unity ECS - Test/Sample Code | |
* Mitchell Pell | |
* 2019.07.26 | |
* v0.1 | |
*********************************************************************/ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using Unity.Entities; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Transforms; | |
using Unity.Mathematics; | |
using Unity.Rendering; | |
//--------------------------------------------------------------------- | |
public class GameHandlerSpriteSheetRenderer : MonoBehaviour | |
{ | |
//Enable/Disable sprite sheet animation test | |
[SerializeField] private bool createAnimatedSpriteSheet; | |
[SerializeField] private float animationFrameTime; | |
//Lazy code to get the quad mesh and sprite sheet material. | |
private static GameHandlerSpriteSheetRenderer s_instance; | |
public static GameHandlerSpriteSheetRenderer GetInstance() { return s_instance; } | |
//Mesh assigned in the editor that the SpriteSheetRenderer grabs. | |
public Mesh quadMesh; | |
//Sprite sheet material assigned in the editor that the SpriteSheetRenderer grabs. | |
public Material spriteSheetMaterial; | |
private void Awake() | |
{ | |
/* Lazy code setting the instance of this class with quadMesh | |
* and spriteSheetMaterial defined. */ | |
s_instance = this; | |
/* Get the Entity Manager and create a new Translation Entity | |
that the SpriteSheetRenderer will use to draw the Sprite. */ | |
EntityManager entityManager = World.Active.EntityManager; | |
if (createAnimatedSpriteSheet) | |
{ | |
AnimatedInstancedSpriteSheetTest(entityManager); | |
} | |
} | |
/// | |
/// Animated Sprite Sprite Test using Instanced UV and the ECS system. | |
/// | |
private void AnimatedInstancedSpriteSheetTest(EntityManager entityManager) | |
{ | |
EntityArchetype spriteArchType = entityManager.CreateArchetype( | |
// SpriteSheetRendere | |
typeof(Translation), | |
// SpriteSheetAnimationSystem | |
typeof(SpriteSheetAnimation_Data) | |
); | |
Entity sprite = entityManager.CreateEntity(spriteArchType); | |
//Set | |
entityManager.SetComponentData(sprite, | |
new Translation | |
{ | |
Value = new float3(0, 0, 0) | |
} | |
); | |
//Set | |
if (animationFrameTime <= 0) animationFrameTime = 0.2f; | |
entityManager.SetComponentData(sprite, | |
new SpriteSheetAnimation_Data | |
{ | |
m_frameTimer = 0f, | |
m_frameTimerMax = animationFrameTime, | |
m_startFrameX = 0, | |
m_startFrameY = 0, | |
m_endFrameX = 0, | |
m_endFrameY = 24, | |
m_currentFrameX = 0, | |
m_currentFrameY = 0, | |
} | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Custom/InstancedSpriteSheetShader" | |
{ | |
Properties | |
{ | |
_MainTex ("Texture", 2D) = "white" {} | |
_MainTex_UV ("Texture UV", Vector) = (1.000,1.000,0.000,0.000) | |
_Color ("Color", Color) = (1,1,1,1) | |
} | |
SubShader | |
{ | |
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } | |
LOD 100 | |
Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#pragma multi_compile_instancing | |
#include "UnityCG.cginc" | |
//Received Application Data Struct | |
struct appdata | |
{ | |
float4 vertex : POSITION; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
float2 uv : TEXCOORD0; | |
}; | |
//Vertex Struct | |
struct v2f | |
{ | |
float2 uv : TEXCOORD0; | |
float4 vertex : SV_POSITION; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
}; | |
//Full floating point support with sampler2D_float. | |
sampler2D_float _MainTex; | |
// Set Potential Incomming Instancing Instanced Properties | |
//------------------------- | |
UNITY_INSTANCING_BUFFER_START(Props) | |
//Instanced Color | |
UNITY_DEFINE_INSTANCED_PROP(float4, _Color) | |
//Instanced UV Coordinates ( Animations, SpriteSheets, etc.) | |
UNITY_DEFINE_INSTANCED_PROP(float4, _MainTex_UV) | |
UNITY_INSTANCING_BUFFER_END(Props) | |
// Vertex Shader | |
v2f vert(appdata v) | |
{ | |
v2f o; //Vertex Struct | |
//Instancing | |
UNITY_SETUP_INSTANCE_ID(v); | |
UNITY_TRANSFER_INSTANCE_ID(v, o); | |
//Get Vertex Data from Application | |
o.vertex = UnityObjectToClipPos(v.vertex); | |
//Calculate UV | |
//------------------------ | |
//o.uv = v.uv; // Entire Texture is applied i.e. {1,1,0,0} | |
//Calculate UV Coordinates from Instancded Application Data | |
o.uv = (v.uv * UNITY_ACCESS_INSTANCED_PROP(Props, _MainTex_UV).xy) + | |
UNITY_ACCESS_INSTANCED_PROP(Props, _MainTex_UV).zw; | |
//------------------------ | |
//Return Vertex Struct to the Fragment Shader. | |
return o; | |
} | |
// Fragment Shader | |
fixed4 frag(v2f i) : SV_Target | |
{ | |
UNITY_SETUP_INSTANCE_ID(i); | |
return (tex2D(_MainTex, i.uv) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color)); | |
//return UNITY_ACCESS_INSTANCED_PROP(Props, _Color); | |
} | |
ENDCG | |
} | |
} | |
} | |
// Resources Used: | |
// https://docs.unity3d.com/Manual/SL-Blend.html | |
// https://docs.unity3d.com/Manual/GPUInstancing.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************************************************************** | |
* Unity ECS - Test/Sample Code | |
* Mitchell Pell | |
* 2019.07.26 | |
* v0.1 | |
*********************************************************************/ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using Unity.Entities; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Transforms; | |
/// | |
/// Animation Frame Component Data. | |
/// | |
public struct SpriteSheetAnimation_Data : IComponentData | |
{ | |
public int m_currentFrameX; | |
public int m_currentFrameY; | |
public int m_startFrameX; | |
public int m_endFrameX; | |
public int m_startFrameY; | |
public int m_endFrameY; | |
public float m_frameTimer; | |
public float m_frameTimerMax; | |
} | |
/// | |
/// Animation System to update animation frames. | |
/// | |
public class SpriteSheetAnimationSystem : JobComponentSystem | |
{ | |
[BurstCompile] | |
public struct Job : IJobForEach<SpriteSheetAnimation_Data> | |
{ | |
public float deltaTime; | |
public void Execute( | |
ref SpriteSheetAnimation_Data spriteSheetAnimationData) { | |
spriteSheetAnimationData.m_frameTimer += deltaTime; | |
while ( spriteSheetAnimationData.m_frameTimer >= | |
spriteSheetAnimationData.m_frameTimerMax) | |
{ | |
spriteSheetAnimationData.m_frameTimer -= | |
spriteSheetAnimationData.m_frameTimerMax; | |
if (++spriteSheetAnimationData.m_currentFrameX > | |
spriteSheetAnimationData.m_endFrameX) | |
spriteSheetAnimationData.m_currentFrameX = | |
spriteSheetAnimationData.m_startFrameX; | |
if (++spriteSheetAnimationData.m_currentFrameY > | |
spriteSheetAnimationData.m_endFrameY) | |
spriteSheetAnimationData.m_currentFrameY = | |
spriteSheetAnimationData.m_startFrameY; | |
} | |
} | |
} | |
protected override JobHandle OnUpdate(JobHandle inputDeps) | |
{ | |
Job jo = new Job { deltaTime = Time.deltaTime }; | |
return jo.Schedule(this, inputDeps); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/********************************************************************** | |
* Unity ECS - Test/Sample Code | |
* Mitchell Pell | |
* 2019.07.26 | |
* v0.1 | |
*********************************************************************/ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using Unity.Entities; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Transforms; | |
/* | |
* Renders Sprites using Instanced UV Data | |
* | |
*/ | |
[UpdateAfter(typeof(SpriteSheetAnimationSystem))] | |
public class SpriteSheetRenderer : ComponentSystem | |
{ | |
public const float UV_UNIT = (1.0f / 4096); | |
public const float UV_TILE_W = (UV_UNIT * 32); | |
public const float UV_TILE_H = (UV_UNIT * 32); | |
public const int UV_TILE_ROWS = 64; | |
public const int UV_TILE_COLS = 96; | |
public static readonly Vector4 UV_START = new Vector4( | |
UV_TILE_W * 16, // W | |
UV_TILE_H * 8, // H | |
0f, // X | |
UV_TILE_H * 42); // Y | |
protected MaterialPropertyBlock m_materialPropertyBlock; | |
protected Vector4[] m_materialBlockMainTexUVArray; | |
protected override void OnCreateManager() { | |
base.OnCreateManager(); | |
m_materialBlockMainTexUVArray = new Vector4[1]; | |
m_materialBlockMainTexUVArray[0] = UV_START; | |
m_materialPropertyBlock = new MaterialPropertyBlock(); | |
} | |
protected override void OnUpdate() { | |
Entities.ForEach( | |
// [ For Each Filter ] | |
( | |
ref Translation translation, | |
ref SpriteSheetAnimation_Data spriteSheetAnimationData | |
// [ For Each Method ] | |
) => { | |
//Get the UV Coordinates based on animation system. | |
m_materialBlockMainTexUVArray[0].z = UV_START.z + (UV_TILE_W * spriteSheetAnimationData.m_currentFrameX); | |
m_materialBlockMainTexUVArray[0].w = UV_START.w + (UV_TILE_H * spriteSheetAnimationData.m_currentFrameY); | |
//Add the UV coordinates to the material property block. | |
m_materialPropertyBlock.SetVectorArray("_MainTex_UV", m_materialBlockMainTexUVArray); | |
//Set transform matrix | |
Matrix4x4 transform = Matrix4x4.identity; | |
transform *= Matrix4x4.Scale(new Vector3(8, 4, 1)); | |
//Render the sprite. | |
Graphics.DrawMesh( | |
// Mesh | |
GameHandlerSpriteSheetRenderer.GetInstance().quadMesh, | |
// Transform | |
transform, | |
// Material | |
GameHandlerSpriteSheetRenderer.GetInstance().spriteSheetMaterial, | |
//Layer | |
0, | |
Camera.main, | |
//Submesh index | |
0, | |
m_materialPropertyBlock | |
); | |
} | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment