Shader "test/MyShader" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma geometry geom #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; float3 worldPosition : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.normal = v.normal; o.worldPosition = mul(_Object2World, v.vertex).xyz; return o; } [maxvertexcount(3)] void geom(triangle v2f input[3], inout TriangleStream<v2f> OutputStream) { v2f test = (v2f)0; float3 normal = normalize(cross(input[1].worldPosition.xyz - input[0].worldPosition.xyz, input[2].worldPosition.xyz - input[0].worldPosition.xyz)); for(int i = 0; i < 3; i++) { test.normal = normal; test.vertex = input[i].vertex; test.uv = input[i].uv; OutputStream.Append(test); } } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); float3 lightDir = float3(1, 1, 0); float ndotl = dot(i.normal, normalize(lightDir)); return col * ndotl; } ENDCG } } }
Shader "Custom/GeometryShaderTest1" { Properties { _Color("Color", Color) = (1,1,1,1) _Size("Size", float) = 0.5 } SubShader { Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } LOD 100 Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off Pass { CGPROGRAM #pragma target 5.0 #pragma vertex vert #pragma geometry geom #pragma fragment frag #include "UnityCG.cginc" // Vars float4 _Color; float _Size; float3 _worldPos; struct data { float4 pos0; }; StructuredBuffer<data> buf_Points; struct input { float4 pos : SV_POSITION; float4 color: COLOR; }; input vert(uint id : SV_VertexID) { input o; o.pos = float4(buf_Points[id].pos0 + _worldPos, 1.0f); return o; } [maxvertexcount(8)] void geom(line input p[2], inout TriangleStream<input> triStream) { float4 s[2]; s[0] = mul(UNITY_MATRIX_VP, p[0].pos); s[1] = mul(UNITY_MATRIX_VP, p[1].pos); s[0].x /= s[0].w; s[0].y /= s[0].w; s[1].x /= s[1].w; s[1].y /= s[1].w; s[0].z = s[1].z = 0.1; s[0].w = s[1].w = 1; float4 ab = s[1] - s[0]; float4 normal = float4(-ab.y, ab.x, 0, 0); normal = normalize(normal); normal.x /= (_ScreenParams.x / _ScreenParams.y); input pIn; pIn.pos = s[0] - normal * _Size; pIn.color = float4(1.0, 0.0, 0.0, 1.0); triStream.Append(pIn); pIn.pos = s[0] + normal * _Size; pIn.color = float4(1.0, 0.0, 0.0, 1.0); triStream.Append(pIn); pIn.pos = s[1] - normal * _Size; pIn.color = float4(0.0, 1.0, 0.0, 1.0); triStream.Append(pIn); pIn.pos = s[1] + normal * _Size; pIn.color = float4(0.0, 1.0, 0.0, 1.0); triStream.Append(pIn); } float4 frag(input i) : COLOR { return i.color; } ENDCG } } FallBack "Diffuse" }
using System.Collections; using System.Collections.Generic; using UnityEngine; struct data { public Vector3 pos; } public class LineSegmentRenderer : MonoBehaviour { public Shader geomShader; public float Size = 0.05f; Material material; ComputeBuffer outputBuffer; List<Vector3> points; // Use this for initialization void Start () { material = new Material(geomShader); points = new List<Vector3>(); SetupTest(); } void SetupTest() { for (int i = 0; i < 10; i++) { AddLineSegmentGS( new Vector3(Random.Range(-10f, 10f), Random.Range(-10f, 10f), Random.Range(-1f, 1f)), new Vector3(Random.Range(-10f, 10f), Random.Range(-10f, 10f), Random.Range(-1f, 1f)) ); } Apply(); } // Update is called once per frame void Update () { } public void AddLineSegmentGS(Vector3 a, Vector3 b) { points.Add(a); points.Add(b); } public void Apply() { outputBuffer = new ComputeBuffer(points.Count, 24); outputBuffer.SetData(points.ToArray()); } public void OnRenderObject() { material.SetPass(0); material.SetBuffer("buf_Points", outputBuffer); material.SetFloat("_Size", Size); Graphics.DrawProcedural(MeshTopology.Lines, outputBuffer.count); } public void OnDestroy() { outputBuffer.Release(); } }