- Home /
Geometry Shader showing wrong geometry
Hi, I wonder if anyone can help me?
I have been trying to create a basic hair simulation using a geometry shader to create the hair strands.
I want the shader, for now, to produce one hair/ line from the middle of a “plane” mesh (a square of 4 vertices).
I do all the physics modelling based on Hooke's law (two masses, two springs and one anchor point - the middle of the plane) and I then send the new coordinates to the geometry shader.
When I enter play mode, I get oscillating coordinates from the inspector view and I get the bounce motion in the game view (but only when the rotation in X is 0.) Unity seems to import my Blender models with a rotation of -89.98 in X.
The problem is I get this bouncing “V” shape. I don't understand what I have done wrong.
Code is below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public struct HairPoints3
{
public float x0; // The base vertex position of the hair
public float y0; // The base vertex position of the hair
public float z0; // The base vertex of position the hair
public float x1; // The Second vertex of the hair
public float y1; // The Second vertex of the hair
public float z1; // The Second vertex of the hair
public float x2; // The third vertex of the hair
public float y2; // The third vertex of the hair
public float z2; // The third vertex of the hair
}
public class HairPhysicsScript3 : MonoBehaviour
{
public Material HairMaterial;
HairPoints3 HairPointStruct;
public Mesh TheMesh;
public MeshFilter MF;
public Vector3[] MeshVertsCopy;
ComputeBuffer OutPutBuffer;
public List<Vector3> MeshVertsToSort;
public List<HairPoints3> HairsLocationsToComputeBuffer;
public HairPoints3[] HairPointsArrayOutPut;
public float GravityNumber; // Gravity constant
public float K; // This is Hooke's constant
public float Dampening; // Dampening Constant;
public float Mass; // This is the mass of each vertex
public bool A;
public float MidPointX;
public float MidPointY;
public float MidPointZ;
public Vector3 H;
public Vector3 H1;
public Vector3 H2;
public Vector3 HLocal;
public Vector3 HLocal1;
public Vector3 HLocal2;
float VelocityX;
float VelocityY;
float VelocityZ;
float VelocityX1;
float VelocityY1;
float VelocityZ1;
float VelocityX2;
float VelocityY2;
float VelocityZ2;
float ForceX;
float ForceX1;
float ForceX2;
float ForceY;
float ForceY1;
float ForceY2;
float ForceZ;
float ForceZ1;
float ForceZ2;
float AccelerationX1;
float AccelerationX2;
float AccelerationY1;
float AccelerationY2;
float AccelerationZ1;
float AccelerationZ2;
// Use this for initialization
void Start()
{
TheMesh = MF.mesh;
MeshVertsCopy = TheMesh.vertices;
// This converts the default "triangle topology" to "point topology" which creates a "point cloud" and also allowes for the geometry shader to work fully.
TheMesh.SetIndices(TheMesh.GetIndices(0), MeshTopology.Points, 0);
HairsLocationsToComputeBuffer = new List<HairPoints3>();
OutPutBuffer = new ComputeBuffer(1, (sizeof(float) * 9) );
HairPointStruct = new HairPoints3();
MeshVertsToSort.Clear();
foreach (Vector3 AB in MeshVertsCopy)
{
Vector3 ABC = transform.TransformPoint(AB);
MeshVertsToSort.Add(ABC);
}
MeshVertsToSort.Sort((a, b) => a.x.CompareTo(b.x));
MidPointX = (MeshVertsToSort[0].x + MeshVertsToSort[3].x) / 2;
// This sorts the verts from low to high in order of y.
MeshVertsToSort.Sort((a, b) => a.y.CompareTo(b.y));
MidPointY = (MeshVertsToSort[0].y + MeshVertsToSort[3].y) / 2;
MeshVertsToSort.Sort((a, b) => a.z.CompareTo(b.z));
MidPointZ = (MeshVertsToSort[0].z + MeshVertsToSort[3].z) / 2;
H = new Vector3(MidPointX, MidPointY, MidPointZ);
H1 = new Vector3(MidPointX, MidPointY -1 , MidPointZ);
H2 = new Vector3(MidPointX, MidPointY -2 , MidPointZ);
}
// Update is called once per frame
void Update()
{
if (A == true)
{
StartCoroutine("DoHair");
}
}
IEnumerator DoHair()
{
A = false;
yield return new WaitForSeconds(Time.deltaTime);
HairsLocationsToComputeBuffer.Clear(); // Clear the list.
////////////////////////////////////////////
// Hooke's calculations below! - They work!!!! ///
///////////////////////////////////////////
//Dealing with the X forces
ForceX1 = (-K * (H1.x - H.x)) - (Dampening * VelocityX1) - (-K * (H2.x - H1.x)) + (Dampening * VelocityX2);
ForceX2 = (-K * (H2.x - H1.x) ) - (Dampening * VelocityX2);
//Dealing with the Y forces
ForceY1 = (-K * (H1.y - H.y)) - (Dampening * VelocityY1) - (Mass * GravityNumber) - (-K * (H2.y - H1.y)) + (Dampening * VelocityY2) ;
ForceY2 = (-K * (H2.y - H1.y)) - (Dampening * VelocityY2) - (Mass * GravityNumber) ;
//Dealing with the Z forces
ForceZ1 = (-K * (H1.z - H.z)) - (Dampening * VelocityZ1) - (-K * (H2.z - H1.z)) + (Dampening * VelocityZ2);
ForceZ2 = (-K * (H2.z - H1.z)) - (Dampening * VelocityZ2) ;
/////////////////////////////////
// Calculating accelerations here....//
////////////////////////////////
AccelerationX1 = ForceX1 / Mass;
AccelerationY1 = ForceY1 / Mass;
AccelerationZ1 = ForceZ1 / Mass;
AccelerationX2 = ForceX2 / Mass;
AccelerationY2 = ForceY2 / Mass;
AccelerationZ2 = ForceZ2 / Mass;
//////////////////////////////
// Calculating velocities here....//
/////////////////////////////
VelocityX1 = VelocityX1 + (AccelerationX1 * Time.deltaTime);
VelocityY1 = VelocityY1 + (AccelerationY1 * Time.deltaTime);
VelocityZ1 = VelocityZ1 + (AccelerationZ1 * Time.deltaTime);
VelocityX2 = VelocityX2 + (AccelerationX2 * Time.deltaTime);
VelocityY2 = VelocityY2 + (AccelerationY2 * Time.deltaTime);
VelocityZ2 = VelocityZ2 + (AccelerationZ2 * Time.deltaTime);
////////////////////////////
// Calculating Positions here...//
/////////////////////////////
H1.x = H1.x + VelocityX1;
H1.y = H1.y + VelocityY1;
H1.z = H1.z + VelocityZ1;
H2.x = H2.x + VelocityX2;
H2.y =H2.y + VelocityY2;
H2.z = H2.z +VelocityZ2;
// Converting to Local/Model Space
HLocal = transform.InverseTransformPoint(H);
HLocal1 =transform.InverseTransformPoint(H1);
HLocal2 =transform.InverseTransformPoint(H2);
// Placing these in a struct.
HairPointStruct.x0 = HLocal.x;
HairPointStruct.y0 = HLocal.y;
HairPointStruct.z0 = HLocal.z;
HairPointStruct.x1 = HLocal1.x;
HairPointStruct.y1 = HLocal1.y;
HairPointStruct.z1 = HLocal1.z;
HairPointStruct.x2 = HLocal2.x;
HairPointStruct.y2 = HLocal2.y;
HairPointStruct.z2 = HLocal2.z;
HairsLocationsToComputeBuffer.Add(HairPointStruct);
OutPutBuffer.SetData(HairsLocationsToComputeBuffer.ToArray() ); // We now copy the array into the buffer.
HairMaterial.SetBuffer("HairPointsBuffer", OutPutBuffer); // This will update the buffer in the shader (the one with vertex shaders etc...)
HairMaterial.SetFloat("GravityNumber", GravityNumber);
HairMaterial.SetFloat("Dampening", Dampening);
HairMaterial.SetFloat("K", K);
HairMaterial.SetFloat("Mass", Mass);
A = true;
}
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,)' with 'UnityObjectToClipPos()'
Shader "Custom/UnlitShaderHair1" {
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
// Upgrade NOTE: excluded shader from DX11, OpenGL ES 2.0 because it uses unsized arrays
//#pragma exclude_renderers d3d11 gles #pragma vertex vert
#pragma geometry MyGeometryShader #pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct HairPoints3
{
int HairNumber;
float x0; // The base vertex position of the hair
float y0; // The base vertex position of the hair
float z0; // The base vertex of position the hair
float x1; // The Second vertex of the hair
float y1; // The Second vertex of the hair
float z1; // The Second vertex of the hair
float x2; // The third vertex of the hair
float y2; // The third vertex of the hair
float z2; // The third vertex of the hair
};
StructuredBuffer<HairPoints3> HairPointsBuffer;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : POSITION;
};
struct GSOut
{
float4 Pos : SV_POSITION;
float2 uv : TEXCOORD0;
// UNITY_FOG_COORDS(1)
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 Color;
/////////////////
//Vertex Shader//
////////////////
v2f vert (appdata v,uint vid : SV_VertexID)
{
v2f o;
o.vertex = v.vertex;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
//////////////////////////////////
//GEOMETRY SHADER SITS HERE!//
//////////////////////////////////
[maxvertexcount (3)]
void MyGeometryShader(point v2f GeometryIn[1], inout LineStream<GSOut> TriStream , uint PrimID : SV_PrimitiveID)
{
GSOut Out;
// Hairs are created at this point......
if (PrimID ==0)
{
Out.Pos = UnityObjectToClipPos( float4(HairPointsBuffer[0].x0,HairPointsBuffer[0].y0,HairPointsBuffer[0].z0, 1) );
Out.uv = GeometryIn[0].uv;
TriStream.Append(Out);
Out.Pos = UnityObjectToClipPos(float4(HairPointsBuffer[0].x1,HairPointsBuffer[0].y1,HairPointsBuffer[0].z1,1 ) );
Out.uv = GeometryIn[0].uv;
TriStream.Append(Out);
Out.Pos = UnityObjectToClipPos( float4(HairPointsBuffer[0].x2,HairPointsBuffer[0].y2,HairPointsBuffer[0].z2,1 ) );
Out.uv = GeometryIn[0].uv;
TriStream.Append(Out);
}
}
//////////////////////////
// This is our pixel shader.//
/////////////////////////
fixed4 frag (GSOut i) : SV_Target
{
Color = fixed4(1,0,0,1); // We need to write fixed4 like this with the bracket. It seems anything else does not work.
return Color;
}
ENDCG
}
}
}
Thanks.
Your answer

Follow this Question
Related Questions
Does Unity support GL_NV_geometry_shader_passthrough geometry shaders? 0 Answers
Texture help 0 Answers
Is it possible to avoid writing to certain g-buffers? 1 Answer
rotation problem 1 Answer
How to achive the same look? Which shaders to use? 2 Answers