Browse Source

GPU skinning/morph shader

BearishSun 9 years ago
parent
commit
5f60c31c28

BIN
Data/Engine/GUISkin.asset


BIN
Data/Engine/Includes/DeferredBasePass.bslinc.asset


BIN
Data/Engine/Includes/NormalVertexInput.bslinc.asset


BIN
Data/Engine/Includes/SkinnedVertexInput.bslinc.asset


BIN
Data/Engine/ResourceManifest.asset


BIN
Data/Engine/Shaders/Default.bsl.asset


BIN
Data/Engine/Shaders/Diffuse.bsl.asset


BIN
Data/Engine/Timestamp.asset


BIN
Data/Engine/arial.ttf.asset


+ 18 - 101
Data/Raw/Engine/Includes/DeferredBasePass.bslinc

@@ -2,76 +2,30 @@
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\PerObjectData.bslinc"
 
+#ifdef USE_ANIMATION
+	#include "$ENGINE$\SkinnedVertexInput.bslinc"
+#else
+	#include "$ENGINE$\NormalVertexInput.bslinc"
+#endif
+
 Technique =
 {
 	Language = "HLSL11";
 	
 	Pass =
 	{
-		Common = 
-		{
-			struct VStoFS
-			{
-				float4 position : SV_Position;
-				float2 uv0 : TEXCOORD0;
-				
-				float3 worldPosition : POSITION;
-				float3 tangentToWorldZ : NORMAL;
-				float4 tangentToWorldX : TANGENT;
-			};
-		};
-
 		Vertex =
 		{			
-			struct VertexInput
-			{
-				float3 position : POSITION;
-				float3 normal : NORMAL;
-				float4 tangent : TANGENT;
-				float2 uv0 : TEXCOORD0;
-			};
-			
-			float3x3 getTangentToObject(VertexInput input, out float tangentSign)
-			{
-				float3x3 output;
-				
-				float3 normal = input.normal;
-				float4 tangent = input.tangent;
-				float3 bitangent = cross(normal, tangent.xyz) * tangent.w;
-				tangentSign = tangent.w * gWorldDeterminantSign;
-				
-				// Note: Maybe it's better to store everything in row vector format?
-				output[0][0] = tangent.x;
-				output[1][0] = tangent.y;
-				output[2][0] = tangent.z;
-				
-				output[0][1] = bitangent.x;
-				output[1][1] = bitangent.y;
-				output[2][1] = bitangent.z;
-				
-				output[0][2] = normal.x;
-				output[1][2] = normal.y;
-				output[2][2] = normal.z;
-								
-				return output;
-			}
-
 			VStoFS main(VertexInput input)
 			{
 				VStoFS output;
 			
-				float4 worldPosition = mul(gMatWorld, float4(input.position, 1));
-			
-				output.position = mul(gMatViewProj, worldPosition);
-				output.worldPosition = worldPosition.xyz;
-				output.uv0 = input.uv0;
+				VertexIntermediate intermediate = getVertexIntermediate(input);
+				float4 worldPosition = getVertexWorldPosition(input, intermediate);
 				
-				float tangentSign;
-				float3x3 tangentToWorld = mul((float3x3)gMatWorldNoScale, getTangentToObject(input, tangentSign));
-
-				output.tangentToWorldZ = float3(tangentToWorld._m02_m12_m22); // Normal basis vector
-				output.tangentToWorldX = float4(tangentToWorld._m00_m10_m20, tangentSign); // Tangent basis vector
-										
+				output.position = mul(gMatViewProj, worldPosition);
+				populateVertexOutput(input, intermediate, output);
+							
 				return output;
 			}
 		};
@@ -99,55 +53,18 @@ Technique =
 	
 	Pass =
 	{
-		Common = 
-		{
-			varying vec4 position;
-			varying vec2 uv0;
-			varying vec3 worldPosition;
-			varying vec3 tangentToWorldZ;
-			varying vec4 tangentToWorldX;	
-		};
-	
 		Vertex =
 		{			
-			in vec3 bs_position;
-			in vec3 bs_normal;
-			in vec4 bs_tangent;
-			in vec2 bs_texcoord0;
-		
-			out gl_PerVertex
-			{
-				vec4 gl_Position;
-			};		
-							
-			void getTangentToObject(vec3 normal, vec4 tangent, out float tangentSign, out mat3 tangentToObject)
-			{
-				vec3 bitangent = cross(normal, tangent.xyz) * tangent.w;
-				tangentSign = tangent.w * gWorldDeterminantSign;
-				
-				tangentToObject[0] = tangent.xyz;
-				tangentToObject[1] = bitangent;
-				tangentToObject[2] = normal;
-			}
-
 			void main()
 			{
-				vec4 worldPos = gMatWorld * vec4(bs_position, 1);
+				VertexIntermediate intermediate;
+				getVertexIntermediate(intermediate);
 			
-				position = gMatViewProj * worldPos;
-				worldPosition = worldPos.xyz;
-				uv0 = bs_texcoord0;
-				
-				float tangentSign;
-				mat3 tangentToObject;
-				getTangentToObject(bs_normal, bs_tangent, tangentSign, tangentToObject);
-				
-				mat3 tangentToWorld = mat3(gMatWorldNoScale) * tangentToObject;
-
-				tangentToWorldZ = tangentToWorld[2]; // Normal basis vector
-				tangentToWorldX = vec4(tangentToWorld[0].xyz, tangentSign); // Tangent basis vector
-				
-				gl_Position = position;
+				vec4 worldPos;
+				getVertexWorldPosition(worldPos, intermediate);
+			
+				gl_Position = gMatViewProj * worldPos;
+				populateVertexOutput(intermediate);
 			}
 		};
 		

+ 147 - 0
Data/Raw/Engine/Includes/NormalVertexInput.bslinc

@@ -0,0 +1,147 @@
+Technique =
+{
+	Language = "HLSL11";
+	
+	Pass =
+	{
+		Common = 
+		{
+			struct VStoFS
+			{
+				float4 position : SV_Position;
+				float2 uv0 : TEXCOORD0;
+				
+				float3 tangentToWorldZ : NORMAL; // Note: Half-precision could be used
+				float4 tangentToWorldX : TANGENT; // Note: Half-precision could be used
+			};
+		};
+
+		Vertex =
+		{
+			struct VertexInput
+			{
+				float3 position : POSITION;
+				float3 normal : NORMAL; // Note: Half-precision could be used
+				float4 tangent : TANGENT; // Note: Half-precision could be used
+				float2 uv0 : TEXCOORD0;
+			};
+			
+			struct VertexIntermediate
+			{
+				float3 worldNormal; // Note: Half-precision could be used
+				float4 worldTangent; // Note: Half-precision could be used
+				
+				float tangentSign;
+			};
+			
+			float3x3 getTangentToLocal(VertexInput input, out float tangentSign)
+			{
+				float3 normal = input.normal;
+				float4 tangent = input.tangent;
+				float3 bitangent = cross(normal, tangent.xyz) * tangent.w;
+				tangentSign = tangent.w * gWorldDeterminantSign;
+				
+				// Note: Maybe it's better to store everything in row vector format?
+				float3x3 result = float3x3(tangent.xyz, bitangent, normal);
+				result = transpose(result);
+												
+				return result;
+			}
+			
+			VertexIntermediate getVertexIntermediate(VertexInput input)
+			{
+				VertexIntermediate result;
+				
+				float tangentSign;
+				float3x3 tangentToLocal = getTangentToLocal(input, tangentSign);
+				float3x3 tangentToWorld = mul((float3x3)gMatWorldNoScale, tangentToLocal);
+				
+				result.worldNormal = float3(tangentToWorld._m02_m12_m22); // Normal basis vector
+				result.worldTangent = float4(tangentToWorld._m00_m10_m20, tangentSign); // Tangent basis vector
+				
+				return result;
+			}
+			
+			float4 getVertexWorldPosition(VertexInput input, VertexIntermediate intermediate)
+			{
+				return mul(gMatWorld, float4(input.position, 1));
+			}
+			
+			void populateVertexOutput(VertexInput input, VertexIntermediate intermediate, inout VStoFS result)
+			{
+				result.uv0 = input.uv0;
+				
+				result.tangentToWorldZ = intermediate.worldNormal;
+				result.tangentToWorldX = intermediate.worldTangent;
+			}
+		};
+	};
+};
+
+Technique =
+{
+	Language = "GLSL";
+	
+	Pass =
+	{
+		Common = 
+		{
+			varying vec2 uv0;
+			varying vec3 tangentToWorldZ;
+			varying vec4 tangentToWorldX;	
+		};
+	
+		Vertex =
+		{			
+			in vec3 bs_position;
+			in vec3 bs_normal;
+			in vec4 bs_tangent;
+			in vec2 bs_texcoord0;
+		
+			struct VertexIntermediate
+			{
+				vec3 worldNormal;
+				vec4 worldTangent;
+			};
+		
+			out gl_PerVertex
+			{
+				vec4 gl_Position;
+			};
+							
+			void getTangentToLocal(vec3 normal, vec4 tangent, out float tangentSign, out mat3 tangentToLocal)
+			{
+				vec3 bitangent = cross(normal, tangent.xyz) * tangent.w;
+				tangentSign = tangent.w * gWorldDeterminantSign;
+				
+				tangentToLocal[0] = tangent.xyz;
+				tangentToLocal[1] = bitangent;
+				tangentToLocal[2] = normal;
+			}
+
+			void getVertexIntermediate(out VertexIntermediate result)
+			{
+				float tangentSign;
+				mat3 tangentToLocal;
+				getTangentToLocal(bs_normal, bs_tangent, tangentSign, tangentToLocal);
+				
+				mat3 tangentToWorld = mat3(gMatWorldNoScale) * tangentToLocal;
+				result.worldNormal = intermediate.tangentToWorld[2]; // Normal basis vector
+				result.worldTangent = vec4(intermediate.tangentToWorld[0].xyz, intermediate.tangentSign); // Tangent basis vector
+			}
+			
+			void getVertexWorldPosition(out vec4 result)
+			{
+				result = gMatWorld * vec4(bs_position, 1);
+			}
+			
+			void populateVertexOutput(VertexIntermediate intermediate)
+			{
+				uv0 = bs_texcoord0;
+				
+				tangentToWorldZ = intermediate.worldNormal;
+				tangentToWorldX = intermediate.worldTangent;
+			}
+		};
+	};
+};

+ 193 - 0
Data/Raw/Engine/Includes/SkinnedVertexInput.bslinc

@@ -0,0 +1,193 @@
+Technique =
+{
+	Language = "HLSL11";
+	
+	Pass =
+	{
+		Common = 
+		{
+			struct VStoFS
+			{
+				float4 position : SV_Position;
+				float2 uv0 : TEXCOORD0;
+				
+				float3 tangentToWorldZ : NORMAL; // Note: Half-precision could be used
+				float4 tangentToWorldX : TANGENT; // Note: Half-precision could be used
+			};
+		};
+
+		Vertex =
+		{
+			StructuredBuffer<float4> boneMatrices;
+		
+			struct VertexInput
+			{
+				float3 position : POSITION;
+				float3 normal : NORMAL; // Note: Half-precision could be used
+				float4 tangent : TANGENT; // Note: Half-precision could be used
+				float2 uv0 : TEXCOORD0;
+				uint4 blendIndices : BLENDINDICES;
+				float4 blendWeights : BLENDWEIGHT;
+				
+				#if USE_BLEND_SHAPES
+					float3 deltaPosition : POSITION1;
+					float4 deltaNormal : NORMAL1;
+				#endif
+			};
+			
+			struct VertexIntermediate
+			{
+				float3x4 blendMatrix;
+			
+				float3 worldNormal; // Note: Half-precision could be used
+				float4 worldTangent; // Note: Half-precision could be used
+			};
+			
+			float3x4 getBoneMatrix(uint idx)
+			{
+				float4 row0 = boneMatrices[idx * 3 + 0];
+				float4 row1 = boneMatrices[idx * 3 + 1];
+				float4 row2 = boneMatrices[idx * 3 + 2];
+				
+				return float3x4(row0, row1, row2);
+			}
+			
+			float3x4 getBlendMatrix(VertexInput input)
+			{
+				float3x4 result = input.blendWeights.x * boneMatrices[input.blendIndices.x];
+				result += input.blendWeights.y * boneMatrices[input.blendIndices.y];
+				result += input.blendWeights.z * boneMatrices[input.blendIndices.z];
+				result += input.blendWeights.w * boneMatrices[input.blendIndices.w];
+				
+				return result;
+			}
+			
+			float3x3 getSkinnedTangentToLocal(VertexInput input, float3x4 blendMatrix, out float tangentSign)
+			{
+				tangentSign = input.tangent.w;
+			
+				#if USE_BLEND_SHAPES
+					float3 normal = input.normal;
+					float3 tangent = input.tangent.xyz;
+					
+					normal = normalize(normal + input.deltaNormal * input.deltaNormal.w);
+					tangent = normalize(tangent - dot(tangent, normal) * normal);
+				#else
+					float3 normal = input.normal;
+					float3 tangent = input.tangent.xyz;
+				#endif
+				
+				normal = mul(blendMatrix, float4(normal, 0.0f)).xyz;
+				tangent = mul(blendMatrix, float4(tangent, 0.0f)).xyz;
+				
+				float3 bitangent = cross(normal, tangent) * tangentSign;
+				tangentSign *= gWorldDeterminantSign;
+				
+				float3x3 result = float3x3(tangent, bitangent, normal);
+				result = transpose(result);
+												
+				return result;
+			}
+			
+			VertexIntermediate getVertexIntermediate(VertexInput input)
+			{
+				VertexIntermediate result;
+				
+				result.blendMatrix = getBlendMatrix(input);
+				
+				float tangentSign;
+				float3x3 tangentToLocal = getSkinnedTangentToLocal(input, result.blendMatrix, tangentSign);
+				float3x3 tangentToWorld = mul((float3x3)gMatWorldNoScale, tangentToLocal);
+				
+				result.worldNormal = float3(tangentToWorld._m02_m12_m22); // Normal basis vector
+				result.worldTangent = float4(tangentToWorld._m00_m10_m20, tangentSign); // Tangent basis vector
+				
+				return result;
+			}
+			
+			float4 getVertexWorldPosition(VertexInput input, VertexIntermediate intermediate)
+			{
+				#if USE_BLEND_SHAPES
+					float4 position = float4(input.position + input.deltaPosition, 1.0f);
+				#else
+					float4 position = float4(input.position, 1.0f);
+				#endif
+			
+				position = mul(intermediate.blendMatrix, position);
+				return mul(gMatWorld, position);
+			}
+			
+			void populateVertexOutput(VertexInput input, VertexIntermediate intermediate, inout VStoFS result)
+			{
+				result.uv0 = input.uv0;
+				
+				result.tangentToWorldZ = float3(intermediate.tangentToWorld._m02_m12_m22); // Normal basis vector
+				result.tangentToWorldX = float4(intermediate.tangentToWorld._m00_m10_m20, tangentSign); // Tangent basis vector
+			}
+		};
+	};
+};
+
+Technique =
+{
+	Language = "GLSL";
+	
+	Pass =
+	{
+		Common = 
+		{
+			varying vec2 uv0;
+			varying vec3 tangentToWorldZ;
+			varying vec4 tangentToWorldX;	
+		};
+	
+		Vertex =
+		{			
+			in vec3 bs_position;
+			in vec3 bs_normal;
+			in vec4 bs_tangent;
+			in vec2 bs_texcoord0;
+		
+			struct VertexIntermediate
+			{
+				mat3 tangentToLocal;
+				mat3 tangentToWorld;
+				float tangentSign;
+			};
+		
+			out gl_PerVertex
+			{
+				vec4 gl_Position;
+			};
+							
+			void getTangentToLocal(vec3 normal, vec4 tangent, out float tangentSign, out mat3 tangentToObject)
+			{
+				vec3 bitangent = cross(normal, tangent.xyz) * tangent.w;
+				tangentSign = tangent.w * gWorldDeterminantSign;
+				
+				tangentToObject[0] = tangent.xyz;
+				tangentToObject[1] = bitangent;
+				tangentToObject[2] = normal;
+			}
+
+			void getVertexIntermediate(out VertexIntermediate result)
+			{
+				getTangentToLocal(bs_normal, bs_tangent, result.tangentSign, result.tangentToLocal);
+				result.tangentToWorld = mat3(gMatWorldNoScale) * result.tangentToLocal;
+			}
+			
+			void getVertexWorldPosition(out vec4 result)
+			{
+				result = gMatWorld * vec4(bs_position, 1);
+			}
+			
+			void populateVertexOutput(VertexIntermediate intermediate)
+			{
+				uv0 = bs_texcoord0;
+				
+				tangentToWorldZ = intermediate.tangentToWorld[2]; // Normal basis vector
+				tangentToWorldX = vec4(intermediate.tangentToWorld[0].xyz, intermediate.tangentSign); // Tangent basis vector
+			}
+		};
+	};
+};