// Pcx - Point cloud importer & renderer for Unity // https://github.com/keijiro/Pcx #include "UnityCG.cginc" #include "Common.cginc" // Uniforms half4 _Tint; half _PointSize; float4x4 _Transform; #if _COMPUTE_BUFFER StructuredBuffer _PointBuffer; #endif // Vertex input attributes struct Attributes { #if _COMPUTE_BUFFER uint vertexID : SV_VertexID; #else float4 position : POSITION; half3 color : COLOR; #endif }; // Fragment varyings struct Varyings { float4 position : SV_POSITION; #if !PCX_SHADOW_CASTER half3 color : COLOR; UNITY_FOG_COORDS(0) #endif }; // Vertex phase Varyings Vertex(Attributes input) { // Retrieve vertex attributes. #if _COMPUTE_BUFFER float4 pt = _PointBuffer[input.vertexID]; float4 pos = mul(_Transform, float4(pt.xyz, 1)); half3 col = PcxDecodeColor(asuint(pt.w)); #else float4 pos = input.position; half3 col = input.color; #endif #if !PCX_SHADOW_CASTER // Color space convertion & applying tint #if UNITY_COLORSPACE_GAMMA col *= _Tint.rgb * 2; #else col *= LinearToGammaSpace(_Tint.rgb) * 2; col = GammaToLinearSpace(col); #endif #endif // Set vertex output. Varyings o; o.position = UnityObjectToClipPos(pos); #if !PCX_SHADOW_CASTER o.color = col; UNITY_TRANSFER_FOG(o, o.position); #endif return o; } // Geometry phase [maxvertexcount(36)] void Geometry(point Varyings input[1], inout TriangleStream outStream) { float4 origin = input[0].position; float2 extent = abs(UNITY_MATRIX_P._11_22 * _PointSize); // Copy the basic information. Varyings o = input[0]; // Determine the number of slices based on the radius of the // point on the screen. float radius = extent.y / origin.w * _ScreenParams.y; uint slices = min((radius + 1) / 5, 4) + 2; // Slightly enlarge quad points to compensate area reduction. // Hopefully this line would be complied without branch. if (slices == 2) extent *= 1.2; // Top vertex o.position.y = origin.y + extent.y; o.position.xzw = origin.xzw; outStream.Append(o); UNITY_LOOP for (uint i = 1; i < slices; i++) { float sn, cs; sincos(UNITY_PI / slices * i, sn, cs); // Right side vertex o.position.xy = origin.xy + extent * float2(sn, cs); outStream.Append(o); // Left side vertex o.position.x = origin.x - extent.x * sn; outStream.Append(o); } // Bottom vertex o.position.x = origin.x; o.position.y = origin.y - extent.y; outStream.Append(o); outStream.RestartStrip(); } half4 Fragment(Varyings input) : SV_Target { #if PCX_SHADOW_CASTER return 0; #else half4 c = half4(input.color, _Tint.a); UNITY_APPLY_FOG(input.fogCoord, c); return c; #endif }