Skip to content

Commit

Permalink
Add ClumpedPositionInput support and bladeUp Vector correction toward…
Browse files Browse the repository at this point in the history
…s sunlight
  • Loading branch information
nicoell committed Jan 23, 2018
1 parent 6ecae4c commit 25563a0
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 27 deletions.
7 changes: 7 additions & 0 deletions Assets/Scripts/GrassSimulation/Core/Inputs/PositionInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,12 @@ public abstract class PositionInput : ScriptableObject
/// <returns>A Vector2 where x:x and y:z with each element in range 0..1</returns>
/// <param name="id">The index at which the position will be placed in the UvBuffer</param>
public abstract Vector2 GetPosition(int id);

/// <summary>
/// <para>Gets the number of positions that are consecutively very similar, e.g. in clumped grass.</para>
/// </summary>
/// <returns>A unsigned int number of the repetition count. If no positions are similar, this should be 1.</returns>
/// <remarks>This is needed to avoid clumping billboard grass.</remarks>
public abstract uint GetRepetitionCount();
}
}
25 changes: 23 additions & 2 deletions Assets/Scripts/GrassSimulation/Core/Lod/GrassPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class GrassPatch : Patch
private bool _applyTransition;
private Mesh _dummyMesh;
private Mesh _dummyMeshBillboardCrossed;
private Mesh _dummyMeshBillboardScreen;
private Bounds _inputBounds;
private Texture2D _normalHeightTexture;

Expand Down Expand Up @@ -67,8 +68,10 @@ public GrassPatch(SimulationContext ctx, Vector4 patchTexCoord, Bounds bounds) :
Bounds = boundsCorrected;
//_boundsVertices = new Bounds.BoundsVertices(bounds);
_patchTexCoord = patchTexCoord;
var maxElementsUsed = Mathf.Max(Ctx.Settings.GetMaxAmountBladesPerPatch(),
Ctx.Settings.GetMinAmountBillboardsPerPatch() * 3 * Ctx.PositionInput.GetRepetitionCount());
_startIndex = Ctx.Random.Next(0,
(int) (Ctx.Settings.GetSharedBufferLength() - Ctx.Settings.GetMaxAmountBladesPerPatch()));
(int) (Ctx.Settings.GetSharedBufferLength() - maxElementsUsed));
_materialPropertyBlock = new MaterialPropertyBlock();
_parameterOffsetX = (float) Ctx.Random.NextDouble();
_parameterOffsetY = (float) Ctx.Random.NextDouble();
Expand Down Expand Up @@ -102,6 +105,7 @@ public GrassPatch(SimulationContext ctx, Vector4 patchTexCoord, Bounds bounds) :
CreateGrassDataTexture();
CreateDummyMesh();
CreateDummyMeshBillboardCrossed();
CreateDummyMeshBillboardScreen();
SetupMaterialPropertyBlock();
}

Expand Down Expand Up @@ -132,7 +136,7 @@ public void Draw()
_materialPropertyBlock);

if (_argsBillboardScreen[1] > 0)
Graphics.DrawMeshInstancedIndirect(_dummyMesh, 0, Ctx.GrassBillboardScreen, Bounds, _argsBillboardScreenBuffer, 0,
Graphics.DrawMeshInstancedIndirect(_dummyMeshBillboardScreen, 0, Ctx.GrassBillboardScreen, Bounds, _argsBillboardScreenBuffer, 0,
_materialPropertyBlock);
}

Expand Down Expand Up @@ -284,6 +288,23 @@ private void CreateDummyMeshBillboardCrossed()
_dummyMeshBillboardCrossed.SetIndices(indices, MeshTopology.Points, 0);
_dummyMeshBillboardCrossed.RecalculateBounds();
}

private void CreateDummyMeshBillboardScreen()
{
var dummyMeshSize = Ctx.Settings.GetMinAmountBillboardsPerPatch();
var dummyVertices = new Vector3[dummyMeshSize];
var indices = new int[dummyMeshSize];

for (var i = 0; i < dummyMeshSize; i++)
{
dummyVertices[i] = Vector3.zero;
indices[i] = i;
}

_dummyMeshBillboardScreen = new Mesh {vertices = dummyVertices};
_dummyMeshBillboardScreen.SetIndices(indices, MeshTopology.Points, 0);
_dummyMeshBillboardScreen.RecalculateBounds();
}

private void SetupMaterialPropertyBlock()
{
Expand Down
4 changes: 2 additions & 2 deletions Assets/Scripts/GrassSimulation/Core/Lod/PatchContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public void DrawGizmo()
protected virtual void UpdatePerFrameData()
{
//TODO: Maybe outsource all the computeshader data settings to its own class
Ctx.GrassSimulationComputeShader.SetBool("BillboardGeneration", false);
Ctx.GrassGeometry.SetVector("CamPos", Ctx.Camera.transform.position);
Ctx.GrassGeometry.SetVector("viewDir", Ctx.Camera.transform.forward);
Ctx.GrassGeometry.SetMatrix("ViewProjMatrix",
Expand All @@ -60,13 +59,14 @@ protected virtual void UpdatePerFrameData()
Ctx.GrassBillboardScreen.SetVector("CamPos", Ctx.Camera.transform.position);
Ctx.GrassBillboardScreen.SetVector("CamUp", Ctx.Camera.transform.up);

Ctx.GrassSimulationComputeShader.SetBool("BillboardGeneration", false);
Ctx.GrassSimulationComputeShader.SetFloat("DeltaTime", Time.deltaTime);
Ctx.GrassSimulationComputeShader.SetFloat("Time", Time.time);
Ctx.GrassSimulationComputeShader.SetMatrix("ViewProjMatrix",
Ctx.Camera.projectionMatrix * Ctx.Camera.worldToCameraMatrix);
Ctx.GrassSimulationComputeShader.SetFloats("CamPos", Ctx.Camera.transform.position.x,
Ctx.Camera.transform.position.y, Ctx.Camera.transform.position.z);

Ctx.GrassSimulationComputeShader.SetVector("SunLight", new Vector4(-Ctx.SunLight.transform.forward.x, -Ctx.SunLight.transform.forward.y, -Ctx.SunLight.transform.forward.z, Ctx.SunLight.intensity));
Ctx.GrassSimulationComputeShader.SetVector("GravityVec", Ctx.Settings.Gravity);
}
}
Expand Down
13 changes: 8 additions & 5 deletions Assets/Scripts/GrassSimulation/Core/Shaders/Grass.shader
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ Shader "GrassSimulation/Grass"

struct UvData { float2 Position; };

//Billboard Generation
//Billboard Specific
uniform float GrassType;
uniform float BillboardAspect;
uniform float RepetitionCount;

//Once
uniform float BillboardAlphaCutoff;
Expand Down Expand Up @@ -137,7 +138,9 @@ Shader "GrassSimulation/Grass"
OUT.vertexID = vertexID;
OUT.instanceID = instanceID;
#ifdef GRASS_BILLBOARD_CROSSED
OUT.uvLocal = UvBuffer[StartIndex + VertexCount * instanceID + (vertexID % VertexCount)].Position;
OUT.uvLocal = UvBuffer[StartIndex + (VertexCount * RepetitionCount) * instanceID + (vertexID % VertexCount) * RepetitionCount].Position;
#elif GRASS_BILLBOARD_SCREEN
OUT.uvLocal = UvBuffer[StartIndex + (VertexCount * RepetitionCount) * instanceID + (vertexID * RepetitionCount)].Position;
#else
OUT.uvLocal = UvBuffer[StartIndex + VertexCount * instanceID + vertexID].Position;
#endif
Expand Down Expand Up @@ -192,12 +195,11 @@ Shader "GrassSimulation/Grass"
HSOut OUT = (HSOut)0;

float2 uvParameter = float2(ParameterOffsetX, ParameterOffsetY) + IN[0].uvLocal;
//float2 uvNormalHeight = lerp(NormalHeightUvCorrection.xy, NormalHeightUvCorrection.zw, IN[0].uvLocal);
float2 uvGlobal = lerp(PatchTexCoord.xy, PatchTexCoord.xy + PatchTexCoord.zw, IN[0].uvLocal);
float4 normalHeight = NormalHeightTexture.SampleLevel(samplerNormalHeightTexture, uvGlobal, 0);
float4 SimulationData0 = SimulationTexture0.SampleLevel(samplerSimulationTexture0, IN[0].uvLocal, 0);
float4 SimulationData1 = SimulationTexture1.SampleLevel(samplerSimulationTexture0, IN[0].uvLocal, 0);
float4 grassMapData = GrassMapTexture.SampleLevel(samplerParameterTexture, uvGlobal, 0);
float4 grassMapData = GrassMapTexture.SampleLevel(samplerNormalHeightTexture, uvGlobal, 0);

OUT.pos = mul(PatchModelMatrix, float4(IN[0].uvLocal.x, normalHeight.w, IN[0].uvLocal.y, 1.0)).xyz;

Expand Down Expand Up @@ -276,7 +278,7 @@ Shader "GrassSimulation/Grass"
DSOut OUT = (DSOut)0;

float3 pos = IN[0].pos;
float3 up = IN[0].bladeUp;
float3 up = IN[0].bladeUp; //TODO: Use same correction as in compute shader
float3 bladeDir = IN[0].bladeDir;
#ifdef GRASS_GEOMETRY
float3 v1 = pos + IN[0].v1 * IN[0].transitionFactor;
Expand Down Expand Up @@ -307,6 +309,7 @@ Shader "GrassSimulation/Grass"
float3 i1 = h1 + v * (h2 - h1);
float3 i2 = i1 + off;

//TODO: Can be removed?
#ifdef BILLBOARD_GENERATION
float widthFactor = 1;
#elif GRASS_GEOMETRY
Expand Down
27 changes: 15 additions & 12 deletions Assets/Scripts/GrassSimulation/Core/Shaders/GrassSimulation.compute
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ float DeltaTime;
float Time;
float4x4 ViewProjMatrix;
float4 GravityVec;
float4 SunLight; //Direction towards sun and Influence
float4 WindData;

float4 LocalToWorldPos(float4 pos){ return mul(PatchModelMatrix, pos); }
Expand Down Expand Up @@ -101,7 +102,7 @@ void CalculateBladeDirAndFront(inout float3 bladeUp, in float dirAlpha, out floa
float3 tmp = normalize(float3(sd, sd + cd, cd)); //arbitrary vector for finding normal vector
bladeDir = normalize(cross(bladeUp, tmp));
bladeFront = normalize(cross(bladeUp, bladeDir));
//bladeUp = normalize(bladeUp + 0.3 * bladeFront);
bladeUp = normalize(bladeUp + SunLight.xyz * SunLight.w);
}

bool IsNAN(float n)
Expand All @@ -119,18 +120,22 @@ void SimulationSetup(uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uin
//Create all the needed uv coordinates
float2 uvLocal = float2(id.x/GrassDataResolution, id.y/GrassDataResolution);
float2 uvGlobal = lerp(PatchTexCoord.xy, PatchTexCoord.xy + PatchTexCoord.zw, uvLocal);
//float2 uvNormalHeight = lerp(NormalHeightUvCorrection.xy, NormalHeightUvCorrection.zw, uvLocal);
float2 uvParameter = float2(ParameterOffsetX, ParameterOffsetY) + uvLocal;

//Read all the textures -°O°/
float4 normalHeight = NormalHeightTexture.SampleLevel(samplerNormalHeightTexture, uvGlobal, 0);
float4 parameters = ParameterTexture.SampleLevel(samplerParameterTexture, uvParameter, 0);

//Create and name all needed variables
float dirAlpha = parameters.w;
float3 bladeDir;
float3 bladeFront;
float3 bladeUp = normalize(normalHeight.xyz);
float3 bladeNormal = normalize(normalHeight.xyz);
CalculateBladeDirAndFront(bladeNormal, dirAlpha, bladeDir, bladeFront);
float height = parameters.z;
float3 v2 = bladeUp * height;
float3 v1 = GetV1(v2, bladeUp, height, 1.0 / height);
float3 v2 = bladeNormal * height;
float3 v1 = GetV1(v2, bladeNormal, height, 1.0 / height);

AdjustBezierArcLength(v1, v2, height);

Expand All @@ -146,16 +151,13 @@ void PhysicsMain (uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint g
{
//Create all the needed uv coordinates
float2 uvLocal = float2(id.x/GrassDataResolution + 0.5 / GrassDataResolution, id.y/GrassDataResolution + 0.5 / GrassDataResolution);
//float2 uvNormalHeight = lerp(NormalHeightUvCorrection.xy, NormalHeightUvCorrection.zw, uvLocal);
float2 uvGlobal = lerp(PatchTexCoord.xy, PatchTexCoord.xy + PatchTexCoord.zw, uvLocal);
float2 uvCollisionTexture = uvGlobal;
//uvCollisionTexture.x = 1 - uvCollisionTexture.x;
float2 uvParameter = float2(ParameterOffsetX, ParameterOffsetY) + uvLocal;

//Read all the textures -°O°/
float4 normalHeight = NormalHeightTexture.SampleLevel(samplerNormalHeightTexture, uvGlobal, 0);
float4 grassMapData = GrassMapTexture.SampleLevel(samplerNormalHeightTexture, uvGlobal, 0);
float4 parameters = ParameterTexture.SampleLevel(samplerParameterTexture, uvParameter, 0);
float4 grassMapData = GrassMapTexture.SampleLevel(samplerParameterTexture, uvGlobal, 0);
//Don't use grassmaps density if we are generating our billboard data
if (BillboardGeneration) grassMapData.z = 1;
float4 simulationData0 = SimulationTexture0.Load(id.xy);
Expand All @@ -178,11 +180,12 @@ void PhysicsMain (uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint g
float3 localV0 = float3(uvLocal.x, normalHeight.w, uvLocal.y);
float3 v0 = LocalToWorldPos(localV0).xyz;
float3 bladeUp = normalize(normalHeight.xyz);
float3 bladeNormal = normalize(normalHeight.xyz); //Normal gets altered by negative gravity, so that it grows away
float3 bladeDir;
float3 bladeFront;
CalculateBladeDirAndFront(bladeUp, dirAlpha, bladeDir, bladeFront);
CalculateBladeDirAndFront(bladeNormal, dirAlpha, bladeDir, bladeFront);
float mdt = DeltaTime;//min(DeltaTime, 1.0);
float3 idleV2 = bladeUp * height;
float3 idleV2 = bladeNormal * height;
float3 v2 = simulationData1.xyz;
float collisionForce = max(simulationData0.w - (1.0 - bendingFactor) * RecoveryFactor * mdt, 0.0);

Expand Down Expand Up @@ -210,7 +213,7 @@ void PhysicsMain (uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint g

//ValidateV2Tex(v2, v0);
ValidateV2(v2, bladeUp);
float3 v1 = GetV1(v2, bladeUp, height, invHeight);
float3 v1 = GetV1(v2, bladeNormal, height, invHeight);
AdjustBezierArcLength(v1, v2, height);

// Collisions
Expand Down Expand Up @@ -280,7 +283,7 @@ void PhysicsMain (uint3 id : SV_DispatchThreadID, uint3 gid : SV_GroupID, uint g
{
//ValidateV2Tex(v2, v0);
ValidateV2(v2, bladeUp);
v1 = GetV1(v2, bladeUp, height, invHeight);
v1 = GetV1(v2, bladeNormal, height, invHeight);
AdjustBezierArcLength(v1, v2, height);
}

Expand Down
3 changes: 3 additions & 0 deletions Assets/Scripts/GrassSimulation/Core/SimulationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class SimulationContext : ScriptableObject
[Header("Requirements")]
public Transform Transform;
public Camera Camera;
public Light SunLight;
public ComputeShader GrassSimulationComputeShader;
public ComputeShader RenderTextureVolumeToSlice;
public Shader CollisionDepthShader;
Expand Down Expand Up @@ -306,8 +307,10 @@ public void Init()

GrassBillboardCrossed.SetTexture("GrassBillboards", BillboardTexturePatchContainer.BillboardTextures);
GrassBillboardCrossed.SetFloat("BillboardAspect", BillboardTexturePatchContainer.BillboardAspect);
GrassBillboardCrossed.SetFloat("RepetitionCount", PositionInput.GetRepetitionCount());
GrassBillboardScreen.SetTexture("GrassBillboards", BillboardTexturePatchContainer.BillboardTextures);
GrassBillboardScreen.SetFloat("BillboardAspect", BillboardTexturePatchContainer.BillboardAspect);
GrassBillboardScreen.SetFloat("RepetitionCount", PositionInput.GetRepetitionCount());

//Everything is ready.
IsReady = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ public class ClumpedPositionInput: PositionInput, IInitializableWithCtx
private Random _random;

private int _lastId;
private int _curClumpSize;
private Vector2 _curPos;

[Range(1, 64)]
public int ClumpSizeMin = 4;
[Range(1, 64)]
public int ClumpSizeMax = 16;
public uint ClumpSize = 4;
public float ClumpRadiusMin = 0.001f;
public float ClumpRadiusMax = 0.001f;

Expand All @@ -29,16 +26,17 @@ public void Init(SimulationContext context)

public override Vector2 GetPosition(int id)
{
if (_lastId == -1 || id > _lastId + _curClumpSize)
if (_lastId == -1 || id > _lastId + ClumpSize)
{
_lastId = id;
_curClumpSize = _random.Next(ClumpSizeMin, ClumpSizeMax);
_curPos = new Vector2((float) _random.NextDouble(), (float) _random.NextDouble());
}
var radius = ClumpRadiusMin + (float) _random.NextDouble() * (ClumpRadiusMax - ClumpRadiusMin);
var angle = 2 * Mathf.PI * (float) _random.NextDouble();
var offset = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * radius;
return _curPos + offset;
}

public override uint GetRepetitionCount() { return ClumpSize; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public override Vector2 GetPosition(int id)
{
return new Vector2((float) _random.NextDouble(), (float) _random.NextDouble());
}

public override uint GetRepetitionCount() { return 1; }
}
}

0 comments on commit 25563a0

Please sign in to comment.