소스 검색

Merge branch '4.0' into 4.1-beta

# Conflicts:
#	spine-ts/package-lock.json
#	spine-ts/spine-threejs/package.json
badlogic 3 년 전
부모
커밋
ecbe087227

+ 1 - 1
CHANGELOG.md

@@ -122,7 +122,7 @@
 * Generated normals are now correctly flipped for back faces.
 * Modifying parent materials updates material instances accordingly.
 * Only `.json` files that are actually encoding Spine skeletons will be loaded. Other `.json` files will be left to other importers.
-* Updated example project to UE 4.25.
+* Updated example project to UE 4.27.
 
 
 ## C# ##

+ 0 - 1
spine-ts/spine-threejs/example/index.html

@@ -5,7 +5,6 @@
 	<title>spine-threejs</title>
 	<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js"></script>
 	<script src="../dist/iife/spine-threejs.js"></script>
-	<script src="index.js"></script>
 </head>
 <style>
 	* {

+ 75 - 3
spine-ts/spine-threejs/src/MeshBatcher.ts

@@ -29,6 +29,8 @@
 
 import { SkeletonMeshMaterial, SkeletonMeshMaterialParametersCustomizer } from "./SkeletonMesh";
 import * as THREE from "three"
+import { ThreeJsTexture } from "./ThreeJsTexture";
+import { BlendMode } from "@esotericsoftware/spine-core";
 
 export class MeshBatcher extends THREE.Mesh {
 	private static VERTEX_SIZE = 9;
@@ -37,8 +39,9 @@ export class MeshBatcher extends THREE.Mesh {
 	private verticesLength = 0;
 	private indices: Uint16Array;
 	private indicesLength = 0;
+	private materialGroups: [number, number, number][] = [];
 
-	constructor (maxVertices: number = 10920, materialCustomizer: SkeletonMeshMaterialParametersCustomizer = (parameters) => { }) {
+	constructor (maxVertices: number = 10920, private materialCustomizer: SkeletonMeshMaterialParametersCustomizer = (parameters) => { }) {
 		super();
 		if (maxVertices > 10920) throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
 		let vertices = this.vertices = new Float32Array(maxVertices * MeshBatcher.VERTEX_SIZE);
@@ -54,7 +57,7 @@ export class MeshBatcher extends THREE.Mesh {
 		geo.drawRange.start = 0;
 		geo.drawRange.count = 0;
 		this.geometry = geo;
-		this.material = new SkeletonMeshMaterial(materialCustomizer);
+		this.material = [new SkeletonMeshMaterial(materialCustomizer)];
 	}
 
 	dispose () {
@@ -74,7 +77,19 @@ export class MeshBatcher extends THREE.Mesh {
 		let geo = (<THREE.BufferGeometry>this.geometry);
 		geo.drawRange.start = 0;
 		geo.drawRange.count = 0;
-		(<SkeletonMeshMaterial>this.material).uniforms.map.value = null;
+		geo.clearGroups();
+		this.materialGroups = [];
+		if (this.material instanceof THREE.Material) {
+			const meshMaterial = this.material as SkeletonMeshMaterial;
+			meshMaterial.uniforms.map.value = null;
+			meshMaterial.blending = THREE.NormalBlending;
+		} else if (Array.isArray(this.material)) {
+			for (let i = 0; i < this.material.length; i++) {
+				const meshMaterial = this.material[i] as SkeletonMeshMaterial;
+				meshMaterial.uniforms.map.value = null;
+				meshMaterial.blending = THREE.NormalBlending;
+			}
+		}
 		return this;
 	}
 
@@ -118,10 +133,67 @@ export class MeshBatcher extends THREE.Mesh {
 		this.vertexBuffer.updateRange.offset = 0;
 		this.vertexBuffer.updateRange.count = this.verticesLength;
 		let geo = (<THREE.BufferGeometry>this.geometry);
+		this.closeMaterialGroups();
 		geo.getIndex().needsUpdate = this.indicesLength > 0;
 		geo.getIndex().updateRange.offset = 0;
 		geo.getIndex().updateRange.count = this.indicesLength;
 		geo.drawRange.start = 0;
 		geo.drawRange.count = this.indicesLength;
 	}
+
+	addMaterialGroup (indicesLength: number, materialGroup: number) {
+		const currentGroup = this.materialGroups[this.materialGroups.length - 1];
+
+		if (currentGroup === undefined || currentGroup[2] !== materialGroup) {
+			this.materialGroups.push([this.indicesLength, indicesLength, materialGroup]);
+		} else {
+			currentGroup[1] += indicesLength;
+		}
+	}
+
+	private closeMaterialGroups () {
+		const geometry = this.geometry as THREE.BufferGeometry;
+		for (let i = 0; i < this.materialGroups.length; i++) {
+			const [startIndex, count, materialGroup] = this.materialGroups[i];
+
+			geometry.addGroup(startIndex, count, materialGroup);
+		}
+	}
+
+	findMaterialGroup (slotTexture: THREE.Texture, slotBlendMode: BlendMode) {
+		const blending = ThreeJsTexture.toThreeJsBlending(slotBlendMode);
+		let group = -1;
+
+		if (Array.isArray(this.material)) {
+			for (let i = 0; i < this.material.length; i++) {
+				const meshMaterial = this.material[i] as SkeletonMeshMaterial;
+
+				if (meshMaterial.uniforms.map.value === null) {
+					updateMeshMaterial(meshMaterial, slotTexture, blending);
+					return i;
+				}
+
+				if (meshMaterial.uniforms.map.value === slotTexture && meshMaterial.blending === blending) {
+					return i;
+				}
+			}
+
+			const meshMaterial = new SkeletonMeshMaterial(this.materialCustomizer);
+			updateMeshMaterial(meshMaterial, slotTexture, blending);
+			this.material.push(meshMaterial);
+			group = this.material.length - 1;
+		} else {
+			throw new Error("MeshBatcher.material needs to be an array for geometry groups to work");
+		}
+
+		return group;
+	}
+}
+
+function updateMeshMaterial (meshMaterial: SkeletonMeshMaterial, slotTexture: THREE.Texture, blending: THREE.Blending) {
+	meshMaterial.uniforms.map.value = slotTexture;
+	meshMaterial.blending = blending;
+	meshMaterial.blendDst = blending === THREE.CustomBlending ? THREE.OneMinusSrcColorFactor : THREE.OneMinusSrcAlphaFactor;
+	meshMaterial.blendSrc = blending === THREE.CustomBlending ? THREE.OneFactor : THREE.SrcAlphaFactor;
+	meshMaterial.needsUpdate = true;
 }

+ 30 - 51
spine-ts/spine-threejs/src/SkeletonMesh.ts

@@ -39,23 +39,23 @@ export interface SkeletonMeshMaterialParametersCustomizer {
 export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 	constructor (customizer: SkeletonMeshMaterialParametersCustomizer) {
 		let vertexShader = `
-				attribute vec4 color;
-				varying vec2 vUv;
-				varying vec4 vColor;
-				void main() {
-					vUv = uv;
-					vColor = color;
-					gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
-				}
-			`;
+			attribute vec4 color;
+			varying vec2 vUv;
+			varying vec4 vColor;
+			void main() {
+				vUv = uv;
+				vColor = color;
+				gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
+			}
+		`;
 		let fragmentShader = `
-				uniform sampler2D map;
-				varying vec2 vUv;
-				varying vec4 vColor;
-				void main(void) {
-					gl_FragColor = texture2D(map, vUv)*vColor;
-				}
-			`;
+			uniform sampler2D map;
+			varying vec2 vUv;
+			varying vec4 vColor;
+			void main(void) {
+				gl_FragColor = texture2D(map, vUv)*vColor;
+			}
+		`;
 
 		let parameters: THREE.ShaderMaterialParameters = {
 			uniforms: {
@@ -65,6 +65,7 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 			fragmentShader: fragmentShader,
 			side: THREE.DoubleSide,
 			transparent: true,
+			depthWrite: false,
 			alphaTest: 0.5
 		};
 		customizer(parameters);
@@ -91,11 +92,10 @@ export class SkeletonMesh extends THREE.Object3D {
 
 	private vertices = Utils.newFloatArray(1024);
 	private tempColor = new Color();
-	private materialCustomizer: SkeletonMeshMaterialParametersCustomizer;
 
-	constructor (skeletonData: SkeletonData, materialCustomizer: SkeletonMeshMaterialParametersCustomizer = (parameters) => { }) {
+	constructor (skeletonData: SkeletonData) {
 		super();
-		this.materialCustomizer = materialCustomizer;
+
 		this.skeleton = new Skeleton(skeletonData);
 		let animData = new AnimationStateData(skeletonData);
 		this.state = new AnimationState(animData);
@@ -128,7 +128,7 @@ export class SkeletonMesh extends THREE.Object3D {
 
 	private nextBatch () {
 		if (this.batches.length == this.nextBatchIndex) {
-			let batch = new MeshBatcher(10920, this.materialCustomizer);
+			let batch = new MeshBatcher();
 			this.add(batch);
 			this.batches.push(batch);
 		}
@@ -163,10 +163,7 @@ export class SkeletonMesh extends THREE.Object3D {
 		for (let i = 0, n = drawOrder.length; i < n; i++) {
 			let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
 			let slot = drawOrder[i];
-			if (!slot.bone.active) {
-				clipper.clipEndWithSlot(slot);
-				continue;
-			}
+			if (!slot.bone.active) continue;
 			let attachment = slot.getAttachment();
 			let attachmentColor: Color = null;
 			let texture: ThreeJsTexture = null;
@@ -196,12 +193,9 @@ export class SkeletonMesh extends THREE.Object3D {
 				let clip = <ClippingAttachment>(attachment);
 				clipper.clipStart(slot, clip);
 				continue;
-			} else {
-				clipper.clipEndWithSlot(slot);
-				continue;
-			}
+			} else continue;
 
-			if (texture) {
+			if (texture != null) {
 				let skeleton = slot.bone.skeleton;
 				let skeletonColor = skeleton.color;
 				let slotColor = slot.color;
@@ -221,7 +215,7 @@ export class SkeletonMesh extends THREE.Object3D {
 					clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, null, false);
 					let clippedVertices = clipper.clippedVertices;
 					let clippedTriangles = clipper.clippedTriangles;
-					if (this.vertexEffect) {
+					if (this.vertexEffect != null) {
 						let vertexEffect = this.vertexEffect;
 						let verts = clippedVertices;
 						for (let v = 0, n = clippedVertices.length; v < n; v += vertexSize) {
@@ -248,7 +242,7 @@ export class SkeletonMesh extends THREE.Object3D {
 					finalIndicesLength = clippedTriangles.length;
 				} else {
 					let verts = vertices;
-					if (this.vertexEffect) {
+					if (this.vertexEffect != null) {
 						let vertexEffect = this.vertexEffect;
 						for (let v = 0, u = 0, n = numFloats; v < n; v += vertexSize, u += 2) {
 							tempPos.x = verts[v];
@@ -283,10 +277,8 @@ export class SkeletonMesh extends THREE.Object3D {
 					finalIndicesLength = triangles.length;
 				}
 
-				if (finalVerticesLength == 0 || finalIndicesLength == 0) {
-					clipper.clipEndWithSlot(slot);
+				if (finalVerticesLength == 0 || finalIndicesLength == 0)
 					continue;
-				}
 
 				// Start new batch if this one can't hold vertices/indices
 				if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
@@ -295,24 +287,11 @@ export class SkeletonMesh extends THREE.Object3D {
 					batch.begin();
 				}
 
-				// FIXME per slot blending would require multiple material support
-				//let slotBlendMode = slot.data.blendMode;
-				//if (slotBlendMode != blendMode) {
-				//	blendMode = slotBlendMode;
-				//	batcher.setBlendMode(getSourceGLBlendMode(this._gl, blendMode, premultipliedAlpha), getDestGLBlendMode(this._gl, blendMode));
-				//}
-
-				let batchMaterial = <SkeletonMeshMaterial>batch.material;
-				if (!batchMaterial.uniforms.map.value) batchMaterial.uniforms.map.value = texture.texture;
-				if (batchMaterial.uniforms.map.value != texture.texture) {
-					batch.end();
-					batch = this.nextBatch();
-					batch.begin();
-					batchMaterial = <SkeletonMeshMaterial>batch.material;
-					batchMaterial.uniforms.map.value = texture.texture;
-				}
-				batchMaterial.needsUpdate = true;
+				const slotBlendMode = slot.data.blendMode;
+				const slotTexture = texture.texture;
+				const materialGroup = batch.findMaterialGroup(slotTexture, slotBlendMode);
 
+				batch.addMaterialGroup(finalIndicesLength, materialGroup);
 				batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
 				z += zOffset;
 			}

+ 16 - 8
spine-ts/spine-threejs/src/ThreeJsTexture.ts

@@ -27,34 +27,34 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-import { Texture, TextureFilter, TextureWrap } from "@esotericsoftware/spine-core";
+import { BlendMode, Texture, TextureFilter, TextureWrap } from "@esotericsoftware/spine-core";
 import * as THREE from "three";
 
 export class ThreeJsTexture extends Texture {
 	texture: THREE.Texture;
 
-	constructor (image: HTMLImageElement) {
+	constructor(image: HTMLImageElement) {
 		super(image);
 		this.texture = new THREE.Texture(image);
 		this.texture.flipY = false;
 		this.texture.needsUpdate = true;
 	}
 
-	setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
+	setFilters(minFilter: TextureFilter, magFilter: TextureFilter) {
 		this.texture.minFilter = ThreeJsTexture.toThreeJsTextureFilter(minFilter);
 		this.texture.magFilter = ThreeJsTexture.toThreeJsTextureFilter(magFilter);
 	}
 
-	setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
+	setWraps(uWrap: TextureWrap, vWrap: TextureWrap) {
 		this.texture.wrapS = ThreeJsTexture.toThreeJsTextureWrap(uWrap);
 		this.texture.wrapT = ThreeJsTexture.toThreeJsTextureWrap(vWrap);
 	}
 
-	dispose () {
+	dispose() {
 		this.texture.dispose();
 	}
 
-	static toThreeJsTextureFilter (filter: TextureFilter) {
+	static toThreeJsTextureFilter(filter: TextureFilter) {
 		if (filter === TextureFilter.Linear) return THREE.LinearFilter;
 		else if (filter === TextureFilter.MipMap) return THREE.LinearMipMapLinearFilter; // also includes TextureFilter.MipMapLinearLinear
 		else if (filter === TextureFilter.MipMapLinearNearest) return THREE.LinearMipMapNearestFilter;
@@ -64,10 +64,18 @@ export class ThreeJsTexture extends Texture {
 		else throw new Error("Unknown texture filter: " + filter);
 	}
 
-	static toThreeJsTextureWrap (wrap: TextureWrap) {
+	static toThreeJsTextureWrap(wrap: TextureWrap) {
 		if (wrap === TextureWrap.ClampToEdge) return THREE.ClampToEdgeWrapping;
 		else if (wrap === TextureWrap.MirroredRepeat) return THREE.MirroredRepeatWrapping;
 		else if (wrap === TextureWrap.Repeat) return THREE.RepeatWrapping;
 		else throw new Error("Unknown texture wrap: " + wrap);
 	}
-}
+
+	static toThreeJsBlending(blend: BlendMode) {
+		if (blend === BlendMode.Normal) return THREE.NormalBlending;
+		else if (blend === BlendMode.Additive) return THREE.AdditiveBlending;
+		else if (blend === BlendMode.Multiply) return THREE.MultiplyBlending;
+		else if (blend === BlendMode.Screen) return THREE.CustomBlending;
+		else throw new Error("Unknown blendMode: " + blend);
+	}
+}

+ 3 - 3
spine-ts/spine-webgl/tests/test-drawcalls.html

@@ -21,7 +21,7 @@
 		info;
 
 		loadAssets(canvas) {
-			this.numSkeletons = 100;
+			this.numSkeletons = 400;
 			this.skeletons = [];
 			this.states = [];
 			this.info = document.querySelector("#info")[0];
@@ -45,7 +45,7 @@
 			for (var i = 0; i < this.numSkeletons; i++) {
 				let skeleton = new spine.Skeleton(skeletonData);
 
-				// Create the animation state			
+				// Create the animation state
 				let state = new spine.AnimationState(stateData);
 				state.setAnimation(0, "dance", true);
 
@@ -92,7 +92,7 @@
 				renderer.drawSkeleton(skeleton, true);
 			}
 			renderer.end();
-			info.innerText = "Draw calls: " + renderer.batcher.drawCalls;
+			info.innerText = "Draw calls: " + renderer.batcher.drawCalls + ", FPS: " + canvas.time.framesPerSecond.toFixed(0);
 		}
 	}
 

+ 1 - 1
spine-ue4/SpineUE4.uproject

@@ -1,6 +1,6 @@
 {
 	"FileVersion": 3,
-	"EngineAssociation": "4.25",
+	"EngineAssociation": "4.27",
 	"Category": "",
 	"Description": "",
 	"Modules": [

+ 6 - 1
spine-unity/Modules/com.esotericsoftware.spine.timeline/Editor/SpineAnimationStateDrawer.cs

@@ -109,7 +109,12 @@ public class SpineAnimationStateDrawer : PropertyDrawer {
 			EditorGUI.PropertyField(singleFieldRect, useBlendDurationProp);
 
 			singleFieldRect.y += lineHeightWithSpacing;
-			EditorGUI.PropertyField(singleFieldRect, mixDurationProp);
+
+			bool greyOutMixDuration = (!useBlendDurationProp.hasMultipleDifferentValues &&
+										useBlendDurationProp.boolValue == true);
+			using (new EditorGUI.DisabledGroupScope(greyOutMixDuration)) {
+				EditorGUI.PropertyField(singleFieldRect, mixDurationProp);
+			}
 		}
 
 		singleFieldRect.y += lineHeightWithSpacing;

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateBehaviour.cs

@@ -41,6 +41,9 @@ namespace Spine.Unity.Playables {
 
 	[Serializable]
 	public class SpineAnimationStateBehaviour : PlayableBehaviour {
+
+		[NonSerialized] public TimelineClip timelineClip;
+
 		public AnimationReferenceAsset animationReference;
 		public bool loop;
 

+ 3 - 0
spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateClip.cs

@@ -38,8 +38,11 @@ namespace Spine.Unity.Playables {
 		public SpineAnimationStateBehaviour template = new SpineAnimationStateBehaviour();
 
 		public ClipCaps clipCaps { get { return ClipCaps.Blending | ClipCaps.ClipIn | ClipCaps.SpeedMultiplier | (template.loop ? ClipCaps.Looping : 0); } }
+		[NonSerialized] public TimelineClip timelineClip;
 
 		public override Playable CreatePlayable (PlayableGraph graph, GameObject owner) {
+			template.timelineClip = this.timelineClip;
+
 			var playable = ScriptPlayable<SpineAnimationStateBehaviour>.Create(graph, template);
 			playable.GetBehaviour();
 			return playable;

+ 14 - 3
spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs

@@ -95,6 +95,8 @@ namespace Spine.Unity.Playables {
 		}
 
 		protected void HandleClipEnd () {
+			if (animationStateComponent == null) return;
+
 			var state = animationStateComponent.AnimationState;
 			if (endAtClipEnd &&
 				timelineStartedTrackEntry != null &&
@@ -172,13 +174,14 @@ namespace Spine.Unity.Playables {
 				endMixOutDuration = clipData.endMixOutDuration;
 
 				if (clipData.animationReference == null) {
-					float mixDuration = clipData.customDuration ? clipData.mixDuration : state.Data.DefaultMix;
+					float mixDuration = clipData.customDuration ? GetCustomMixDuration(clipData) : state.Data.DefaultMix;
 					state.SetEmptyAnimation(trackIndex, mixDuration);
 				} else {
 					if (clipData.animationReference.Animation != null) {
 						TrackEntry currentEntry = state.GetCurrent(trackIndex);
 						Spine.TrackEntry trackEntry;
-						if (currentEntry == null && (clipData.customDuration && clipData.mixDuration > 0)) {
+						float customMixDuration = clipData.customDuration ? GetCustomMixDuration(clipData) : 0.0f;
+						if (currentEntry == null && customMixDuration > 0) {
 							state.SetEmptyAnimation(trackIndex, 0); // ease in requires empty animation
 							trackEntry = state.AddAnimation(trackIndex, clipData.animationReference.Animation, clipData.loop, 0);
 						} else
@@ -192,7 +195,7 @@ namespace Spine.Unity.Playables {
 						trackEntry.HoldPrevious = clipData.holdPrevious;
 
 						if (clipData.customDuration)
-							trackEntry.MixDuration = clipData.mixDuration;
+							trackEntry.MixDuration = customMixDuration;
 
 						timelineStartedTrackEntry = trackEntry;
 					}
@@ -314,6 +317,14 @@ namespace Spine.Unity.Playables {
 		}
 #endif
 
+		float GetCustomMixDuration (SpineAnimationStateBehaviour clipData) {
+			if (clipData.useBlendDuration) {
+				TimelineClip clip = clipData.timelineClip;
+				return (float)Math.Max(clip.blendInDuration, clip.easeInDuration);
+			} else {
+				return clipData.mixDuration;
+			}
+		}
 	}
 
 }

+ 8 - 0
spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateTrack.cs

@@ -27,6 +27,7 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
+using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Playables;
 using UnityEngine.Timeline;
@@ -39,6 +40,13 @@ namespace Spine.Unity.Playables {
 		public int trackIndex = 0;
 
 		public override Playable CreateTrackMixer (PlayableGraph graph, GameObject go, int inputCount) {
+			IEnumerable<TimelineClip> clips = this.GetClips();
+			foreach (TimelineClip clip in clips) {
+				var animationStateClip = clip.asset as SpineAnimationStateClip;
+				if (animationStateClip != null)
+					animationStateClip.timelineClip = clip;
+			}
+
 			var scriptPlayable = ScriptPlayable<SpineAnimationStateMixerBehaviour>.Create(graph, inputCount);
 			var mixerBehaviour = scriptPlayable.GetBehaviour();
 			mixerBehaviour.trackIndex = this.trackIndex;

+ 1 - 1
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/2D/Include/Spine-Sprite-StandardPass-URP-2D.hlsl

@@ -104,7 +104,7 @@ half4 CombinedShapeLightFragment(VertexOutputSpriteURP2D input) : SV_Target
 	pixel.rgb = applyRimLighting(input.positionWS.xyz, normalWS, pixel);
 #endif
 
-	APPLY_EMISSION(pixel.rgb, input.texcoord)
+	APPLY_EMISSION(pixel.rgb, input.texcoord.xy)
 	pixel = prepareLitPixelForOutput(pixel, texureColor.a, input.vertexColor.a);
 	COLORISE(pixel)
 	return pixel;

+ 4 - 18
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/Shaders/Include/Spine-Sprite-ForwardPass-URP.hlsl

@@ -127,7 +127,7 @@ half4 LightweightFragmentBlinnPhongSimplified(InputData inputData, half4 texDiff
 #endif
 	half3 diffuseLighting = inputData.bakedGI;
 
-	half3 attenuation = mainLight.distanceAttenuation * mainLight.shadowAttenuation;
+	half3 attenuation = mainLight.distanceAttenuation* mainLight.shadowAttenuation;
 	half3 attenuatedLightColor = mainLight.color * attenuation;
 #ifndef _DIFFUSE_RAMP
 	diffuseLighting += LightingLambert(attenuatedLightColor, mainLight.direction, inputData.normalWS);
@@ -184,24 +184,15 @@ VertexOutputLWRP ForwardPassVertexSprite(VertexInput input)
 	output.positionWS = float4(positionWS, 1);
 #endif
 
-#if defined(PER_PIXEL_LIGHTING)
-
 	half3 normalWS = calculateSpriteWorldNormal(input, -backFaceSign);
 	output.normalWorld.xyz = normalWS;
-
 #if defined(_NORMALMAP)
 	output.tangentWorld.xyz = calculateWorldTangent(input.tangent);
 	output.binormalWorld.xyz = calculateSpriteWorldBinormal(input, output.normalWorld.xyz, output.tangentWorld.xyz, backFaceSign);
 #endif
 
-#else // !PER_PIXEL_LIGHTING
-	half3 fixedNormal = half3(0, 0, -1);
-	half3 normalWS = normalize(mul((float3x3)unity_ObjectToWorld, fixedNormal));
-
-#endif // !PER_PIXEL_LIGHTING
 	output.fogFactorAndVertexLight.yzw = LightweightLightVertexSimplified(positionWS, normalWS);
 
-
 #if (defined(_MAIN_LIGHT_SHADOWS) || defined(MAIN_LIGHT_CALCULATE_SHADOWS)) && !defined(_RECEIVE_SHADOWS_OFF)
 	VertexPositionInputs vertexInput;
 	vertexInput.positionWS = positionWS;
@@ -243,16 +234,11 @@ half4 ForwardPassFragmentSprite(VertexOutputLWRP input) : SV_Target
 	inputData.viewDirectionWS = input.viewDirectionWS;
 	inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
 
-#if defined(PER_PIXEL_LIGHTING)
-	#if defined(_NORMALMAP)
+#if defined(PER_PIXEL_LIGHTING) && defined(_NORMALMAP)
 	half3 normalWS = calculateNormalFromBumpMap(input.texcoord.xy, input.tangentWorld.xyz, input.binormalWorld.xyz, input.normalWorld.xyz);
-	#else
+#else
 	half3 normalWS = input.normalWorld.xyz;
-	#endif
-#else // !PER_PIXEL_LIGHTING
-	half3 fixedNormal = half3(0, 0, -1);
-	half3 normalWS = normalize(mul((float3x3)unity_ObjectToWorld, fixedNormal));
-#endif // !PER_PIXEL_LIGHTING
+#endif
 
 	inputData.normalWS = normalWS;
 	inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS);

+ 1 - 1
spine-unity/Modules/com.esotericsoftware.spine.urp-shaders/package.json

@@ -2,7 +2,7 @@
   "name": "com.esotericsoftware.spine.urp-shaders",
   "displayName": "Spine Universal RP Shaders",
   "description": "This plugin provides universal render pipeline (URP) shaders for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
-  "version": "4.0.4",
+  "version": "4.0.5",
   "unity": "2019.3",
   "author": {
     "name": "Esoteric Software",