// 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 grassBuffer; StructuredBuffer inGrassBuffer;//ConsumeStructuredBuffer 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" }