I am writing a shader for a particle billboard. I am making it look like those retro styled doom sprites, where it shows a different sprite depending on which side you are looking at it. So far I have been able to make it look the way I wanted it to.
Now I seem to have reached the problem where I forgot to think about if I want to rotate the object, it always “looks” the same direction. In other words I forgot to include the object rotation, but I have no idea how. Currently I calculate rotation like this
// from object to camera direction; in world space
float3 cameraDirection = -1 * mul((float3x3)unity_ObjectToWorld, transpose(mul(unity_WorldToObject, unity_MatrixInvV)) [2].xyz);
// Rotate cameraDirection about axis, to simulate spinning
vector <float, 3> rotatedTransform;
RotateAboutAxis_Radians_float(cameraDirection, float3(0, 1, 0), rotateAmount, rotatedTransform);
// Rotation towards ??? (I'm guessing (0, 0, 1) in world space) in radians
float artanned = atan2(rotatedTransform.x, rotatedTransform.z);
My rotate amount is just calculated with _Time like this float animation = floor((_Time * _Fps) % _AnimFrameCount);
I use all this information to map it to a sprite sheet with a flipbook.
How would I go about getting the object world space rotation so I can += onto the rotateAmount?
I am very new to shader programming so here is my entire shader
Shader "Bjørn/Directional Particle"
{
Properties
{
[NoScaleOffset] _MainTex ("Sprite Sheet", 2D) = "white" {}
_AnimFrameCount ("Animation Frame Count", int) = 1
_SideCount ("Side count", int) = 8
_Fps ("Fps", int) = 5
[Toggle] _Rotate ("Rotate", Float) = 0
_RotateSpeed ("Rotate Speed", Float) = 1
}
SubShader
{
Tags { "RenderType"="Transparent" "DisableBatching"="True" }
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
Cull Back
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma exclude_renderers gles xbox360 ps3
#pragma exclude_renderers gles xbox360 ps3
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
void Flipbook_float(float2 UV, float Width, float Height, float Tile, float2 Invert, out float2 Out)
{
Tile = fmod(Tile, Width * Height);
float2 tileCount = float2(1.0, 1.0) / float2(Width, Height);
float tileY = abs(Invert.y * Height - (floor(Tile * tileCount.x) + Invert.y * 1));
float tileX = abs(Invert.x * Width - ((Tile - Width * floor(Tile * tileCount.x)) + Invert.x * 1));
Out = (UV + float2(tileX, tileY)) * tileCount;
}
void Remap_float(float In, float2 InMinMax, float2 OutMinMax, out float Out)
{
Out = OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x);
}
void RotateAboutAxis_Radians_float(float3 In, float3 Axis, float Rotation, out float3 Out)
{
float s = sin(Rotation);
float c = cos(Rotation);
float one_minus_c = 1.0 - c;
Axis = normalize(Axis);
float3x3 rot_mat =
{ one_minus_c * Axis.x * Axis.x + c, one_minus_c * Axis.x * Axis.y - Axis.z * s, one_minus_c * Axis.z * Axis.x + Axis.y * s,
one_minus_c * Axis.x * Axis.y + Axis.z * s, one_minus_c * Axis.y * Axis.y + c, one_minus_c * Axis.y * Axis.z - Axis.x * s,
one_minus_c * Axis.z * Axis.x - Axis.y * s, one_minus_c * Axis.y * Axis.z + Axis.x * s, one_minus_c * Axis.z * Axis.z + c
};
Out = mul(rot_mat, In);
}
int _AnimFrameCount;
int _SideCount;
int _Fps;
bool _Rotate;
float _RotateSpeed;
fixed4 frag (v2f i) : SV_Target
{
float animation = floor((_Time * _Fps) % _AnimFrameCount);
// Rotate amount
float rotateAmount;
if (_Rotate == 1)
{
rotateAmount = _RotateSpeed * _Time;
}
else if (_Rotate == 0)
{
rotateAmount = 0;
}
// from object to camera direction; in world space
float3 cameraDirection = -1 * mul((float3x3)unity_ObjectToWorld, transpose(mul(unity_WorldToObject, unity_MatrixInvV)) [2].xyz);
// Rotate cameraDirection about axis, to simulate spinning
vector <float, 3> rotatedTransform;
RotateAboutAxis_Radians_float(cameraDirection, float3(0, 1, 0), rotateAmount, rotatedTransform);
// Rotation towards ??? (I'm guessing (0, 0, 1) in world space) in radians
float artanned = atan2(rotatedTransform.x, rotatedTransform.z);
// Map direction to spritesheet position
float remappedAngle;
Remap_float(atan2(rotatedTransform.x, rotatedTransform.z), float2 (-3.141593, 3.141593), float2 (1, 0), remappedAngle);
float direction = _AnimFrameCount * round(_SideCount * remappedAngle);
// Sprite sheet sample
float tile = animation + direction;
float2 flipbookUV;
Flipbook_float(i.uv, _AnimFrameCount, _SideCount, tile , float2 (0, 1 ), flipbookUV);
fixed4 col = tex2D(_MainTex, flipbookUV);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}