,Help Changing a "Doom" Style Billboard Shader to a Surface Shader
I'm currently learning more about surface shaders and their differences from Vertex and Frag Shaders, because I am trying to change my shader that creates a "2.D" rotational billboarding sprite to a surface shader so I can add normals, a shadow ect. to the sprite. The current vert and frag shader works by calculating the rotation angle of the billboard and using that data to UV offset the tilesheet I made of sprites to the appropriate angled sprite so it has a 3d effect! It also animates using the columns of this tilesheet as well.
I am having NO LUCK converting it to a Surface Shader appropriately. I have no errors but all I get so far is just the Tilesheet billboarding, no UV offsets and I don't even know if it is using the angle data that it is being fed! ANY help would be appreciated I cannot figure this one out!
here is the original Shader
Shader "UnityCoder/Doom2"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_Frames ("Frames (rows)", Float) = 13
_Columns ("Columns", Float) = 4
_AnimSpeed ("Animation Speed", Float) = 1
_ScaleX ("Scale X", Float) = 1.0
_ScaleY ("Scale Y", Float) = 1.0
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define PI 3.1415926535897932384626433832795
#define RAD2DEG 57.2958
#define SINGLEFRAMEANGLE (360/_Frames)
#define UVOFFSETX (1/_Frames)
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform float _ScaleX;
uniform float _ScaleY;
struct appdata {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
};
// float4x4 _CameraToWorld;
float _Frames;
float _Columns;
float _AnimSpeed;
float2 atan2Approximation(float2 y, float2 x) // http://http.developer.nvidia.com/Cg/atan2.html
{
float2 t0, t1, t2, t3, t4;
t3 = abs(x);
t1 = abs(y);
t0 = max(t3, t1);
t1 = min(t3, t1);
t3 = float(1) / t0;
t3 = t1 * t3;
t4 = t3 * t3;
t0 = - float(0.013480470);
t0 = t0 * t4 + float(0.057477314);
t0 = t0 * t4 - float(0.121239071);
t0 = t0 * t4 + float(0.195635925);
t0 = t0 * t4 - float(0.332994597);
t0 = t0 * t4 + float(0.999995630);
t3 = t0 * t3;
t3 = (abs(y) > abs(x)) ? float(1.570796327) - t3 : t3;
t3 = (x < 0) ? float(3.141592654) - t3 : t3;
t3 = (y < 0) ? -t3 : t3;
return t3;
}
v2f vert (appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0, 0, 0, 1)) + float4(v.vertex.x, v.vertex.y, 0, 0)* float4(_ScaleX, _ScaleY, 1.0, 1.0)) ;
// get direction
float3 cameraUp = UNITY_MATRIX_IT_MV[1].xyz;
float3 cameraForward = normalize(UNITY_MATRIX_IT_MV[2].xyz);
float3 towardsRight = normalize(cross(cameraUp, cameraForward));
// get angle & current frame
float angle = (atan2Approximation(towardsRight.z,towardsRight.x)*RAD2DEG) % 360;
int index = angle/SINGLEFRAMEANGLE;
// animated frames
float animFrame= _Columns-(1+round(_Time.y*_AnimSpeed) % _Columns);
// set uv to display current frame
o.uv = float2(v.texcoord.x*UVOFFSETX+UVOFFSETX*index,(v.texcoord.y+animFrame)/_Columns);
// billboard towards camera
float3 vpos=mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);
float4 worldCoord=float4(unity_ObjectToWorld._m03,unity_ObjectToWorld._m13,unity_ObjectToWorld._m23,1);
float4 viewPos=mul(UNITY_MATRIX_V,worldCoord)+float4(vpos,0);
float4 outPos=mul(UNITY_MATRIX_P,viewPos);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return tex2D(_MainTex,i.uv);
}
ENDCG
}
}
}
and here is the Surface Shader I am currently trying to create from it:
Shader "TestShader/Billboard" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_Frames ("Frames (rows)", Float) = 13
_Columns ("Columns", Float) = 4
_AnimSpeed ("Animation Speed", Float) = 1
_ScaleX ("Scale X", Float) = 1.0
_ScaleY ("Scale Y", Float) = 1.0
}
SubShader {
Tags { "Queue"="Transparent" "RenderType"="TransparentCutout" "DisableBatching"="True" }
LOD 200
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Lambert addshadow vertex:vert alphatest:_Cutoff
#define PI 3.1415926535897932384626433832795
#define RAD2DEG 57.2958
#define SINGLEFRAMEANGLE (360/_Frames)
#define UVOFFSETX (1/_Frames)
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform float _ScaleX;
uniform float _ScaleY;
struct Input {
float4 pos : SV_POSITION;
half2 uv_MainTex :TEXCOORD0;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
float _Frames;
float _Columns;
float _AnimSpeed;
float2 atan2Approximation(float2 y, float2 x) // http://http.developer.nvidia.com/Cg/atan2.html
{
float2 t0, t1, t2, t3, t4;
t3 = abs(x);
t1 = abs(y);
t0 = max(t3, t1);
t1 = min(t3, t1);
t3 = float(1) / t0;
t3 = t1 * t3;
t4 = t3 * t3;
t0 = - float(0.013480470);
t0 = t0 * t4 + float(0.057477314);
t0 = t0 * t4 - float(0.121239071);
t0 = t0 * t4 + float(0.195635925);
t0 = t0 * t4 - float(0.332994597);
t0 = t0 * t4 + float(0.999995630);
t3 = t0 * t3;
t3 = (abs(y) > abs(x)) ? float(1.570796327) - t3 : t3;
t3 = (x < 0) ? float(3.141592654) - t3 : t3;
t3 = (y < 0) ? -t3 : t3;
return t3;
}
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
o.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0, 0, 0, 1)) + float4(v.vertex.x, v.vertex.y, 0, 0)* float4(_ScaleX, _ScaleY, 1.0, 1.0)) ;
// get the camera basis vectors
float3 cameraUp = normalize(UNITY_MATRIX_V._m10_m11_m12);
float3 cameraForward = -normalize(UNITY_MATRIX_V._m20_m21_m22);
float3 towardsRight = normalize(cross(cameraUp, cameraForward));
// get angle & current frame
float angle = (atan2Approximation(towardsRight.z,towardsRight.x)*RAD2DEG) % 360;
int index = angle/SINGLEFRAMEANGLE;
// billboard towards camera
float4x4 rotationMatrix = float4x4(towardsRight, 0,
cameraUp, 0,
cameraForward, 0,
0, 0, 0, 1);
v.vertex = mul(v.vertex, rotationMatrix);
v.normal = mul(v.normal, rotationMatrix);
// animated frames
float animFrame= _Columns-(1+round(_Time.y*_AnimSpeed) % _Columns);
// set uv to display current frame
o.uv_MainTex = float2(v.texcoord.x*UVOFFSETX+UVOFFSETX*index,(v.texcoord.y+animFrame)/_Columns);
// undo object to world transform surface shader will apply
v.vertex.xyz = mul((float3x3)unity_WorldToObject, v.vertex.xyz);
v.normal = mul(v.normal, (float3x3)unity_ObjectToWorld);
}
void surf (Input IN, inout SurfaceOutput o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
}