A game about forced loneliness, made by TACStudios
1// Unity built-in shader source. Copyright (c) 2023 Unity Technologies. MIT license (see license.txt) 2 3#ifndef SPEEDTREE_COMMON_INCLUDED 4#define SPEEDTREE_COMMON_INCLUDED 5 6 7float3 DoLeafFacing(float3 vPos, float3 anchor) 8{ 9 float3 facingPosition = vPos - anchor; // move to origin 10 float offsetLen = length(facingPosition); 11 12 // rotate X -90deg: normals keep looking 'up' while cards/leaves now 'stand up' and face the view plane 13 facingPosition = float3(facingPosition.x, -facingPosition.z, facingPosition.y); 14 15 // extract scale from model matrix 16 float3x3 modelMatrix = (float3x3) GetObjectToWorldMatrix(); // UNITY_MATRIX_M 17 float3 scale = float3( 18 length(float3(modelMatrix[0][0], modelMatrix[1][0], modelMatrix[2][0])), 19 length(float3(modelMatrix[0][1], modelMatrix[1][1], modelMatrix[2][1])), 20 length(float3(modelMatrix[0][2], modelMatrix[1][2], modelMatrix[2][2])) 21 ); 22 23 // inverse of model : discards object rotations & scale 24 // inverse of view : discards camera rotations 25 float3x3 modelMatrixInv = (float3x3) GetWorldToObjectMatrix(); // UNITY_MATRIX_I_M 26 float3x3 viewMatrixInv = (float3x3) GetViewToWorldMatrix(); // UNITY_MATRIX_I_V 27 float3x3 matCardFacingTransform = mul(modelMatrixInv, viewMatrixInv); 28 29 // re-encode the scale into the final transformation (otherwise cards would look small if tree is scaled up via world transform) 30 matCardFacingTransform[0] *= scale.x; 31 matCardFacingTransform[1] *= scale.y; 32 matCardFacingTransform[2] *= scale.z; 33 34 // make the leaves/cards face the camera 35 facingPosition = mul(matCardFacingTransform, facingPosition.xyz); 36 facingPosition = normalize(facingPosition) * offsetLen; // make sure the offset vector is still scaled 37 38 return facingPosition + anchor; // move back to branch 39} 40 41#define SPEEDTREE_SUPPORT_NON_UNIFORM_SCALING 0 42float3 TransformWindVectorFromWorldToLocalSpace(float3 vWindDirection) 43{ 44 // we intend to transform the world-space wind vector into local space. 45 float3x3 modelMatrixInv = (float3x3) GetWorldToObjectMatrix(); // UNITY_MATRIX_I_M 46#if SPEEDTREE_SUPPORT_NON_UNIFORM_SCALING 47 // the inverse world matrix would contain scale transformation as well, so we need 48 // to get rid of scaling of the wind direction while doing inverse rotation. 49 float3x3 modelMatrix = (float3x3) GetObjectToWorldMatrix(); // UNITY_MATRIX_M 50 float3 scaleInv = float3( 51 length(float3(modelMatrix[0][0], modelMatrix[1][0], modelMatrix[2][0])), 52 length(float3(modelMatrix[0][1], modelMatrix[1][1], modelMatrix[2][1])), 53 length(float3(modelMatrix[0][2], modelMatrix[1][2], modelMatrix[2][2])) 54 ); 55 float3x3 matWorldToLocalSpaceRotation = float3x3( // 3x3 discards translation 56 modelMatrixInv[0][0] * scaleInv.x, modelMatrixInv[0][1] , modelMatrixInv[0][2], 57 modelMatrixInv[1][0] , modelMatrixInv[1][1] * scaleInv.y, modelMatrixInv[1][2], 58 modelMatrixInv[2][0] , modelMatrixInv[2][1] , modelMatrixInv[2][2] * scaleInv.z 59 ); 60 float3 vLocalSpaceWind = mul(matWorldToLocalSpaceRotation, vWindDirection); 61#else 62 // Assume uniform scaling for the object -- discard translation and invert object rotations (and scale). 63 // We'll normalize to get rid of scaling after the transformation. 64 float3 vLocalSpaceWind = mul(modelMatrixInv, vWindDirection); 65#endif 66 float windVecLength = length(vLocalSpaceWind); 67 if (windVecLength > 1e-5) 68 vLocalSpaceWind *= (1.0f / windVecLength); // normalize 69 return vLocalSpaceWind; 70} 71 72#define ST_GEOM_TYPE_BRANCH 0 73#define ST_GEOM_TYPE_FROND 1 74#define ST_GEOM_TYPE_LEAF 2 75#define ST_GEOM_TYPE_FACINGLEAF 3 76int GetGeometryType(float4 uv3, out bool bLeafTwo) 77{ 78 int geometryType = (int) (uv3.w + 0.25); 79 bLeafTwo = geometryType > ST_GEOM_TYPE_FACINGLEAF; 80 if (bLeafTwo) 81 { 82 geometryType -= 2; 83 } 84 return geometryType; 85} 86 87// shadergraph stubs 88void SpeedTree8LeafFacing_float(float3 vVertexLocalPosition, float4 UV1, float4 UV2, float4 UV3, out float3 vVertexLocalPositionOut) 89{ 90 vVertexLocalPositionOut = vVertexLocalPosition; 91 bool bDummy = false; 92 if (GetGeometryType(UV3, bDummy) == ST_GEOM_TYPE_FACINGLEAF) 93 { 94 float3 vAnchorPosition = float3(UV1.zw, UV2.w); 95 vVertexLocalPositionOut = DoLeafFacing(vVertexLocalPosition, vAnchorPosition); 96 } 97} 98void SpeedTree9LeafFacing_float(float3 vVertexLocalPosition, float4 UV2, float4 UV3, out float3 vVertexLocalPositionOut) 99{ 100 vVertexLocalPositionOut = vVertexLocalPosition; 101 const bool bHasCameraFacingLeaf = UV3.w > 0.0f || UV2.w > 0.0f; 102 if (bHasCameraFacingLeaf) 103 { 104 const float3 vAnchorPosition = UV3.w > 0.0f ? UV3.xyz : UV2.xyz; 105 vVertexLocalPositionOut = DoLeafFacing(vVertexLocalPosition, vAnchorPosition); 106 } 107} 108 109void SpeedTreeLODTransition_float(float3 ObjectSpacePosition, float4 ObjectSpacePositionNextLOD, const bool bBillboard, out float3 OutObjectSpacePosition) 110{ 111 OutObjectSpacePosition = bBillboard 112 ? ObjectSpacePosition 113 : lerp(ObjectSpacePosition, ObjectSpacePositionNextLOD.xyz, unity_LODFade.x); 114} 115 116#endif // SPEEDTREE_COMMON_INCLUDED