Skip to content

Instantly share code, notes, and snippets.

@mzandvliet
Created October 26, 2019 11:14
Show Gist options
  • Save mzandvliet/fd5a1abb4a7767e28080e465211edbc9 to your computer and use it in GitHub Desktop.
Save mzandvliet/fd5a1abb4a7767e28080e465211edbc9 to your computer and use it in GitHub Desktop.
Sketch of how you procedurally generate data using Burst, then pass it to gpu through compute buffers
// C# side
public class LineRenderer : MonoBehaviour {
[SerializeField] private Camera _camera;
[SerializeField] private Material _lineMaterial;
private NativeArray<float3> _linePoints;
private ComputeBuffer _linePointBuffer;
private ComputeBuffer _lineIndexBuffer;
private int _lineCount;
private void Awake() {
_linePoints = new NativeArray<float3>(_lineCapacity * _numPointsPerLine, Allocator.Persistent, NativeArrayOptions.ClearMemory);
var indices = new uint[] { 2, 1, 0, 1, 2, 3 }; // left right left, right left right
_lineIndexBuffer = new ComputeBuffer(indices.Length, sizeof(uint));
_lineIndexBuffer.SetData(indices);
_linePointBuffer = new ComputeBuffer(_linePoints.Length, Marshal.SizeOf(typeof(float3)));
_linePointBuffer.SetData(_linePoints);
var commandBuffer = new CommandBuffer();
commandBuffer.DrawProcedural(Matrix4x4.identity, _lineMaterial, 0, MeshTopology.Triangles, 6, 4);
_camera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, commandBuffer);
_lineMaterial.SetBuffer("indices", _lineIndexBuffer);
_lineMaterial.SetBuffer("points", _linePointBuffer);
}
private void OnDestroy() {
_linePoints.Dispose();
_linePointBuffer.Dispose();
_lineIndexBuffer.Dispose();
}
}
// GPU side
Shader "Custom/TessellatedLine" {
Properties {
_MainTex("Texture", 2D) = "white" {}
}
SubShader{
Tags{ "LightMode" = "ForwardBase" }
Cull Back
Pass{
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 5.0
#pragma vertex vertex_shader
#pragma fragment fragment_shader
sampler2D _MainTex;
float4 _MainTex_ST;
uniform fixed4 _LightColor0;
float _AspectRatio;
StructuredBuffer<float3> points;
StructuredBuffer<uint> indices; // Since Unity doesn't offer DrawProceduralIndexed
struct v2f {
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 uv : TEXCOORD0;
};
v2f vertex_shader(uint id : SV_VertexID, uint inst : SV_InstanceID)
{
v2f o;
// evens are left, odds are right -> -1 or 1
int side = (id % 2) * 2 - 1;
// high indices are part of the end of segment, low indices are part of the start
int bottomTop = indices[id] > 1 ? 1 : 0;
float4 posA = mul(UNITY_MATRIX_VP, float4(points[inst * 2 + 0], 1));
float4 posB = mul(UNITY_MATRIX_VP, float4(points[inst * 2 + 1], 1));
float3 worldPos = points[inst * 2 + bottomTop];
float4 tangentScreen = posB - posA;
float2 normalScreen = normalize(float2(-tangentScreen.y, tangentScreen.x));
normalScreen.x /= _AspectRatio;
o.pos = mul(UNITY_MATRIX_VP, float4(worldPos, 1));
o.pos += float4(normalScreen * (0.5 * side), 0, 0);
float2 uv = float2(1 - (id % 2), id / 2);//float2((id % 2), (id / 2) % 2);
o.uv = TRANSFORM_TEX(uv, _MainTex);
o.col = float4(id % 3 == 0, id % 3 == 1, id % 3 == 2, 1);
return o;
}
fixed4 fragment_shader(v2f i) : SV_Target
{
fixed4 final = tex2D(_MainTex, i.uv);
final *= i.col;
return final;
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment