Skip to content

Instantly share code, notes, and snippets.

@bgk-
Last active January 8, 2022 19:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bgk-/d7e41a545fc91601cd17d5b748b4d595 to your computer and use it in GitHub Desktop.
Save bgk-/d7e41a545fc91601cd17d5b748b4d595 to your computer and use it in GitHub Desktop.
17.waves Tower Radius Display

Branching

Some people feel branching is too slow, even for modern gpus, if so and you really want to optimize you can always change the branching to something like

bool ring = isRing(i.worldPos, _RingPositions[index], _RingRadii[index]);
o.Albedo = lerp(o.Albedo, RingColor, ring);
o.Emission = lerp(o.Emission, RingColor, ring);

Array

Shaders can't change size of an array, so make the max the largest size you'll need. You also define a uniform int _RingCount variable which syncs the current length, and instead loop over the current count rather than the max everytime.

Post Processing

If there are a lot of small objects and a lot of rings this can be a hit on performance, it may be better to make this a post processing shader and so only performs the loops once, however it'll be placed on all objects and not just ones with the material.

using System;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SeventeenWaves
{
public class RadiusDisplay : MonoBehaviour
{
private static Vector4[] _positions;
private static float[] _radii;
private const int MaxRingCount = 4;
private static readonly int RingPositions = Shader.PropertyToID("_RingPositions");
private static readonly int RingRadii = Shader.PropertyToID("_RingRadii");
private void Awake()
{
_positions = new Vector4[MaxRingCount];
_radii = new float[MaxRingCount];
DontDestroyOnLoad(this);
}
private static void Clear()
{
Shader.SetGlobalVectorArray(RingPositions, _positions);
Shader.SetGlobalFloatArray(RingRadii, _radii);
}
private void OnDestroy()
{
Clear();
}
public static void SetRadius(Vector3 position, float radius, int i)
{
if (index > MaxRingCount - 1) throw new IndexOutOfRangeException("Ring index exceeds MaxRingCount");
_positions[i] = position;
_radii[i] = radius;
Shader.SetGlobalVectorArray(RingPositions, _positions);
Shader.SetGlobalFloatArray(RingRadii, _radii);
}
}
}
Shader "Custom/RadiusDisplay"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
static const float RingThickness = 0.1f;
static const int MaxRings = 4;
static const float4 RingColor = float4(1, 1, 1, 1);
uniform float4 _RingPositions[MaxRings];
uniform float _RingRadii[MaxRings];
struct Input
{
float2 uv_MainTex;
};
bool isRing(float3 worldPos, float3 ringPosition, float ringRadius)
{
const float dist = distance(worldPos, ringPosition);
return dist < ringRadius && dist > ringRadius - RingThickness;
}
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = 1;
for (int index = 0; index < MaxRings; index++)
{
if (isRing(i.worldPos, _RingPositions[index], _RingRadii[index]))
{
o.Albedo = RingColor;
o.Emission = RingColor;
}
}
}
ENDCG
}
FallBack "Diffuse"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment