浏览代码

add visual eye setup + cleanup and dead code removal

/main
Lasse Jon Fuglsang Pedersen 4 年前
当前提交
cda478a6
共有 5 个文件被更改,包括 532 次插入340 次删除
  1. 461
      Runtime/EyeRenderer.cs
  2. 2
      Runtime/MeshTools/KdTree3.cs
  3. 201
      ShaderLibrary/Nodes_Eyes/EyeProperties.hlsl
  4. 197
      Editor/EyeRendererEditor.cs
  5. 11
      Editor/EyeRendererEditor.cs.meta

461
Runtime/EyeRenderer.cs


using UnityEngine;
using System;
using UnityEngine;
using UnityEngine.Serialization;
using Unity.DemoTeam.Attributes;
namespace Unity.DemoTeam.DigitalHuman

private Renderer rnd;
private MaterialPropertyBlock rndProps;
public float eyeRadius = 0.014265f;
[Space]
[Tooltip("The Z offset from the eye origin of the iris plane")]
public float eyeCorneaRadiusStart = 0.01325f;
[Tooltip("The Z offset from the cornea that contains limbus darkening (the dark ring around the iris)")]
public float eyeCorneaLimbusDarkeningOffset = 0.00075f;// was 0.001
[Range(1.0f, 1.4f), Tooltip("The index of refraction of a human cornea is 1.376, but our geometry works well with a value of 1.2. Affects magnitude of iris distortion from cornea lens.")]
public float eyeCorneaIndexOfRefraction = 1.3f;// was 1.2
[Range(0.0f, 1.0f)]
public float eyeCorneaSSSScale = 0.0f;
[Range(0.0f, 1.0f)]
public float eyeCorneaSmoothness = 0.917f;
public bool eyeCorneaDebug = false;
[Space]
public bool eyeIrisBentLightingDebug = false;
public bool eyeIrisBentLighting = true;
public float eyeIrisPlaneOffset = 0.002f;// was 0
[Range(-1.0f, 1.0f)]
public float eyeIrisConcavity = 0.0f;
[Space]
[Tooltip("Texture space pupil offset")]
public Vector2 eyePupilOffset = new Vector2(0.002f, 0.016f);
[Tooltip("Texture space pupil diameter")]
public float eyePupilDiameter = 0.095f;
[Tooltip("Texture space pupil falloff")]
public float eyePupilFalloff = 0.015f;
[Tooltip("Texture space pupil scale")]
public float eyePupilScale = 1.0f;
[Space]
public bool eyeWrappedLighting = false;
[Range(0.0f, 1.0f)]
public float eyeWrappedLightingCosine = 0.5f;
[Range(1.0f, 4.0f)]
public float eyeWrappedLightingPower = 4.0f;
// http://hyperphysics.phy-astr.gsu.edu/hbase/vision/eyescal.html
const float IOR_HUMAN_AQUEOUS_HUMOR = 1.336f;
const float IOR_HUMAN_CORNEA = 1.376f;

const float IOR_HUMAN_TEARS = 1.33698f;
[Space]
[Range(1.0f, 2.0f)]
public float eyeLitIORCornea = IOR_HUMAN_CORNEA;
[Range(1.0f, 2.0f)]
public float eyeLitIORSclera = IOR_HUMAN_TEARS;
[Header("Geometry")]
public float geometryRadius = 0.014265f;
public Vector3 geometryOrigin = Vector3.zero;
public Vector3 geometryAngle = Vector3.zero;
[Space]
public Transform eyePolygonContainer;
private const int eyePolygonSize = 4;// should match size in EyeLitForward.shader
private Vector4[] eyePolygonOS = new Vector4[eyePolygonSize];
private Vector3 eyeAsgOriginOS = new Vector3(0.0f, 0.0f, 0.0f);
private Vector3 eyeAsgMeanOS = new Vector3(0.0f, 0.0f, 1.0f);
private Vector3 eyeAsgTangentOS = new Vector3(1.0f, 0.0f, 0.0f);
private Vector3 eyeAsgBitangentOS = new Vector3(0.0f, 1.0f, 0.0f);
private Vector2 eyeAsgSharpness = new Vector2(1.25f, 9.0f);
[Range(1e-1f, 128.0f)]
public float eyeAsgPower = 16.0f;
[Range(1e-7f, 1e-1f)]
public float eyeAsgThreshold = 1e-1f;
private Vector2 eyeAsgThresholdScaleBias = new Vector2(1.0f, 0.0f);
[Range(0.0f, 1.0f)]
public float eyeAsgModulateAlbedo = 0.5f;
[Header("Sclera")]
[FormerlySerializedAs("eyeLitIORSclera"), Range(1.0f, 2.0f)]
public float scleraIOR = IOR_HUMAN_TEARS;
[Space]
public ConeMapping coneMapping = ConeMapping.ClosingAxisSpaceSplit;
[Header("Cornea")]
public bool corneaCrossSectionEditMode = false;
[FormerlySerializedAs("eyeCorneaRadiusStart")]
public float corneaCrossSection = 0.01325f;
[FormerlySerializedAs("eyeIrisPlaneOffset")]
public float corneaCrossSectionIrisOffset = 0.002f;
[FormerlySerializedAs("eyeCorneaLimbusDarkeningOffset")]
public float corneaCrossSectionFadeOffset = 0.00075f;
[FormerlySerializedAs("eyeLitIORCornea"), Range(1.0f, 2.0f)]
public float corneaIOR = IOR_HUMAN_CORNEA;
[FormerlySerializedAs("eyeCorneaIndexOfRefraction"), Range(1.0f, 2.0f)]
public float corneaIORIrisRay = 1.3f;
[FormerlySerializedAs("eyeCorneaSmoothness"), Range(0.0f, 1.0f)]
public float corneaSmoothness = 0.917f;
[FormerlySerializedAs("eyeCorneaSSSScale"), Range(0.0f, 1.0f)]
public float corneaSSS = 0.0f;
[Header("Iris")]
[FormerlySerializedAs("eyeIrisBentLighting")]
public bool irisRefractedLighting = true;
[Tooltip("Enables constant step (being the specified iris offset) along the refracted ray below the cornea cross section, rather than stepping all the way to the plane defined by the iris offset. Effectively curves the iris towards the refracted ray.")]
public bool irisRefractedOffset = true;
[Header("Pupil")]
[FormerlySerializedAs("eyePupilOffset")]
public Vector2 pupilUVOffset = new Vector2(0.002f, 0.016f);
[FormerlySerializedAs("eyePupilDiameter")]
public float pupilUVDiameter = 0.095f;
[FormerlySerializedAs("eyePupilFalloff")]
public float pupilUVFalloff = 0.015f;
[FormerlySerializedAs("eyePupilScale"), Range(0.5f, 2.2f)]
public float pupilScale = 1.0f;
[Header("Occlusion")]
[FormerlySerializedAs("eyeAsgPower"), Range(1e-1f, 128.0f)]
public float asgPower = 10.0f;
[FormerlySerializedAs("eyeAsgThreshold"), Range(1e-7f, 1e-1f)]
public float asgThreshold = 1e-7f;
[FormerlySerializedAs("eyeAsgModulateAlbedo"), Range(0.0f, 1.0f)]
public float asgModulateAlbedo = 0.65f;
[FormerlySerializedAs("eyePolygonContainer")]
public Transform asgMarkerPolygon;
[Space]
public ConeMapping coneMapping = ConeMapping.ClosingAxisSpaceSplit;
[VisibleIf("coneMapping", ConeMapping.ClosingAxisSpaceSplit)]
public float coneOriginOffset = 1.0f;
[VisibleIf("coneMapping", ConeMapping.ClosingAxisSpaceSplit)]

public bool coneDebug = false;
[NonSerialized]
public Vector3 asgOriginOS = new Vector3(0.0f, 0.0f, 0.0f);
[NonSerialized]
public Vector3 asgMeanOS = new Vector3(0.0f, 0.0f, 1.0f);
[NonSerialized]
public Vector3 asgTangentOS = new Vector3(1.0f, 0.0f, 0.0f);
[NonSerialized]
public Vector3 asgBitangentOS = new Vector3(0.0f, 1.0f, 0.0f);
[NonSerialized]
public Vector2 asgSharpness = new Vector2(1.25f, 9.0f);
[NonSerialized]
public Vector2 asgThresholdScaleBias = new Vector2(1.0f, 0.0f);
void Awake()
{
rnd = GetComponent<Renderer>();

// amplitude * e^(pow(sharpness * (cosTheta - 1), power)) = epsilon
// e^(pow(sharpness * (cosTheta - 1), power)) = epsilon / amplitude
// pow(sharpness * (cosTheta - 1), power) = log(epsilon / amplitude)
// pow(sharpness * (cosTheta - 1), power) = log(epsilon) - log(amplitude)
// sharpness * (cosTheta - 1) = pow(log(epsilon) - log(amplitude), 1.0 / power)
// sharpness = pow(log(epsilon) - log(amplitude), 1.0 / power) / (cosTheta - 1)
// amplitude * e^(pow(sharpness * (cosTheta - 1), power)) = epsilon
// e^(pow(sharpness * (cosTheta - 1), power)) = epsilon / amplitude
// pow(sharpness * (cosTheta - 1), power) = log(epsilon / amplitude)
// pow(sharpness * (cosTheta - 1), power) = log(epsilon) - log(amplitude)
// sharpness * (cosTheta - 1) = pow(log(epsilon) - log(amplitude), 1.0 / power)
// sharpness = pow(log(epsilon) - log(amplitude), 1.0 / power) / (cosTheta - 1)
void LateUpdate()
void AsgParameterUpdate()
var eyePolygonComplete = (eyePolygonContainer != null) && (eyePolygonContainer.childCount == eyePolygonSize);
if (eyePolygonComplete)
Vector3 osMarkerL = (1.1f * geometryRadius) * Vector3.Normalize(Vector3.forward + Vector3.left);
Vector3 osMarkerR = (1.1f * geometryRadius) * Vector3.Normalize(Vector3.forward + Vector3.right);
Vector3 osMarkerT = (1.1f * geometryRadius) * Vector3.Normalize(Vector3.forward + 0.35f * Vector3.up);
Vector3 osMarkerB = (1.1f * geometryRadius) * Vector3.Normalize(Vector3.forward + 0.35f * Vector3.down);
if (asgMarkerPolygon != null && asgMarkerPolygon.childCount == 4)
for (int i = 0; i != eyePolygonSize; i++)
{
eyePolygonOS[i] = this.transform.InverseTransformPoint(eyePolygonContainer.GetChild(i).position);
if (coneDebug)
{
DrawRayLocal(Vector3.zero, eyePolygonOS[i], Color.white);
}
}
// 1
// .-´ `-.
// 0 2
// `-. .-´
// 3
float cosThetaTangent = 0.0f;
float cosThetaBitangent = 0.0f;
osMarkerL = this.transform.InverseTransformPoint(asgMarkerPolygon.GetChild(0).position);
osMarkerR = this.transform.InverseTransformPoint(asgMarkerPolygon.GetChild(2).position);
osMarkerT = this.transform.InverseTransformPoint(asgMarkerPolygon.GetChild(1).position);
osMarkerB = this.transform.InverseTransformPoint(asgMarkerPolygon.GetChild(3).position);
}
switch (coneMapping)
{
case ConeMapping.ObjectSpaceMean:
{
eyeAsgOriginOS = Vector3.zero;
eyeAsgMeanOS = Vector3.Normalize(
Vector3.Normalize(eyePolygonOS[0])
+ Vector3.Normalize(eyePolygonOS[1])
+ Vector3.Normalize(eyePolygonOS[2])
+ Vector3.Normalize(eyePolygonOS[3])
);
eyeAsgBitangentOS = Vector3.Normalize(
Vector3.Cross(eyeAsgMeanOS, Vector3.Normalize(eyePolygonOS[2] - eyePolygonOS[0]))
);
eyeAsgTangentOS = Vector3.Cross(eyeAsgBitangentOS, eyeAsgMeanOS);
if (coneDebug)
{
DrawLocalRay(Vector3.zero, osMarkerT, Color.white);
DrawLocalRay(Vector3.zero, osMarkerR, Color.white);
DrawLocalRay(Vector3.zero, osMarkerB, Color.white);
DrawLocalRay(Vector3.zero, osMarkerL, Color.white);
}
float cosThetaMeanToLeft = Vector3.Dot(Vector3.Normalize(eyePolygonOS[0]), eyeAsgMeanOS);
float cosThetaMeanToRight = Vector3.Dot(Vector3.Normalize(eyePolygonOS[2]), eyeAsgMeanOS);
float cosThetaMeanToTop = Vector3.Dot(Vector3.Normalize(eyePolygonOS[1]), eyeAsgMeanOS);
float cosThetaMeanToBottom = Vector3.Dot(Vector3.Normalize(eyePolygonOS[3]), eyeAsgMeanOS);
float cosThetaTangent = 0.0f;
float cosThetaBitangent = 0.0f;
cosThetaTangent = (cosThetaMeanToLeft + cosThetaMeanToRight) * 0.5f;
cosThetaBitangent = (cosThetaMeanToTop + cosThetaMeanToBottom) * 0.5f;
}
break;
case ConeMapping.ClosingAxisSpaceSplit:
{
var eyePolygonRot = Quaternion.Euler(coneBias.y, coneBias.x, coneBias.z);
switch (coneMapping)
{
case ConeMapping.ObjectSpaceMean:
{
asgOriginOS = geometryOrigin;
asgMeanOS = Vector3.Normalize(
Vector3.Normalize(osMarkerT) +
Vector3.Normalize(osMarkerR) +
Vector3.Normalize(osMarkerB) +
Vector3.Normalize(osMarkerL)
);
asgBitangentOS = Vector3.Cross(asgMeanOS, Vector3.Normalize(osMarkerR - osMarkerL));
asgTangentOS = Vector3.Cross(asgBitangentOS, asgMeanOS);
for (int i = 0; i != eyePolygonSize; i++)
{
eyePolygonOS[i] = eyePolygonRot * eyePolygonOS[i];
}
float cosThetaMeanToLeft = Vector3.Dot(Vector3.Normalize(osMarkerL), asgMeanOS);
float cosThetaMeanToRight = Vector3.Dot(Vector3.Normalize(osMarkerR), asgMeanOS);
float cosThetaMeanToTop = Vector3.Dot(Vector3.Normalize(osMarkerT), asgMeanOS);
float cosThetaMeanToBottom = Vector3.Dot(Vector3.Normalize(osMarkerB), asgMeanOS);
var closingPlaneNormal = Vector3.Normalize(eyePolygonOS[2] - eyePolygonOS[0]);
var closingPlaneOrigin = Vector3.ProjectOnPlane(eyePolygonOS[0], closingPlaneNormal);
cosThetaTangent = (cosThetaMeanToLeft + cosThetaMeanToRight) * 0.5f;
cosThetaBitangent = (cosThetaMeanToTop + cosThetaMeanToBottom) * 0.5f;
}
break;
var closingPlanePosTop = Vector3.ProjectOnPlane(eyePolygonOS[1], closingPlaneNormal) - closingPlaneOrigin;
var closingPlanePosBottom = Vector3.ProjectOnPlane(eyePolygonOS[3], closingPlaneNormal) - closingPlaneOrigin;
var closingPlaneDirTop = Vector3.Normalize(closingPlanePosTop);
var closingPlaneDirBottom = Vector3.Normalize(closingPlanePosBottom);
case ConeMapping.ClosingAxisSpaceSplit:
{
var asgPolygonRot = Quaternion.Euler(coneBias.y, coneBias.x, coneBias.z);
osMarkerL = asgPolygonRot * osMarkerL;
osMarkerR = asgPolygonRot * osMarkerR;
osMarkerT = asgPolygonRot * osMarkerT;
osMarkerB = asgPolygonRot * osMarkerB;
var closingPlaneForward = Vector3.Normalize(closingPlaneDirTop + closingPlaneDirBottom);
{
closingPlaneOrigin -= closingPlaneForward * (0.01f * coneOriginOffset);
//TODO pick an origin that sends the resulting forward vector through the original origin in the closing plane
var closingPlaneNormal = Vector3.Normalize(osMarkerR - osMarkerL);
var closingPlaneOrigin = Vector3.ProjectOnPlane(osMarkerL, closingPlaneNormal);
closingPlanePosTop = Vector3.ProjectOnPlane(eyePolygonOS[1], closingPlaneNormal) - closingPlaneOrigin;
closingPlanePosBottom = Vector3.ProjectOnPlane(eyePolygonOS[3], closingPlaneNormal) - closingPlaneOrigin;
closingPlaneDirTop = Vector3.Normalize(closingPlanePosTop);
closingPlaneDirBottom = Vector3.Normalize(closingPlanePosBottom);
var closingPlanePosTop = Vector3.ProjectOnPlane(osMarkerT, closingPlaneNormal) - closingPlaneOrigin;
var closingPlanePosBottom = Vector3.ProjectOnPlane(osMarkerB, closingPlaneNormal) - closingPlaneOrigin;
var closingPlaneDirTop = Vector3.Normalize(closingPlanePosTop);
var closingPlaneDirBottom = Vector3.Normalize(closingPlanePosBottom);
closingPlaneForward = Vector3.Normalize(closingPlaneDirTop + closingPlaneDirBottom);
}
var closingPlaneForward = Vector3.Normalize(closingPlaneDirTop + closingPlaneDirBottom);
{
closingPlaneOrigin -= closingPlaneForward * (0.01f * coneOriginOffset);
//TODO pick an origin that sends the resulting forward vector through the original origin in the closing plane
var openingPosLeft = (Vector3)eyePolygonOS[0] - closingPlaneOrigin;
var openingPosRight = (Vector3)eyePolygonOS[2] - closingPlaneOrigin;
var openingDirLeft = Vector3.Normalize(openingPosLeft);
var openingDirRight = Vector3.Normalize(openingPosRight);
closingPlanePosTop = Vector3.ProjectOnPlane(osMarkerT, closingPlaneNormal) - closingPlaneOrigin;
closingPlanePosBottom = Vector3.ProjectOnPlane(osMarkerB, closingPlaneNormal) - closingPlaneOrigin;
closingPlaneDirTop = Vector3.Normalize(closingPlanePosTop);
closingPlaneDirBottom = Vector3.Normalize(closingPlanePosBottom);
var closingPlaneAltitude = coneScale.y * 0.5f * Mathf.Deg2Rad * Vector3.Angle(closingPlaneDirTop, closingPlaneDirBottom);
var closingPlaneAzimuth = coneScale.x * 0.5f * Mathf.Deg2Rad * Vector3.Angle(openingDirLeft, openingDirRight);
closingPlaneForward = Vector3.Normalize(closingPlaneDirTop + closingPlaneDirBottom);
}
if (coneDebug)
{
DrawRayLocal(closingPlaneOrigin, closingPlanePosTop, Color.yellow);
DrawRayLocal(closingPlaneOrigin, closingPlanePosBottom, Color.yellow);
DrawRayLocal(closingPlaneOrigin, openingPosLeft, Color.yellow);
DrawRayLocal(closingPlaneOrigin, openingPosRight, Color.yellow);
}
var openingPosLeft = (osMarkerL - closingPlaneOrigin);
var openingPosRight = (osMarkerR - closingPlaneOrigin);
var openingDirLeft = Vector3.Normalize(openingPosLeft);
var openingDirRight = Vector3.Normalize(openingPosRight);
eyeAsgOriginOS = closingPlaneOrigin;
eyeAsgMeanOS = closingPlaneForward;
eyeAsgTangentOS = closingPlaneNormal;
eyeAsgBitangentOS = Vector3.Normalize(Vector3.Cross(eyeAsgMeanOS, eyeAsgTangentOS));
var closingPlaneAltitude = coneScale.y * 0.5f * Mathf.Deg2Rad * Vector3.Angle(closingPlaneDirTop, closingPlaneDirBottom);
var closingPlaneAzimuth = coneScale.x * 0.5f * Mathf.Deg2Rad * Vector3.Angle(openingDirLeft, openingDirRight);
cosThetaTangent = Mathf.Cos(closingPlaneAzimuth);
cosThetaBitangent = Mathf.Cos(closingPlaneAltitude);
if (coneDebug)
{
DrawLocalRay(closingPlaneOrigin, closingPlanePosTop, Color.yellow);
DrawLocalRay(closingPlaneOrigin, closingPlanePosBottom, Color.yellow);
DrawLocalRay(closingPlaneOrigin, openingPosLeft, Color.yellow);
DrawLocalRay(closingPlaneOrigin, openingPosRight, Color.yellow);
break;
}
if (coneDebug)
{
DrawRayLocal(eyeAsgOriginOS, eyeAsgMeanOS, Color.red);
DrawRayLocal(eyeAsgOriginOS, eyeAsgBitangentOS, Color.green);
DrawRayLocal(eyeAsgOriginOS, eyeAsgTangentOS, Color.blue);
}
asgOriginOS = closingPlaneOrigin;
asgMeanOS = closingPlaneForward;
asgTangentOS = closingPlaneNormal;
asgBitangentOS = Vector3.Normalize(Vector3.Cross(asgMeanOS, asgTangentOS));
eyeAsgSharpness.x = AsgSharpnessFromThreshold(eyeAsgThreshold, 1.0f, eyeAsgPower, cosThetaTangent);
eyeAsgSharpness.y = AsgSharpnessFromThreshold(eyeAsgThreshold, 1.0f, eyeAsgPower, cosThetaBitangent);
cosThetaTangent = Mathf.Cos(closingPlaneAzimuth);
cosThetaBitangent = Mathf.Cos(closingPlaneAltitude);
}
break;
eyeAsgThresholdScaleBias.x = 1.0f / (1.0f - eyeAsgThreshold);
eyeAsgThresholdScaleBias.y = -eyeAsgThreshold / (1.0f - eyeAsgThreshold);
}
else
{
for (int i = 0; i != eyePolygonSize; i++)
{
eyePolygonOS[i] = Vector4.zero;
}
}
}// switch (coneMapping)
if (eyeCorneaDebug)
if (coneDebug)
var pos = this.transform.position;
var rot = this.transform.rotation;
var dirBF = rot * Vector3.forward;
var dirBT = rot * Vector3.up;
var dirLR = rot * Vector3.right;
var rot45 = rot * Quaternion.AngleAxis(45.0f, Vector3.forward);
var dirBT45 = rot45 * dirBT;
var dirLR45 = rot45 * dirLR;
var orange = Color.Lerp(Color.yellow, Color.red, 0.5f);
DrawLocalRay(asgOriginOS, (1.5f * geometryRadius) * asgMeanOS, orange);
DrawLocalRay(asgOriginOS, (1.5f * geometryRadius) * asgBitangentOS, orange);
DrawLocalRay(asgOriginOS, (1.5f * geometryRadius) * asgTangentOS, orange);
}
var posIris = pos + dirBF * eyeCorneaRadiusStart;
var posFade = pos + dirBF * (eyeCorneaRadiusStart + eyeCorneaLimbusDarkeningOffset);
var posSide = pos + dirLR * eyeRadius;
asgSharpness.x = AsgSharpnessFromThreshold(asgThreshold, 1.0f, asgPower, cosThetaTangent);
asgSharpness.y = AsgSharpnessFromThreshold(asgThreshold, 1.0f, asgPower, cosThetaBitangent);
var lineIris = eyeRadius * 0.6f;
{
Debug.DrawLine(posIris - dirBT * lineIris, posIris + dirBT * lineIris, Color.red);
Debug.DrawLine(posIris - dirLR * lineIris, posIris + dirLR * lineIris, Color.red);
Debug.DrawLine(posIris - dirBT45 * lineIris, posIris + dirBT45 * lineIris, Color.red);
Debug.DrawLine(posIris - dirLR45 * lineIris, posIris + dirLR45 * lineIris, Color.red);
}
var lineFade = eyeRadius * 0.5f;
{
Debug.DrawLine(posFade - dirBT45 * lineFade, posFade + dirBT45 * lineFade, Color.magenta);
Debug.DrawLine(posFade - dirLR45 * lineFade, posFade + dirLR45 * lineFade, Color.magenta);
Debug.DrawLine(posFade - dirBT45 * lineFade, posIris - dirBT45 * lineFade, Color.magenta);
Debug.DrawLine(posFade + dirBT45 * lineFade, posIris + dirBT45 * lineFade, Color.magenta);
Debug.DrawLine(posFade - dirLR45 * lineFade, posIris - dirLR45 * lineFade, Color.magenta);
Debug.DrawLine(posFade + dirLR45 * lineFade, posIris + dirLR45 * lineFade, Color.magenta);
}
asgThresholdScaleBias.x = 1.0f / (1.0f - asgThreshold);
asgThresholdScaleBias.y = -asgThreshold / (1.0f - asgThreshold);
}
var lineSide = eyeRadius * 0.25f;
{
Debug.DrawLine(posSide - dirBT * lineSide, posSide + dirBT * lineSide, Color.blue);
Debug.DrawLine(posSide - dirBF * lineSide, posSide + dirBF * lineSide, Color.blue);
}
}
void LateUpdate()
{
AsgParameterUpdate();
if (rndProps == null)
rndProps = new MaterialPropertyBlock();

rndProps.SetFloat("_EyeRadius", eyeRadius);
rndProps.SetFloat("_EyeCorneaRadiusStart", eyeCorneaRadiusStart);
rndProps.SetFloat("_EyeCorneaLimbusDarkeningOffset", eyeCorneaLimbusDarkeningOffset);
rndProps.SetFloat("_EyeCorneaIndexOfRefraction", eyeCorneaIndexOfRefraction);
rndProps.SetFloat("_EyeCorneaIndexOfRefractionRatio", 1.0f / eyeCorneaIndexOfRefraction);
rndProps.SetFloat("_EyeCorneaSSS", eyeCorneaSSSScale);
rndProps.SetFloat("_EyeCorneaSmoothness", eyeCorneaSmoothness);
var geometryLookRotation = Quaternion.Euler(geometryAngle);
rndProps.SetFloat("_EyeIrisBentLightingDebug", eyeIrisBentLightingDebug ? 1 : 0);
rndProps.SetFloat("_EyeIrisBentLighting", eyeIrisBentLighting ? 1 : 0);
rndProps.SetFloat("_EyeIrisPlaneOffset", eyeIrisPlaneOffset);
rndProps.SetFloat("_EyeIrisConcavity", eyeIrisConcavity);
rndProps.SetFloat("_EyeGeometryRadius", geometryRadius);
rndProps.SetVector("_EyeGeometryOrigin", geometryOrigin);
rndProps.SetVector("_EyeGeometryForward", Vector3.Normalize(geometryLookRotation * Vector3.forward));
rndProps.SetVector("_EyeGeometryRight", Vector3.Normalize(geometryLookRotation * Vector3.right));
rndProps.SetVector("_EyeGeometryUp", Vector3.Normalize(geometryLookRotation * Vector3.up));
rndProps.SetVector("_EyePupilOffset", eyePupilOffset);
rndProps.SetFloat("_EyePupilDiameter", eyePupilDiameter);
rndProps.SetFloat("_EyePupilFalloff", eyePupilFalloff);
rndProps.SetFloat("_EyePupilScale", eyePupilScale);
if (eyeWrappedLighting)
if (corneaCrossSectionEditMode && Application.isEditor)
rndProps.SetFloat("_EyeWrappedLightingCosine", eyeWrappedLightingCosine);
rndProps.SetFloat("_EyeWrappedLightingPower", eyeWrappedLightingPower);
rndProps.SetFloat("_EyeCorneaCrossSection", 1e+7f);
rndProps.SetFloat("_EyeCorneaCrossSectionIrisOffset", 0.0f);
rndProps.SetFloat("_EyeCorneaCrossSectionFadeOffset", 0.0f);
rndProps.SetFloat("_EyeWrappedLightingCosine", 0.0f);
rndProps.SetFloat("_EyeWrappedLightingPower", 1.0f);
rndProps.SetFloat("_EyeCorneaCrossSection", corneaCrossSection);
rndProps.SetFloat("_EyeCorneaCrossSectionIrisOffset", Mathf.Max(0.0f, corneaCrossSectionIrisOffset));
rndProps.SetFloat("_EyeCorneaCrossSectionFadeOffset", Mathf.Max(0.0f, corneaCrossSectionFadeOffset));
rndProps.SetFloat("_EyeLitIORCornea", eyeLitIORCornea);
rndProps.SetFloat("_EyeLitIORSclera", eyeLitIORSclera);
rndProps.SetFloat("_EyeCorneaIOR", corneaIOR);
rndProps.SetFloat("_EyeCorneaIORIrisRay", corneaIORIrisRay);
rndProps.SetFloat("_EyeCorneaSmoothness", corneaSmoothness);
rndProps.SetFloat("_EyeCorneaSSS", corneaSSS);
rndProps.SetFloat("_EyeIrisRefractedLighting", irisRefractedLighting ? 1 : 0);
rndProps.SetFloat("_EyeIrisRefractedOffset", irisRefractedOffset ? 1 : 0);
rndProps.SetVector("_EyePupilUVOffset", pupilUVOffset);
rndProps.SetFloat("_EyePupilUVDiameter", pupilUVDiameter);
rndProps.SetFloat("_EyePupilUVFalloff", pupilUVFalloff);
rndProps.SetFloat("_EyePupilScale", pupilScale);
rndProps.SetVector("_EyeAsgOriginOS", eyeAsgOriginOS);
rndProps.SetVector("_EyeAsgMeanOS", eyeAsgMeanOS);
rndProps.SetVector("_EyeAsgTangentOS", eyeAsgTangentOS);
rndProps.SetVector("_EyeAsgBitangentOS", eyeAsgBitangentOS);
rndProps.SetVector("_EyeAsgSharpness", eyeAsgSharpness);
rndProps.SetFloat("_EyeAsgPower", eyeAsgPower);
rndProps.SetVector("_EyeAsgThresholdScaleBias", eyeAsgThresholdScaleBias);
rndProps.SetFloat("_EyeAsgModulateAlbedo", eyeAsgModulateAlbedo);
rndProps.SetFloat("_EyeScleraIOR", scleraIOR);
rndProps.SetFloat("_EyeAsgPower", asgPower);
rndProps.SetVector("_EyeAsgSharpness", asgSharpness);
rndProps.SetVector("_EyeAsgThresholdScaleBias", asgThresholdScaleBias);
rndProps.SetVector("_EyeAsgOriginOS", asgOriginOS);
rndProps.SetVector("_EyeAsgMeanOS", asgMeanOS);
rndProps.SetVector("_EyeAsgTangentOS", asgTangentOS);
rndProps.SetVector("_EyeAsgBitangentOS", asgBitangentOS);
rndProps.SetFloat("_EyeAsgModulateAlbedo", asgModulateAlbedo);
void DrawRayLocal(Vector3 localPosition, Vector3 localVector, Color color)
void DrawLocalRay(Vector3 p, Vector3 v, Color color)
Vector3 worldPosition = this.transform.TransformPoint(localPosition);
Vector3 worldVector = this.transform.TransformVector(localVector);
Vector3 worldPosition = this.transform.TransformPoint(p);
Vector3 worldVector = this.transform.TransformVector(v);
Debug.DrawRay(worldPosition, worldVector, color);
}
}

2
Runtime/MeshTools/KdTree3.cs


unsafe static void SelectByAxis(int nth, Point3* points, int length, int axis)
{
// note: this function adapted from public domain variants listed in KdTreeUtils
// note: this function adapted from public domain variants listed in KdTreeUtils.cs
const int strideLsh = 2;
var i = 0;

201
ShaderLibrary/Nodes_Eyes/EyeProperties.hlsl


#ifndef __EYEPROPERTIES_H__
#define __EYEPROPERTIES_H__
float _EyeRadius;
float _EyeGeometryRadius;
float3 _EyeGeometryOrigin;
float3 _EyeGeometryForward;
float3 _EyeGeometryRight;
float3 _EyeGeometryUp;
float _EyeScleraIOR;
float _EyeCorneaRadiusStart;
float _EyeCorneaLimbusDarkeningOffset;
float _EyeCorneaIndexOfRefraction;
float _EyeCorneaIndexOfRefractionRatio;
float _EyeCorneaSSS;
float _EyeCorneaCrossSection;
float _EyeCorneaCrossSectionIrisOffset;
float _EyeCorneaCrossSectionFadeOffset;
float _EyeCorneaIOR;
float _EyeCorneaIORIrisRay;
float _EyeCorneaSSS;
float _EyeIrisBentLightingDebug;
float _EyeIrisBentLighting;
float _EyeIrisPlaneOffset;
float _EyeIrisConcavity;
float _EyeIrisRefractedLighting;
float _EyeIrisRefractedOffset;
float2 _EyePupilOffset;
float _EyePupilDiameter;
float _EyePupilFalloff;
float2 _EyePupilUVOffset;
float _EyePupilUVDiameter;
float _EyePupilUVFalloff;
float _EyeWrappedLightingCosine;
float _EyeWrappedLightingPower;
float _EyeAsgPower;
float _EyeAsgModulateAlbedo;
float _EyeLitIORCornea;
float _EyeLitIORSclera;
float _EyeAsgPower;
float2 _EyeAsgSharpness;
float2 _EyeAsgSharpness;
float _EyeAsgModulateAlbedo;
// (Anisotropic) Higher-Order Gaussian Distribution aka (Anisotropic) Super-Gaussian Distribution extended to be evaluated across the unit sphere.
//
// Source for Super-Gaussian Distribution:
// https://en.wikipedia.org/wiki/Gaussian_function#Higher-order_Gaussian_or_super-Gaussian_function
//
// Source for Anisotropic Spherical Gaussian Distribution:
// http://www.jp.square-enix.com/info/library/pdf/Virtual%20Spherical%20Gaussian%20Lights%20for%20Real-Time%20Glossy%20Indirect%20Illumination%20(supplemental%20material).pdf
//
// (Anisotropic) Higher-Order Gaussian Distribution aka (Anisotropic) Super-Gaussian Distribution extended to be evaluated across the unit sphere.
//
// Source for Super-Gaussian Distribution:
// https://en.wikipedia.org/wiki/Gaussian_function#Higher-order_Gaussian_or_super-Gaussian_function
//
// Source for Anisotropic Spherical Gaussian Distribution:
// http://www.jp.square-enix.com/info/library/pdf/Virtual%20Spherical%20Gaussian%20Lights%20for%20Real-Time%20Glossy%20Indirect%20Illumination%20(supplemental%20material).pdf
//
float amplitude;
float2 sharpness;
float power;

return a.amplitude * max(0.0, dDotM) * exp(-pow(abs(-a.sharpness.x * dDotT * dDotT - a.sharpness.y * dDotB * dDotB), a.power));
}
struct EyeData
struct EyeProperties
{
float2 refractedUV;
float maskCornea;

float corneaSSS;
};
EyeData GetEyeData(in float3 surfacePositionOS, in float3 surfaceNormalOS)
float2 ResolvePlanarUV(in float3 positionOS)
{
float3 r = (positionOS - _EyeGeometryOrigin) / (2.0 * _EyeGeometryRadius);
float3 rp = r - _EyeGeometryForward * dot(_EyeGeometryForward, r);
return float2(
0.5 + dot(rp, _EyeGeometryRight),
0.5 + dot(rp, _EyeGeometryUp)
);
}
EyeProperties ResolveEyeProperties(in float3 surfacePositionOS, in float3 surfaceNormalOS)
// Eye geometry must be centered at origin in object space, planar uv mapped along Z, and look straight down +Z.
const float3 irisPlaneNormalOS = float3(0.0, 0.0, 1.0);
const float3 irisPlaneOriginOS = irisPlaneNormalOS * _EyeCorneaRadiusStart;
// Currently using a user defined scale factor to go from object space to [0, 1] uv range, since our eye geometry
// is not normalized radius in object space.
const float2 uvFromOSScale = float2(-0.5, 0.5) / _EyeRadius;
const float2 uvFromOSBias = float2(0.5, 0.5);
// prepare texture coordinates for top and bottom layer
float2 uv0 = ResolvePlanarUV(surfacePositionOS);
float2 uv1 = uv0;
// Calculate texture coordinates for top and bottom layer.
float2 uv0 = surfacePositionOS.xy * uvFromOSScale + uvFromOSBias;
float2 uv1 = uv0;
// if the surface is above the cornea cross-section, then we refract the view ray and intersect
// this new ray with the iris, in order to obtain the texture coordinates for the bottom layer
float3 crossSectionOrigin = _EyeGeometryOrigin + _EyeGeometryForward * _EyeCorneaCrossSection;
float crossSectionDistance = dot(_EyeGeometryForward, surfacePositionOS - crossSectionOrigin);
// If eye geometry is passing into the positive half-space of our iris plane, it must be the cornea geometry.
// Refract view ray based on human cornea index of refraction, and intersect it with the iris plane.
float irisPlaneDistance = dot(irisPlaneNormalOS, surfacePositionOS - irisPlaneOriginOS);
if (irisPlaneDistance > 0.0)
if (crossSectionDistance > 0.0)
float3 refractedViewDirectionOS = refract(viewDirectionOS, surfaceNormalOS, _EyeCorneaIndexOfRefractionRatio);
float3 refractedRayOS = refract(viewDirectionOS, surfaceNormalOS, 1.0 / _EyeCorneaIORIrisRay);
float refractedRayCosA = -dot(_EyeGeometryForward, refractedRayOS);
float refractedRayT;
{
if (_EyeIrisRefractedOffset)
refractedRayT = (crossSectionDistance / refractedRayCosA) + _EyeCorneaCrossSectionIrisOffset;
else
refractedRayT = (crossSectionDistance + _EyeCorneaCrossSectionIrisOffset) / refractedRayCosA;
}
float cosA = -dot(irisPlaneNormalOS, refractedViewDirectionOS);
float irisDistance = (irisPlaneDistance / cosA) + _EyeIrisPlaneOffset;
float3 irisPositionOS = surfacePositionOS + irisDistance * refractedViewDirectionOS;
uv1 = irisPositionOS.xy * uvFromOSScale + uvFromOSBias;
uv1 = ResolvePlanarUV(surfacePositionOS + refractedRayOS * refractedRayT);
// Linear remapping of the iris to allow dilation of the pupil.
// perform linear uv remapping of the bottom layer to allow dilation of the pupil
float2 centerPos = float2(0.5, 0.5) - _EyePupilOffset;
float2 centerPos = float2(0.5, 0.5) - _EyePupilUVOffset;
float sampleIrisMax = 2.2 * _EyePupilDiameter;//TODO replace with user param
float sampleIrisMin = 0.5 * _EyePupilDiameter;
float sampleIrisMax = 2.2 * _EyePupilUVDiameter;//TODO replace with user param
float sampleIrisMin = 0.5 * _EyePupilUVDiameter;
float outputIrisMax = sampleIrisMax;
float outputIrisMin = clamp(sampleIrisMin * _EyePupilScale, FLT_EPS, sampleIrisMax - FLT_EPS);

}
// Prepare blend masks for cornea and sclera.
float maskCornea = smoothstep(0.0, _EyeCorneaLimbusDarkeningOffset, irisPlaneDistance);
float maskSclera = smoothstep(0.0, _EyeCorneaLimbusDarkeningOffset, -irisPlaneDistance);
// resolve blend masks for sclera and cornea
float maskSclera = smoothstep(0.0, _EyeCorneaCrossSectionFadeOffset, -crossSectionDistance);
float maskCornea = smoothstep(0.0, _EyeCorneaCrossSectionFadeOffset, crossSectionDistance);
// Prepare blend mask for the pupil.
float distPupil = length(uv1 - float2(0.5, 0.5) + _EyePupilOffset) - (0.5 * _EyePupilDiameter);
float maskPupil = smoothstep(_EyePupilFalloff, 0.0, distPupil);
// resolve blend mask for the pupil
float distPupil = length(uv1 - float2(0.5, 0.5) + _EyePupilUVOffset) - (0.5 * _EyePupilUVDiameter);
float maskPupil = smoothstep(_EyePupilUVFalloff, 0.0, distPupil);
// Construct a function across the surface of the eye that roughly approximates visiblity function (eye lids occlude eye),
// but are too thin / small to rely on typical shadow mapping techniques to capture high enough quality visiblity.
AnisotropicSphericalSuperGaussian a;
a.amplitude = 1.0;
a.power = _EyeAsgPower;
a.sharpness = _EyeAsgSharpness;
a.mean = _EyeAsgMeanOS;
a.tangent = _EyeAsgTangentOS;
a.bitangent = _EyeAsgBitangentOS;
// construct a function across the surface of the eye that roughly approximates visiblity function (eye lids occlude eye),
// but are too thin / small to rely on typical shadow mapping techniques to capture high enough quality visiblity
AnisotropicSphericalSuperGaussian asg;
asg.amplitude = 1.0;
asg.power = _EyeAsgPower;
asg.sharpness = _EyeAsgSharpness;
asg.mean = _EyeAsgMeanOS;
asg.tangent = _EyeAsgTangentOS;
asg.bitangent = _EyeAsgBitangentOS;
float asgAO = EvaluateAnisotropicSphericalSuperGaussian(a, asgEvaluationDirectionOS);
float asgAO = EvaluateAnisotropicSphericalSuperGaussian(asg, asgEvaluationDirectionOS);
// Copy to output.
EyeData eyeData;
eyeData.refractedUV = lerp(uv0, uv1, maskCornea);
eyeData.maskCornea = maskCornea;
eyeData.maskSclera = maskSclera;
eyeData.maskPupil = maskPupil;
eyeData.asgAO = saturate(asgAO * _EyeAsgThresholdScaleBias.x + _EyeAsgThresholdScaleBias.y);
eyeData.asgModulateAlbedo = _EyeAsgModulateAlbedo;
eyeData.ior = lerp(_EyeLitIORSclera, _EyeLitIORCornea, maskCornea);
eyeData.irisBentLighting = _EyeIrisBentLighting;
eyeData.corneaSmoothness = _EyeCorneaSmoothness;
eyeData.corneaSSS = _EyeCorneaSSS;
return eyeData;
// copy to output struct
EyeProperties props;
props.refractedUV = lerp(uv0, uv1, maskCornea);
props.maskCornea = maskCornea;
props.maskSclera = maskSclera;
props.maskPupil = maskPupil;
props.asgAO = saturate(asgAO * _EyeAsgThresholdScaleBias.x + _EyeAsgThresholdScaleBias.y);
props.asgModulateAlbedo = _EyeAsgModulateAlbedo;
props.ior = lerp(_EyeScleraIOR, _EyeCorneaIOR, maskCornea);
props.irisBentLighting = _EyeIrisRefractedLighting;
props.corneaSmoothness = _EyeCorneaSmoothness;
props.corneaSSS = _EyeCorneaSSS;
return props;
EyeData data = GetEyeData(positionOS, normalOS);
refractedUV = data.refractedUV;
maskCornea = data.maskCornea;
maskSclera = data.maskSclera;
maskPupil = data.maskPupil;
asgAO = data.asgAO;
asgModulateAlbedo = data.asgModulateAlbedo;
ior = data.ior;
irisBentLighting = data.irisBentLighting;
corneaSmoothness = data.corneaSmoothness;
corneaSSS = data.corneaSSS;
EyeProperties props = ResolveEyeProperties(positionOS, normalOS);
{
refractedUV = props.refractedUV;
maskCornea = props.maskCornea;
maskSclera = props.maskSclera;
maskPupil = props.maskPupil;
asgAO = props.asgAO;
asgModulateAlbedo = props.asgModulateAlbedo;
ior = props.ior;
irisBentLighting = props.irisBentLighting;
corneaSmoothness = props.corneaSmoothness;
corneaSSS = props.corneaSSS;
}
}
#endif//__EYEPROPERTIES_H__

197
Editor/EyeRendererEditor.cs


using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace Unity.DemoTeam.DigitalHuman
{
[CustomEditor(typeof(EyeRenderer))]
public class EyeRendererEditor : Editor
{
void OnSceneGUI()
{
var eye = target as EyeRenderer;
if (eye == null)
return;
DrawEyeHandles(eye);
}
void DrawEyeHandles(EyeRenderer eye)
{
var geometryRadius = eye.geometryRadius;
var geometryOrigin = eye.geometryOrigin;
var geometryDiameter = 2.0f * geometryRadius;
var geometryLookRadius = 1.2f * geometryRadius;
var geometryLookRotation = Quaternion.Euler(eye.geometryAngle);
var geometryForward = Vector3.Normalize(geometryLookRotation * Vector3.forward);
var geometryRight = Vector3.Normalize(geometryLookRotation * Vector3.right);
var geometryUp = Vector3.Normalize(geometryLookRotation * Vector3.up);
var drawColorWire = Color.Lerp(Color.clear, Color.green, 1.0f);
var drawColorSolid = Color.Lerp(Color.clear, Color.green, 0.6f);
var drawMatrixObject = eye.transform.localToWorldMatrix;
var drawMatrixGeometry = drawMatrixObject * Matrix4x4.TRS(geometryOrigin, geometryLookRotation, Vector3.one);
var crossSection = eye.corneaCrossSection;
var crossSectionIris = crossSection - eye.corneaCrossSectionIrisOffset;
var crossSectionFade = crossSection + eye.corneaCrossSectionFadeOffset;
var pupilOrigin = geometryDiameter * new Vector3(-eye.pupilUVOffset.x, -eye.pupilUVOffset.y, 0.0f) + Vector3.forward * crossSectionIris;
var pupilRadius = geometryDiameter * (0.5f * eye.pupilUVDiameter);
Vector3 hndGeometryOrigin = geometryOrigin;
Vector3 hndGeometryRadius = geometryOrigin + geometryRight * geometryRadius;
Vector3 hndGeometryForward = geometryOrigin + geometryForward * geometryLookRadius;
Vector3 hndCrossSection = Vector3.forward * crossSection;
Vector3 hndCrossSectionIris = Vector3.forward * crossSectionIris;
Vector3 hndCrossSectionFade = Vector3.forward * crossSectionFade;
Vector3 hndPupilOrigin = pupilOrigin;
Vector3 hndPupilRadius = pupilOrigin + Vector3.right * pupilRadius;
bool hndGeometryRadiusChanged = false;
bool hndCrossSectionChanged = false;
bool hndCrossSectionIrisChanged = false;
bool hndCrossSectionFadeChanged = false;
bool hndPupilOriginChanged = false;
bool hndPupilRadiusChanged = false;
float hndSize = geometryRadius / 50.0f;
float hndDots = 2.0f;
EditorGUI.BeginChangeCheck();
using (new Handles.DrawingScope(drawColorWire, drawMatrixObject))
{
// geometry
{
Handles.DrawWireDisc(geometryOrigin, geometryForward, geometryRadius);
Handles.DrawDottedLine(geometryOrigin, geometryOrigin + geometryForward * geometryLookRadius, hndDots);
Handles.DrawDottedLine(geometryOrigin, geometryOrigin + geometryRight * geometryRadius, hndDots);
Handles.DrawDottedLine(geometryOrigin, geometryOrigin + geometryRight * -geometryRadius, hndDots);
Handles.DrawDottedLine(geometryOrigin, geometryOrigin + geometryUp * geometryRadius, hndDots);
Handles.DrawDottedLine(geometryOrigin, geometryOrigin + geometryUp * -geometryRadius, hndDots);
Handles.DrawWireArc(geometryOrigin, geometryUp, geometryForward, 12.0f, geometryLookRadius);
Handles.DrawWireArc(geometryOrigin, geometryUp, geometryForward, -12.0f, geometryLookRadius);
Handles.DrawWireArc(geometryOrigin, geometryRight, geometryForward, 12.0f, geometryLookRadius);
Handles.DrawWireArc(geometryOrigin, geometryRight, geometryForward, -12.0f, geometryLookRadius);
using (var check = new EditorGUI.ChangeCheckScope())
{
hndGeometryRadius = Handles.Slider2D(hndGeometryRadius, geometryForward, geometryRight, geometryUp, hndSize, Handles.SphereHandleCap, 0.0f);
hndGeometryRadiusChanged = check.changed;
}
}
// pupil
using (new Handles.DrawingScope(drawMatrixGeometry))
{
Handles.DrawDottedLine(hndPupilOrigin, hndPupilRadius, hndDots);
Handles.DrawWireDisc(hndPupilOrigin, Vector3.forward, pupilRadius);
using (var check = new EditorGUI.ChangeCheckScope())
{
hndPupilOrigin = Handles.Slider2D(hndPupilOrigin, Vector3.forward, Vector3.right, Vector3.up, pupilRadius, Handles.CircleHandleCap, 0.0f);
hndPupilOriginChanged = check.changed;
}
using (var check = new EditorGUI.ChangeCheckScope())
{
hndPupilRadius = Handles.Slider2D(hndPupilRadius, Vector3.forward, Vector3.right, Vector3.up, hndSize, Handles.SphereHandleCap, 0.0f);
hndPupilRadiusChanged = check.changed;
}
}
// cross section
using (new Handles.DrawingScope(drawMatrixGeometry))
{
var dir45A = Vector3.Normalize(Vector3.right + Vector3.up);
var dir45B = Vector3.Normalize(Vector3.right - Vector3.up);
var extCrossSection = geometryRadius * 0.65f;
var extCrossSectionFadeOffset = geometryRadius * 0.5f;
var extCrossSectionIrisOffset = geometryRadius * 0.35f;
using (new Handles.DrawingScope(new Color(1.0f, 0.5f, 0.0f)))
{
Handles.DrawLine(hndCrossSectionIris - dir45A * extCrossSectionIrisOffset, hndCrossSectionIris + dir45A * extCrossSectionIrisOffset);
Handles.DrawLine(hndCrossSectionIris - dir45B * extCrossSectionIrisOffset, hndCrossSectionIris + dir45B * extCrossSectionIrisOffset);
Handles.DrawLine(hndCrossSectionIris - dir45A * extCrossSectionIrisOffset, hndCrossSection - dir45A * extCrossSectionIrisOffset);
Handles.DrawLine(hndCrossSectionIris - dir45B * extCrossSectionIrisOffset, hndCrossSection - dir45B * extCrossSectionIrisOffset);
Handles.DrawLine(hndCrossSectionIris + dir45A * extCrossSectionIrisOffset, hndCrossSection + dir45A * extCrossSectionIrisOffset);
Handles.DrawLine(hndCrossSectionIris + dir45B * extCrossSectionIrisOffset, hndCrossSection + dir45B * extCrossSectionIrisOffset);
using (var check = new EditorGUI.ChangeCheckScope())
{
hndCrossSectionIris = Handles.Slider2D(hndCrossSectionIris, Vector3.right, Vector3.forward, Vector3.up, hndSize, Handles.CubeHandleCap, 0.0f);
hndCrossSectionIrisChanged = check.changed;
}
}
using (new Handles.DrawingScope(Color.red))
{
Handles.DrawLine(hndCrossSection - dir45A * extCrossSection, hndCrossSection + dir45A * extCrossSection);
Handles.DrawLine(hndCrossSection - dir45B * extCrossSection, hndCrossSection + dir45B * extCrossSection);
using (var check = new EditorGUI.ChangeCheckScope())
{
hndCrossSection = Handles.Slider2D(hndCrossSection, Vector3.right, Vector3.forward, Vector3.up, hndSize, Handles.CubeHandleCap, 0.0f);
hndCrossSectionChanged = check.changed;
}
}
using (new Handles.DrawingScope(new Color(1.0f, 0.0f, 0.5f)))
{
Handles.DrawLine(hndCrossSectionFade - dir45A * extCrossSectionFadeOffset, hndCrossSectionFade + dir45A * extCrossSectionFadeOffset);
Handles.DrawLine(hndCrossSectionFade - dir45B * extCrossSectionFadeOffset, hndCrossSectionFade + dir45B * extCrossSectionFadeOffset);
Handles.DrawLine(hndCrossSectionFade - dir45A * extCrossSectionFadeOffset, hndCrossSection - dir45A * extCrossSectionFadeOffset);
Handles.DrawLine(hndCrossSectionFade - dir45B * extCrossSectionFadeOffset, hndCrossSection - dir45B * extCrossSectionFadeOffset);
Handles.DrawLine(hndCrossSectionFade + dir45A * extCrossSectionFadeOffset, hndCrossSection + dir45A * extCrossSectionFadeOffset);
Handles.DrawLine(hndCrossSectionFade + dir45B * extCrossSectionFadeOffset, hndCrossSection + dir45B * extCrossSectionFadeOffset);
using (var check = new EditorGUI.ChangeCheckScope())
{
hndCrossSectionFade = Handles.Slider2D(hndCrossSectionFade, Vector3.right, Vector3.forward, Vector3.up, hndSize, Handles.CubeHandleCap, 0.0f);
hndCrossSectionFadeChanged = check.changed;
}
}
}
}
if (EditorGUI.EndChangeCheck())
{
Undo.RegisterCompleteObjectUndo(eye, "Eye property change");
// update geometry
if (hndGeometryRadiusChanged)
eye.geometryRadius = Vector3.Magnitude(hndGeometryRadius - geometryOrigin);
// update pupil
if (hndPupilOriginChanged)
eye.pupilUVOffset = new Vector2(-hndPupilOrigin.x, -hndPupilOrigin.y) / geometryDiameter;
if (hndPupilRadiusChanged)
eye.pupilUVDiameter = 2.0f * Vector3.Magnitude(hndPupilRadius - pupilOrigin) / geometryDiameter;
// update cross section
if (hndCrossSectionChanged)
eye.corneaCrossSection = hndCrossSection.z;
if (hndCrossSectionIrisChanged)
eye.corneaCrossSectionIrisOffset = Mathf.Max(0.0f, crossSection - hndCrossSectionIris.z);
if (hndCrossSectionFadeChanged)
eye.corneaCrossSectionFadeOffset = Mathf.Max(0.0f, hndCrossSectionFade.z - crossSection);
}
}
}
}

11
Editor/EyeRendererEditor.cs.meta


fileFormatVersion: 2
guid: 25f28bacd17985447bd4d82e81fcba84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存