fix normals
This commit is contained in:
parent
10f57041f9
commit
3b1f2d4073
@ -241020,111 +241020,6 @@ Mesh:
|
||||
offset: 0
|
||||
size: 0
|
||||
path:
|
||||
--- !u!1 &1663409491
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1663409495}
|
||||
- component: {fileID: 1663409494}
|
||||
- component: {fileID: 1663409493}
|
||||
- component: {fileID: 1663409492}
|
||||
m_Layer: 0
|
||||
m_Name: Cube
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!65 &1663409492
|
||||
BoxCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1663409491}
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_IsTrigger: 0
|
||||
m_ProvidesContacts: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Size: {x: 1, y: 1, z: 1}
|
||||
m_Center: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &1663409493
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1663409491}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 944161d6703f1e244a9216da9f82501b, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!33 &1663409494
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1663409491}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!4 &1663409495
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1663409491}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 7.656, y: 0.872, z: 0.544}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!43 &1663750196
|
||||
Mesh:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -308734,4 +308629,3 @@ SceneRoots:
|
||||
- {fileID: 2016058937}
|
||||
- {fileID: 513204364}
|
||||
- {fileID: 934953871}
|
||||
- {fileID: 1663409495}
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
}
|
||||
SubShader {
|
||||
LOD 100
|
||||
// Cull Off
|
||||
Cull Off
|
||||
|
||||
//Render Pass
|
||||
Pass {
|
||||
|
||||
@ -24,7 +24,7 @@ struct v2g {
|
||||
struct g2f {
|
||||
float4 pos : SV_POSITION;
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
float3 normal : NORMAL;
|
||||
float3 localNormal : NORMAL;
|
||||
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
|
||||
float3 worldPos : TEXCOORD2;
|
||||
@ -40,10 +40,6 @@ v2g vert (MeshData v) {
|
||||
return o;
|
||||
}
|
||||
|
||||
float getCameraDistance(float3 pos) {
|
||||
return distance(_MainCameraPosition, pos);
|
||||
}
|
||||
|
||||
#if _LOD_LOD_0
|
||||
[MaxVertexCount(4 + ( 11 - 1 ) * 2)]
|
||||
#elif _LOD_LOD_1
|
||||
@ -56,7 +52,6 @@ float getCameraDistance(float3 pos) {
|
||||
void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
const float3 basePos = IN[0].vertex.xyz;
|
||||
const float3 tipOffset = IN[0].tipOffset;
|
||||
const float3 tipPosObjectSpace = basePos + tipOffset;
|
||||
|
||||
// const float4 basePosClipSpace = UnityObjectToClipPos(float4(basePos, 1));
|
||||
// const float4 tipPosClipSpace = UnityObjectToClipPos(float4(tipPosObjectSpace, 1));
|
||||
@ -64,9 +59,9 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
|
||||
const float3 basePosWS = mul(unity_ObjectToWorld, float4(basePos.xyz, 1.0)).xyz;
|
||||
|
||||
const float cameraDistance = getCameraDistance(basePosWS);
|
||||
const float mainCamDist = distance(_MainCameraPosition, basePosWS);
|
||||
|
||||
float interpolator = invLerp(_TransitionRange.x, _TransitionRange.y, cameraDistance);
|
||||
float interpolator = invLerp(_TransitionRange.x, _TransitionRange.y, mainCamDist);
|
||||
|
||||
float halfWidth = _BladeWidth/2;
|
||||
|
||||
@ -78,18 +73,16 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
}
|
||||
|
||||
// randomly shrink shadow blades to create a smooth transition between shadowed and non-shadowed area
|
||||
#ifdef IS_IN_SHADOW_PASS
|
||||
#if _LOD_LOD_1
|
||||
#ifdef IS_IN_SHADOW_PASS
|
||||
#if _LOD_LOD_1
|
||||
float widthMultiplier = remap(N21(basePos.xz) * 0.5, 1, 1, 0, interpolator);
|
||||
widthMultiplier = max(0, widthMultiplier);
|
||||
halfWidth *= widthMultiplier;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
g2f o;
|
||||
o.debug = float3(0,0,0);
|
||||
|
||||
float3 previousSegmentCenter = basePos - float3(0,-1,0); // point beneath the basePos
|
||||
|
||||
int numSegments;
|
||||
#if _LOD_LOD_0
|
||||
@ -102,13 +95,12 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
numSegments = 1;
|
||||
#endif
|
||||
|
||||
float3 localCameraPos = mul(unity_WorldToObject, float4(_MainCameraPosition.xyz, 1.0)).xyz;
|
||||
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);
|
||||
const float3 widthOffset = getWidthOffset(tipOffset.xz) * segmentWidth * max(1, mainCamDist / 10);
|
||||
float3 segmentCenterBase = basePos;
|
||||
float3 segmentCenterTip = basePos + tipOffset;
|
||||
const float3 vertLeftBase = segmentCenterBase + widthOffset * 2.5;
|
||||
@ -118,22 +110,13 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
|
||||
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);
|
||||
|
||||
// at which side of the blade are we looking?
|
||||
const bool lookingFromAbove = dot(camVec, normal) > 0;
|
||||
if (lookingFromAbove) {
|
||||
// normalWS = -normalWS;
|
||||
}
|
||||
const float3 normal = cross(surfTangent1, surfTangent2);
|
||||
|
||||
o.pos = UnityObjectToClipPos(vertRightBase);
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(1, 0);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = normalWS;
|
||||
o.localNormal = normal;
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightBase,1.0)).xyz;
|
||||
#endif
|
||||
triStream.Append(o);
|
||||
@ -142,7 +125,7 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(0, 0);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = normalWS;
|
||||
o.localNormal = normal;
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftBase,1.0)).xyz;
|
||||
#endif
|
||||
triStream.Append(o);
|
||||
@ -151,7 +134,7 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(1, 1);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = normalWS;
|
||||
o.localNormal = normal;
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(vertRightTip,1.0)).xyz;
|
||||
#endif
|
||||
triStream.Append(o);
|
||||
@ -160,83 +143,105 @@ void geom(point v2g IN[1], inout TriangleStream<g2f> triStream) {
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(0, 1);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = normalWS;
|
||||
o.localNormal = normal;
|
||||
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;
|
||||
// float nextSegmentHeightNormalized = (i+1) / (float)numSegments;
|
||||
const float3 widthOffset = getWidthOffset(tipOffset.xz) * max(1, mainCamDist / 10);
|
||||
|
||||
// generate new verts
|
||||
const float3 widthOffset = getWidthOffset(segmentWidth, tipOffset.xz) * max(1, cameraDistance / 10);
|
||||
float3 segmentCenter = basePos + bendParabula(tipOffset, segmentHeightNormalized, _BendStrength);
|
||||
const float3 segmentCenterSnapshot = segmentCenter;
|
||||
|
||||
const float3 vertLeft = segmentCenter + widthOffset;
|
||||
const float3 vertRight = segmentCenter - widthOffset;
|
||||
//const float3 nextSegmentCenter = basePos + bendParabula(tipPos, nextSegmentHeight01);
|
||||
// previous vertex positions, used for normal calculation
|
||||
float3 previousVertLeft;
|
||||
float3 previousVertRight;
|
||||
for (int i = 0; i < numSegments; i++) {
|
||||
const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141 * (numSegments - i) / numSegments), .8);
|
||||
const float3 segmentWidthOffset = widthOffset * segmentWidth;
|
||||
const float segmentHeightNormalized = i / (float)numSegments;
|
||||
|
||||
const float3 segmentCenter = basePos + bendParabula(tipOffset, segmentHeightNormalized, _BendStrength);
|
||||
const float3 vertLeft = segmentCenter + segmentWidthOffset;
|
||||
const float3 vertRight = segmentCenter - segmentWidthOffset;
|
||||
|
||||
#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?
|
||||
const bool lookingFromAbove = dot(camVec, normalWS) > 0;
|
||||
if (lookingFromAbove) {
|
||||
normalWS = -normalWS;
|
||||
float3 surfTangent1, surfTangent2;
|
||||
if (i == 0) {
|
||||
// for the normals at the bottom vertices, use the normals of the next segment
|
||||
const float nextSegmentHeightNormalized = (i+1) / (float)numSegments;
|
||||
const float3 nextSegmentCenter = basePos + bendParabula(tipOffset, nextSegmentHeightNormalized, _BendStrength);
|
||||
surfTangent1 = nextSegmentCenter - vertRight;
|
||||
surfTangent2 = nextSegmentCenter - vertLeft;
|
||||
}
|
||||
else {
|
||||
surfTangent1 = segmentCenter - previousVertRight;
|
||||
surfTangent2 = segmentCenter - previousVertLeft;
|
||||
}
|
||||
const float3 normal = cross(surfTangent1, surfTangent2);
|
||||
|
||||
// TODO fake curvature
|
||||
// o.localNormal = normalize(lerp(normalWS, UnityObjectToWorldNormal(-normalize(segmentWidthOffset)), _BladeBow));
|
||||
|
||||
previousVertLeft = vertLeft;
|
||||
previousVertRight = vertRight;
|
||||
#endif
|
||||
|
||||
o.pos = UnityObjectToClipPos(vertRight);
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(1, segmentHeightNormalized);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(-normalize(widthOffset)), _BladeBow));
|
||||
o.localNormal = normal;
|
||||
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.localNormal = normal;
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(vertLeft,1.0)).xyz;
|
||||
#endif
|
||||
triStream.Append(o);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
o.pos = UnityObjectToClipPos(basePos + tipOffset * float3(_BendStrength, 1, _BendStrength));
|
||||
// tip vertex
|
||||
const float3 tipPosObjectSpace = basePos + tipOffset;
|
||||
const float3 surfTangent1 = tipPosObjectSpace - previousVertRight;
|
||||
const float3 surfTangent2 = tipPosObjectSpace - previousVertLeft;
|
||||
const float3 normal = cross(surfTangent1, surfTangent2);
|
||||
o.pos = UnityObjectToClipPos(tipPosObjectSpace * float3(_BendStrength, 1, _BendStrength));
|
||||
#ifdef IS_IN_BASE_PASS
|
||||
o.uv = float2(.5, 1);
|
||||
TRANSFER_SHADOW(o)
|
||||
o.normal = o.normal > 0 ? float3(0, 1, 0) : float3(0, -1, 0);
|
||||
o.localNormal = normal;
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(tipPosObjectSpace,1.0)).xyz;
|
||||
#endif
|
||||
triStream.Append(o);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float4 frag(g2f i) : SV_Target{
|
||||
#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);
|
||||
float d = distance(localPos, i.debug) * 50;
|
||||
float k = frac(d);
|
||||
// return float4(k,k,k, 1);
|
||||
// return float4(i.debug,1);
|
||||
|
||||
float3 worldNormal = UnityObjectToWorldNormal(i.localNormal);
|
||||
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
|
||||
|
||||
// at which side of the blade are we looking?
|
||||
// NOT ACCURATE, because the normals don't exactly match the geometry
|
||||
const bool lookingFromAbove = dot(worldViewDir, worldNormal) > 0;
|
||||
if (!lookingFromAbove) {
|
||||
worldNormal = -worldNormal;
|
||||
}
|
||||
|
||||
float3 worldNormal = normalize(i.normal);
|
||||
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
|
||||
|
||||
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
|
||||
float3 worldRefl = reflect(-worldViewDir, worldNormal);
|
||||
|
||||
// same as in previous shader
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// tipPos2D = xz coordinates of tip
|
||||
float3 getWidthOffset(float width, float2 tipPos2D) {
|
||||
float3 getWidthOffset(float2 tipPos2D) {
|
||||
float2 dirBaseToTip = normalize(tipPos2D);
|
||||
return float3(-dirBaseToTip.y * width, 0, dirBaseToTip.x * width);
|
||||
return float3(-dirBaseToTip.y, 0, dirBaseToTip.x);
|
||||
}
|
||||
|
||||
float3 bendParabula(float3 tipPos, float posOnBlade, float bendStrength) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user