Skip to content

Instantly share code, notes, and snippets.

@herohiralal
Last active January 19, 2022 22:15
Show Gist options
  • Save herohiralal/e9dc58fadab7cc0184b7da2a829fc530 to your computer and use it in GitHub Desktop.
Save herohiralal/e9dc58fadab7cc0184b7da2a829fc530 to your computer and use it in GitHub Desktop.
Add curvature to the rendering without changing simulation code. Modified for a specific use-case where +Z/-Z have a different curvature.
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_VerticalCurvaturePositiveZ = 0f;
[SerializeField] [Range(-k_CurvatureClamp, k_CurvatureClamp)] private float m_HorizontalCurvaturePositiveZ = 0f;
[SerializeField] [Range(-k_CurvatureClamp, k_CurvatureClamp)] private float m_VerticalCurvatureNegativeZ = 0f;
[SerializeField] [Range(-k_CurvatureClamp, k_CurvatureClamp)] private float m_HorizontalCurvatureNegativeZ = 0f;
private static readonly int s_StraightRenderDistanceID = Shader.PropertyToID("_CURVER_STRAIGHT_RENDER_DISTANCE");
private static readonly int s_HorizontalCurvaturePositiveZID = Shader.PropertyToID("_CURVER_HORIZONTAL_CURVATURE_POSITIVE_Z");
private static readonly int s_VerticalCurvaturePositiveZID = Shader.PropertyToID("_CURVER_VERTICAL_CURVATURE_POSITIVE_Z");
private static readonly int s_HorizontalCurvatureNegativeZID = Shader.PropertyToID("_CURVER_HORIZONTAL_CURVATURE_NEGATIVE_Z");
private static readonly int s_VerticalCurvatureNegativeZID = Shader.PropertyToID("_CURVER_VERTICAL_CURVATURE_NEGATIVE_Z");
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;
horizontalCurvaturePositiveZ = m_HorizontalCurvaturePositiveZ;
verticalCurvaturePositiveZ = m_VerticalCurvaturePositiveZ;
horizontalCurvatureNegativeZ = m_HorizontalCurvatureNegativeZ;
verticalCurvatureNegativeZ = m_VerticalCurvatureNegativeZ;
}
public float straightDistance
{
get => m_StraightDistance;
set
{
value = Mathf.Clamp(value, 0f, k_StraightDistanceClamp);
m_StraightDistance = value;
Shader.SetGlobalFloat(s_StraightRenderDistanceID, value);
}
}
public float horizontalCurvaturePositiveZ
{
get => m_HorizontalCurvaturePositiveZ;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_HorizontalCurvaturePositiveZ = value;
Shader.SetGlobalFloat(s_HorizontalCurvaturePositiveZID, value);
}
}
public float verticalCurvaturePositiveZ
{
get => m_VerticalCurvaturePositiveZ;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_VerticalCurvaturePositiveZ = value;
Shader.SetGlobalFloat(s_VerticalCurvaturePositiveZID, value);
}
}
public float horizontalCurvatureNegativeZ
{
get => m_HorizontalCurvatureNegativeZ;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_HorizontalCurvatureNegativeZ = value;
Shader.SetGlobalFloat(s_HorizontalCurvatureNegativeZID, value);
}
}
public float verticalCurvatureNegativeZ
{
get => m_VerticalCurvatureNegativeZ;
set
{
value = Mathf.Clamp(value, -k_CurvatureClamp, k_CurvatureClamp);
m_VerticalCurvatureNegativeZ = value;
Shader.SetGlobalFloat(s_VerticalCurvatureNegativeZID, 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/[email protected]/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_POSITIVE_Z;
uniform float _CURVER_VERTICAL_CURVATURE_POSITIVE_Z;
uniform float _CURVER_HORIZONTAL_CURVATURE_NEGATIVE_Z;
uniform float _CURVER_VERTICAL_CURVATURE_NEGATIVE_Z;
#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 CurvatureModifier = lerp(
float2(_CURVER_HORIZONTAL_CURVATURE_NEGATIVE_Z, _CURVER_VERTICAL_CURVATURE_NEGATIVE_Z),
float2(_CURVER_HORIZONTAL_CURVATURE_POSITIVE_Z, _CURVER_VERTICAL_CURVATURE_POSITIVE_Z),
(sign(VertexPosWS.z) + 1) * 0.5f);
const float2 Curvature = pow(abs(DistanceToCamera - _CURVER_STRAIGHT_RENDER_DISTANCE), CURVER_CURVATURE_POWER)
* CurvatureModifier * 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 CurvatureModifier = lerp(
half2(_CURVER_HORIZONTAL_CURVATURE_NEGATIVE_Z, _CURVER_VERTICAL_CURVATURE_NEGATIVE_Z),
half2(_CURVER_HORIZONTAL_CURVATURE_POSITIVE_Z, _CURVER_VERTICAL_CURVATURE_POSITIVE_Z),
(sign(VertexPosWS.z) + 1) * 0.5f);
const half2 Curvature = pow(abs(DistanceToCamera - _CURVER_STRAIGHT_RENDER_DISTANCE), CURVER_CURVATURE_POWER)
* CurvatureModifier * 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