Skip to content

Instantly share code, notes, and snippets.

@harunseng
Forked from herohiralal/CurveController.cs
Created January 19, 2022 06:52
Show Gist options
  • Save harunseng/dae9ddd9af12d88b8a7778aff2424d93 to your computer and use it in GitHub Desktop.
Save harunseng/dae9ddd9af12d88b8a7778aff2424d93 to your computer and use it in GitHub Desktop.
Add curvature to the rendering without changing simulation code.
using UnityEngine;
namespace AIEngineTest
{
public class CurveController : MonoBehaviour
{
private static CurveController s_Instance = null;
private const float k_StraightDistanceClamp = 50f;
private const float k_CurvatureClamp = 10f;
[SerializeField] [Range(0f, k_StraightDistanceClamp)] private float m_StraightDistance = 10f;
[SerializeField] [Range(-k_CurvatureClamp, k_CurvatureClamp)] private float m_VerticalCurvature = 0f;
[SerializeField] [Range(-k_CurvatureClamp, k_CurvatureClamp)] private float m_HorizontalCurvature = 0f;
private static readonly int s_StraightRenderDistanceID = Shader.PropertyToID("_CURVER_STRAIGHT_RENDER_DISTANCE");
private static readonly int s_HorizontalCurvatureID = Shader.PropertyToID("_CURVER_HORIZONTAL_CURVATURE");
private static readonly int s_VerticalCurvatureID = Shader.PropertyToID("_CURVER_VERTICAL_CURVATURE");
private void Awake()
{
if (s_Instance == null)
{
s_Instance = this;
}
else
{
Debug.Log("Duplicate curve controller detected.", this);
return;
}
UpdateValues();
}
private void OnDestroy()
{
if (s_Instance == this)
{
s_Instance = null;
}
}
private void OnValidate()
{
UpdateValues();
}
private void UpdateValues()
{
straightDistance = m_StraightDistance;
horizontalCurvature = m_HorizontalCurvature;
verticalCurvature = m_VerticalCurvature;
}
public float straightDistance
{
get => m_StraightDistance;
set
{
value = Mathf.Clamp(value, 0f, k_StraightDistanceClamp);
m_StraightDistance = value;
Shader.SetGlobalFloat(s_StraightRenderDistanceID, value);
}
}
public float horizontalCurvature
{
get => m_HorizontalCurvature;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_HorizontalCurvature = value;
Shader.SetGlobalFloat(s_HorizontalCurvatureID, value);
}
}
public float verticalCurvature
{
get => m_VerticalCurvature;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_VerticalCurvature = value;
Shader.SetGlobalFloat(s_VerticalCurvatureID, value);
}
}
}
}
// this file is meant to be used in conjunction with a Custom Function node
// in ShaderGraph. You can find out more about how to use it at
// https://docs.unity3d.com/Packages/com.unity.shadergraph@13.1/manual/Custom-Function-Node.html
// all you need is the Position node (Object Space), connect its input to VertexPosOS and optionally
// provide an origin to determine where the rendering looks straight (and not curved)
#ifndef CURVER_INCLUDED
#define CURVER_INCLUDED
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"
uniform float _CURVER_STRAIGHT_RENDER_DISTANCE;
uniform float _CURVER_HORIZONTAL_CURVATURE;
uniform float _CURVER_VERTICAL_CURVATURE;
#define CURVER_CURVATURE_POWER 2
void GetModifiedObjectSpace_float(const float3 OriginWS, const float3 VertexPosOS, out float3 ModifiedVertexPosOS)
{
const float3 VertexPosWS = TransformObjectToWorld(VertexPosOS);
const float DistanceToCamera = distance(OriginWS, VertexPosWS);
const float StraighteningMask = step(_CURVER_STRAIGHT_RENDER_DISTANCE, DistanceToCamera);
const float2 Curvature = pow(DistanceToCamera - _CURVER_STRAIGHT_RENDER_DISTANCE, CURVER_CURVATURE_POWER)
* float2(_CURVER_HORIZONTAL_CURVATURE, _CURVER_VERTICAL_CURVATURE) * pow(0.1f, CURVER_CURVATURE_POWER);
const float3 ModifiedVertexPosWS = VertexPosWS + (StraighteningMask * float3(Curvature.x, Curvature.y, 0));
ModifiedVertexPosOS = TransformWorldToObject(ModifiedVertexPosWS);
}
void GetModifiedObjectSpace_half(const half3 OriginWS, const half3 VertexPosOS, out half3 ModifiedVertexPosOS)
{
const half3 VertexPosWS = TransformObjectToWorld(VertexPosOS);
const half DistanceToCamera = distance(OriginWS, VertexPosWS);
const half StraighteningMask = step(_CURVER_STRAIGHT_RENDER_DISTANCE, DistanceToCamera);
const half2 Curvature = pow(DistanceToCamera - _CURVER_STRAIGHT_RENDER_DISTANCE, CURVER_CURVATURE_POWER)
* half2(_CURVER_HORIZONTAL_CURVATURE, _CURVER_VERTICAL_CURVATURE) * pow(0.1f, CURVER_CURVATURE_POWER);
const half3 ModifiedVertexPosWS = VertexPosWS + (StraighteningMask * half3(Curvature.x, Curvature.y, 0));
ModifiedVertexPosOS = TransformWorldToObject(ModifiedVertexPosWS);
}
#undef CURVER_CURVATURE_POWER
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment