correct winding order + cleanup

This commit is contained in:
Timo Eberl 2025-08-31 14:20:52 +02:00
parent a3d689bbb2
commit 10f57041f9
Signed by: Timo
SSH Key Fingerprint: SHA256:swVjhbVzKCLQZNtwPqMEmtOUG3FTydzVrpIKpUZYTQw
2 changed files with 82 additions and 95 deletions

View File

@ -24,7 +24,7 @@
}
SubShader {
LOD 100
Cull Off
// Cull Off
//Render Pass
Pass {

View File

@ -25,11 +25,11 @@ struct g2f {
float4 pos : SV_POSITION;
#ifdef IS_IN_BASE_PASS
float3 normal : NORMAL;
float3 worldPos : TEXCOORD3;
float2 uv : TEXCOORD0; // bottom left 0.0 top right 1.1 (values converge - 0 and 1 meet at the tip)
SHADOW_COORDS(1) // put shadows data into TEXCOORD1
float transitionInterpolator : TEXCOORD2;
float3 worldPos : TEXCOORD2;
#endif
float3 debug : TEXCOORD3;
};
v2g vert (MeshData v) {
@ -87,6 +87,8 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
#endif
g2f o;
o.debug = float3(0,0,0);
float3 previousSegmentCenter = basePos - float3(0,-1,0); // point beneath the basePos
int numSegments;
@ -101,86 +103,70 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
#endif
float3 localCameraPos = mul(unity_WorldToObject, float4(_MainCameraPosition.xyz, 1.0)).xyz;
const float lowerThickness = 0.8;
for (int i = 0; i < numSegments; i++) {
const float lowerThickness = 0.8;
// LOD 3 has a different algorithm
#if _LOD_LOD_3
{
const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141), .8);
const float3 widthOffset = getWidthOffset(segmentWidth, tipOffset.xz) * max(1, cameraDistance / 10);
float3 segmentCenterBase = basePos;
float3 segmentCenterTip = basePos + tipOffset;
const float3 vertLeftBase = segmentCenterBase + widthOffset * 2.5;
const float3 vertRightBase = segmentCenterBase - widthOffset * 2.5;
const float3 vertLeftTip = segmentCenterTip + widthOffset * 0.4;
const float3 vertRightTip = segmentCenterTip - widthOffset * 0.4;
const float3 surfTangent1 = vertLeftBase - vertLeftTip;
const float3 surfTangent2 = vertLeftBase - vertRightBase;
const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize
float3 normalWS = UnityObjectToWorldNormal(normal);
const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141), .8);
const float3 widthOffset = getWidthOffset(segmentWidth, tipOffset.xz) * max(1, cameraDistance / 10);
float3 segmentCenterBase = basePos;
float3 segmentCenterTip = basePos + tipOffset;
const float3 vertLeftBase = segmentCenterBase + widthOffset * 2.5;
const float3 vertRightBase = segmentCenterBase - widthOffset * 2.5;
const float3 vertLeftTip = segmentCenterTip + widthOffset * 0.4;
const float3 vertRightTip = segmentCenterTip - widthOffset * 0.4;
const float3 surfTangent1 = vertRightBase - segmentCenterTip;
const float3 surfTangent2 = vertLeftBase - segmentCenterTip;
const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize
float3 normalWS = UnityObjectToWorldNormal(normal);
const float3 camVec = normalize(segmentCenterTip - localCameraPos);
const float3 camVec = normalize(vertLeftBase - localCameraPos);
// at which side of the blade are we looking?
const bool lookingFromAbove = dot(camVec, normal) > 0;
if (lookingFromAbove) {
// normalWS = -normalWS;
}
// at which side of the blade are we looking?
const bool lookingFromAbove = dot(camVec, normalWS) > 0;
if (lookingFromAbove) {
normalWS = -normalWS;
}
//normalWS = float3(1,1,1) * lookingFromAbove;
//normalWS = basePosWS - _MainCameraPosition.xyz;
//normalWS = camVec;
o.pos = UnityObjectToClipPos(vertLeftBase);
#ifndef IS_IN_SHADOW_PASS
o.uv = float2(0, 0);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftBase,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertRightBase);
#ifndef IS_IN_SHADOW_PASS
o.uv = float2(1, 0);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightBase,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertLeftTip);
#ifndef IS_IN_SHADOW_PASS
o.uv = float2(0, 1);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftTip,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertRightTip);
#ifndef IS_IN_SHADOW_PASS
o.uv = float2(1, 1);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightTip,1.0)).xyz;
#endif
triStream.Append(o);
}
continue;
o.pos = UnityObjectToClipPos(vertRightBase);
#ifdef IS_IN_BASE_PASS
o.uv = float2(1, 0);
TRANSFER_SHADOW(o)
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightBase,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertLeftBase);
#ifdef IS_IN_BASE_PASS
o.uv = float2(0, 0);
TRANSFER_SHADOW(o)
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftBase,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertRightTip);
#ifdef IS_IN_BASE_PASS
o.uv = float2(1, 1);
TRANSFER_SHADOW(o)
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightTip,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertLeftTip);
#ifdef IS_IN_BASE_PASS
o.uv = float2(0, 1);
TRANSFER_SHADOW(o)
o.normal = normalWS;
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftTip,1.0)).xyz;
#endif
triStream.Append(o);
#else
for (int i = 0; i < numSegments; i++) {
// in "blade space"
const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141 * (numSegments - i) / numSegments), .8);
const float segmentHeightNormalized = i / (float)numSegments;
@ -195,14 +181,13 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
const float3 vertRight = segmentCenter - widthOffset;
//const float3 nextSegmentCenter = basePos + bendParabula(tipPos, nextSegmentHeight01);
#ifndef IS_IN_SHADOW_PASS
#ifdef IS_IN_BASE_PASS
// calculate normal
const float3 surfTangent1 = previousSegmentCenter - segmentCenter;
const float3 surfTangent2 = previousSegmentCenter - vertLeft;
const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize
float3 normalWS = UnityObjectToWorldNormal(normal);
const float3 camVec = normalize(segmentCenter - localCameraPos);
// at which side of the blade are we looking?
@ -211,41 +196,43 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
normalWS = -normalWS;
}
#endif
o.pos = UnityObjectToClipPos(vertLeft);
#ifndef IS_IN_SHADOW_PASS
o.uv = float2(0, segmentHeightNormalized);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(normalize(widthOffset)), _BladeBow));
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeft,1.0)).xyz;
#endif
triStream.Append(o);
o.pos = UnityObjectToClipPos(vertRight);
#ifndef IS_IN_SHADOW_PASS
#ifdef IS_IN_BASE_PASS
o.uv = float2(1, segmentHeightNormalized);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(-normalize(widthOffset)), _BladeBow));
o.worldPos = mul(unity_ObjectToWorld, float4(vertRight,1.0)).xyz;
#endif
triStream.Append(o);
previousSegmentCenter = segmentCenterSnapshot;
o.pos = UnityObjectToClipPos(vertLeft);
#ifdef IS_IN_BASE_PASS
o.uv = float2(0, segmentHeightNormalized);
TRANSFER_SHADOW(o)
o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(normalize(widthOffset)), _BladeBow));
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeft,1.0)).xyz;
#endif
triStream.Append(o);
}
#endif
o.pos = UnityObjectToClipPos(basePos + tipOffset * float3(_BendStrength, 1, _BendStrength));
#ifndef IS_IN_SHADOW_PASS
#ifdef IS_IN_BASE_PASS
o.uv = float2(.5, 1);
TRANSFER_SHADOW(o)
o.transitionInterpolator = interpolator;
o.normal = o.normal > 0 ? float3(0, 1, 0) : float3(0, -1, 0);
#endif
triStream.Append(o);
}
float4 frag(g2f i) : SV_Target{
#ifndef IS_IN_SHADOW_PASS
#ifdef IS_IN_BASE_PASS
float3 localPos = mul(unity_WorldToObject, float4(i.worldPos, 1)).xyz;
float d = distance(localPos, i.debug) * 5;
return float4(i.debug, 1);
float3 worldNormal = normalize(i.normal);
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);