I have been trying to figure this out for my grass shader. I have it were it builds one blade of grass in a script and all the positions for it, passes that information to a shader that will than for each instance I wanted to be created will randomize the meshes rotation and convert that rotation to world space.
How ever it always seems to rotation all the blades of grass around the game object in a circle that the grass script is attached too. Can’t seem to figure out why or how this is happening. With out the rotation matrix I am using the grass blades render fine. Here is how it looks with my current attempt at a rotation matrix for the mesh:
Here is the Shader code I have so far:
Shader "Grass/GrassShader"
{
Properties
{
[MainColor] _BaseColour("Base Colour", Color) = (0, 0.5, 0, 1)
_TipColour("Tip Colour", Color) = (0, 1, 0, 1)
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline"}
LOD 100
Pass
{
Cull OFF // Don't need to cull grass, flat and need to see both sides
ZTest Less
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM //Use the newer HLSL instead of the old unity type
#pragma vertex vert //Vertex shader
#pragma fragment frag // Framant shader
// make fog work
#pragma multi_compile_fog
//Lighting and shadowing
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile_fog
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#define UNITY_PI 3.14159265359f
#define UNITY_TWO_PI 6.28318530718f
//Vertex system to pass vertices of grass blades to GPU
struct VertsIN
{
float3 position : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
};
struct FragShade
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
//Needed tyo hold all the values for the material to be used with SRP rendering and the same per pass
CBUFFER_START(UnityPerMaterial)
float4 _BaseColour;
float4 _TipColour;
StructuredBuffer<float3> grassBladePositionBuffer;
CBUFFER_END
float rand(float3 co)
{
return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
}
//rotation matrix for grass from unity.
//Rotates around to the angle provided with the axis provided
/* float3x3 angleAxis3x3(float angle, float3 axis)
{
float sina, cosa;
sincos(angle, sina, cosa);
float icosa = 1 - cosa;
float x = axis.x;
float y = axis.y;
float z = axis.z;
return float3x3(
cosa + x * x * icosa, y * x * icosa - z * sina, z *x * icosa + y * sina,
x * z * icosa + z * sina, cosa + y * y * icosa, y * z * icosa - x * sina,
x * z * icosa - y * sina, y * z * icosa + x * sina, cosa + z * z * icosa
);
}*/
float3x3 angleAxis3x3(float angle, float3 axis)
{
float c, s;
sincos(angle, s, c);
float t = 1 - c;
float x = axis.x;
float y = axis.y;
float z = axis.z;
return float3x3
(
t * x * x + c, t * x * y - s * z, t * x * z + s * y,
t * x * y + s * z, t * y * y + c, t * y * z - s * x,
t * x * z - s * y, t * y * z + s * x, t * z * z + c
);
}
FragShade vert(VertsIN IN, uint instanceID : SV_InstanceID)
{
FragShade OUT;
float3 biTangent = cross(IN.normal, IN.tangent.xyz) * IN.tangent.w; // used for tanget space calculations
//Matrix for converting the meshes vertices from its tangent space into unity world space
float3x3 tangentSpaceToLocalSpace = float3x3 (
IN.tangent.x, biTangent.x, IN.normal.x,
IN.tangent.y, biTangent.y, IN.normal.y,
IN.tangent.z, biTangent.z, IN.normal.z
);
//Take the position of the grass blade, use it as the seed for the random function and create the rotation matrix
float3x3 randomRotationMatrix = angleAxis3x3(rand(grassBladePositionBuffer[instanceID].zzx) * UNITY_TWO_PI , float3(0, 0, 1.0f));
float3x3 TransformMatrix = mul(tangentSpaceToLocalSpace, randomRotationMatrix);
//IN.position = mul(grassBladePositionBuffer[instanceID], IN.position);
IN.position += mul(TransformMatrix, IN.position);
//IN.position = IN.position + mul(UNITY_MATRIX_MVP, IN.position);
//OUT.position = TransformObjectToHClip(mul(TransformMatrix, IN.position));
VertexPositionInputs posIn = GetVertexPositionInputs(IN.position.xyz);
OUT.position = posIn.positionCS;
OUT.color = _BaseColour;
return OUT;
}
float4 frag(FragShade IN) : SV_Target
{
return _BaseColour;
}
ENDHLSL
}
}
}