186 lines
6.3 KiB
GLSL
186 lines
6.3 KiB
GLSL
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
|
|
|
|
Shader "DBV/Kristo/InstancedConsumeGrassShader"
|
|
{
|
|
Properties {
|
|
_MainTex("Main tex", 2D) = "white" {}
|
|
_Glossiness("Smoothness", Range(0,1)) = 0.5
|
|
_Metallic("Metallic", Range(0,1)) = 0.0
|
|
|
|
[Space]
|
|
_ColorA("Color A", Color) = (1,1,1,1)
|
|
_ColorB("Color B", Color) = (1,1,1,1)
|
|
|
|
[Space]
|
|
_Size("Size",float) = 1
|
|
_Height("Height",float) = 1
|
|
|
|
[Space]
|
|
_WindTex("Wind tex", 2D) = "grey" {}
|
|
_WindAmount("Wind strength", float) = 1
|
|
_WindSize("Wind size", float) = 1
|
|
_WindSpeed("Wind speed", float) = 1
|
|
|
|
[Space]
|
|
_AlphaCutoff ("Alpha cutoff", Range(0,1)) = 0.05
|
|
_DitherTex ("Dither tex.", 2D) = "white" {}
|
|
|
|
fadeStartDist ("Fade start",float) = 1
|
|
fadeEndDist ("Fade end",float) = 1
|
|
}
|
|
SubShader
|
|
{
|
|
Tags { "RenderType"="Instanced" }
|
|
LOD 200
|
|
Cull Off
|
|
//ZWrite Off
|
|
|
|
CGPROGRAM
|
|
#pragma surface surf BlinnPhong vertex:vert noshadowmask nodynlightmap nodirlightmap nolightmap noshadow
|
|
#pragma multi_compile_instancing
|
|
#pragma instancing_options procedural:setup
|
|
|
|
#pragma target 4.5
|
|
|
|
sampler2D _MainTex, _DitherTex, _WindTex;
|
|
fixed4 _DitherTex_TexelSize, _WindTex_TexelSize;
|
|
|
|
struct Input{
|
|
float2 uv_MainTex;
|
|
float4 screenPos;
|
|
float3 worldPos;
|
|
};
|
|
|
|
struct GrassElement {
|
|
float3 position;
|
|
float rotation;
|
|
float size;
|
|
float colorBlend;//0-1
|
|
};
|
|
|
|
struct custom_appdata {
|
|
float4 vertex : POSITION;
|
|
float3 normal : NORMAL;
|
|
float4 texcoord : TEXCOORD0;
|
|
float4 texcoord1 : TEXCOORD1;
|
|
float4 texcoord2 : TEXCOORD2;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
//Note
|
|
//StructuredBuffers are good when there are loads of data that needs to be read at different places by different threads
|
|
//Constant buffers are good when there isent too much data and threads read the same dat
|
|
|
|
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
|
|
StructuredBuffer<GrassElement> grassBuffer;
|
|
StructuredBuffer<uint> inGrassBuffer;//ConsumeStructuredBuffer<uint> inGrassBuffer;
|
|
#endif
|
|
|
|
|
|
//https://forum.unity.com/threads/rotating-mesh-in-vertex-shader.501709/
|
|
float3x3 YRotationMatrix(float degrees) {
|
|
float alpha = degrees * UNITY_PI / 180.0;
|
|
float sina, cosa;
|
|
sincos(alpha, sina, cosa);
|
|
return float3x3(
|
|
cosa, 0, -sina,
|
|
0, 1, 0,
|
|
sina, 0, cosa);
|
|
}
|
|
//USAGE: pos.xyz = mul(YRotationMatrix(degrees),pos.xyz);
|
|
|
|
//void rotate2D(inout float2 v, float r) {
|
|
// float s, c;
|
|
// sincos(r, s, c);
|
|
// v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
|
|
// }
|
|
|
|
half _Glossiness;
|
|
half _Metallic;
|
|
fixed4 _ColorA, _ColorB;
|
|
float _AlphaCutoff, _Size, _Height;
|
|
|
|
float fadeStartDist, fadeEndDist, _WindAmount, _WindSize, _WindSpeed;
|
|
|
|
//float3 pos;
|
|
float colorBlend;
|
|
float rotationInDegrees;
|
|
|
|
void setup () {
|
|
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
|
|
uint index = inGrassBuffer[unity_InstanceID];//inGrassBuffer.Consume();//Consume buffer is not working at all for some reason
|
|
GrassElement data = grassBuffer[index];//unity_InstanceID
|
|
|
|
//save data
|
|
float3 pos = data.position.xyz;
|
|
colorBlend = data.colorBlend;
|
|
rotationInDegrees = data.rotation;
|
|
|
|
//Scale the mesh
|
|
float size = _Size * data.size;
|
|
unity_ObjectToWorld._11_21_31_41 = float4(size, 0, 0, 0);
|
|
unity_ObjectToWorld._12_22_32_42 = float4(0, size*_Height, 0, 0);
|
|
unity_ObjectToWorld._13_23_33_43 = float4(0, 0, size, 0);
|
|
|
|
//position the mesh
|
|
unity_ObjectToWorld._14_24_34_44 = float4(pos, 1);
|
|
|
|
//No idea what this does but it must be important
|
|
unity_WorldToObject = unity_ObjectToWorld;
|
|
unity_WorldToObject._14_24_34 *= -1;
|
|
unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
|
|
#else
|
|
//pos = float3(0,2,0);
|
|
colorBlend = 0.5;
|
|
rotationInDegrees = 45;
|
|
#endif
|
|
}
|
|
|
|
void vert (inout custom_appdata v) {
|
|
//Rotate
|
|
v.vertex.xyz = mul(YRotationMatrix(rotationInDegrees),v.vertex);
|
|
|
|
//Do wind
|
|
float vertexHeight = v.vertex.y;
|
|
|
|
float3 worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
|
|
float2 windCoord = (worldPos.xz)*_WindSize + (_Time.yy)*_WindSpeed;
|
|
float3 wind = (tex2Dlod(_WindTex,float4(windCoord.xy,0,0)*2 - 1 )).xyz * _WindAmount;//tex2D(_WindTex, windCoord).rgb * vertexHeight;
|
|
|
|
v.vertex.xyz += float3(wind.x-0.5,0,wind.z) * vertexHeight;
|
|
}
|
|
|
|
void surf (Input IN, inout SurfaceOutput o) {
|
|
//Get color
|
|
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
|
|
|
|
//Do cutout
|
|
clip(c.a - _AlphaCutoff);
|
|
|
|
//Do dithering
|
|
float2 screenPos = IN.screenPos.xy / IN.screenPos.w;
|
|
float2 ditherCoord = screenPos * _ScreenParams.xy * _DitherTex_TexelSize.xy;
|
|
float ditherAmount = tex2D(_DitherTex, ditherCoord).r;
|
|
|
|
float distToCamera = distance(IN.worldPos, _WorldSpaceCameraPos);
|
|
if(distToCamera > fadeStartDist) {
|
|
float ditherRange = 1 - saturate((distToCamera-fadeStartDist)/(fadeEndDist-fadeStartDist));
|
|
clip(ditherRange - ditherAmount);
|
|
}
|
|
|
|
//Do blending
|
|
fixed4 col = colorBlend * _ColorA + (1-colorBlend) * _ColorB;
|
|
|
|
// Albedo comes from a texture tinted by color
|
|
c = c * col;
|
|
o.Albedo = c.rgb;
|
|
// Metallic and smoothness come from slider variables
|
|
//o.Metallic = _Metallic;
|
|
//o.Smoothness = _Glossiness;
|
|
//o.Alpha = c.a;
|
|
}
|
|
ENDCG
|
|
}
|
|
FallBack "Diffuse"
|
|
}
|