Pixel-Composer/shaders/BBMOD_ShDefaultUnlitAnimated/BBMOD_ShDefaultUnlitAnimated.vsh
2023-04-23 16:47:33 +02:00

148 lines
3.8 KiB
GLSL

// FIXME: Temporary fix!
precision highp float;
////////////////////////////////////////////////////////////////////////////////
//
// Defines
//
// Maximum number of bones of animated models
#define BBMOD_MAX_BONES 128
// Maximum number of vec4 uniforms for dynamic batch data
#define BBMOD_MAX_BATCH_VEC4S 192
////////////////////////////////////////////////////////////////////////////////
//
// Attributes
//
attribute vec4 in_Position;
attribute vec3 in_Normal;
attribute vec2 in_TextureCoord0;
attribute vec4 in_TangentW;
attribute vec4 in_BoneIndex;
attribute vec4 in_BoneWeight;
////////////////////////////////////////////////////////////////////////////////
//
// Uniforms
//
uniform vec2 bbmod_TextureOffset;
uniform vec2 bbmod_TextureScale;
uniform vec4 bbmod_Bones[2 * BBMOD_MAX_BONES];
////////////////////////////////////////////////////////////////////////////////
//
// Varyings
//
varying vec3 v_vVertex;
varying vec2 v_vTexCoord;
varying mat3 v_mTBN;
varying vec4 v_vPosition;
varying vec4 v_vPosShadowmap;
////////////////////////////////////////////////////////////////////////////////
//
// Includes
//
vec3 QuaternionRotate(vec4 q, vec3 v)
{
return (v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v));
}
vec3 DualQuaternionTransform(vec4 real, vec4 dual, vec3 v)
{
return (QuaternionRotate(real, v)
+ 2.0 * (real.w * dual.xyz - dual.w * real.xyz + cross(real.xyz, dual.xyz)));
}
/// @desc Transforms vertex and normal by animation and/or batch data.
///
/// @param vertex Variable to hold the transformed vertex.
/// @param normal Variable to hold the transformed normal.
/// @param tangent Variable to hold the transformed tangent.
/// @param bitangent Variable to hold the transformed bitangent.
void Transform(
inout vec4 vertex,
inout vec3 normal,
inout vec3 tangent,
inout vec3 bitangent)
{
// Source:
// https://www.cs.utah.edu/~ladislav/kavan07skinning/kavan07skinning.pdf
// https://www.cs.utah.edu/~ladislav/dq/dqs.cg
ivec4 i = ivec4(in_BoneIndex) * 2;
ivec4 j = i + 1;
vec4 real0 = bbmod_Bones[i.x];
vec4 real1 = bbmod_Bones[i.y];
vec4 real2 = bbmod_Bones[i.z];
vec4 real3 = bbmod_Bones[i.w];
vec4 dual0 = bbmod_Bones[j.x];
vec4 dual1 = bbmod_Bones[j.y];
vec4 dual2 = bbmod_Bones[j.z];
vec4 dual3 = bbmod_Bones[j.w];
if (dot(real0, real1) < 0.0) { real1 *= -1.0; dual1 *= -1.0; }
if (dot(real0, real2) < 0.0) { real2 *= -1.0; dual2 *= -1.0; }
if (dot(real0, real3) < 0.0) { real3 *= -1.0; dual3 *= -1.0; }
vec4 blendReal =
real0 * in_BoneWeight.x
+ real1 * in_BoneWeight.y
+ real2 * in_BoneWeight.z
+ real3 * in_BoneWeight.w;
vec4 blendDual =
dual0 * in_BoneWeight.x
+ dual1 * in_BoneWeight.y
+ dual2 * in_BoneWeight.z
+ dual3 * in_BoneWeight.w;
float len = length(blendReal);
blendReal /= len;
blendDual /= len;
vertex = vec4(DualQuaternionTransform(blendReal, blendDual, vertex.xyz), 1.0);
normal = QuaternionRotate(blendReal, normal);
tangent = QuaternionRotate(blendReal, tangent);
bitangent = QuaternionRotate(blendReal, bitangent);
vertex = gm_Matrices[MATRIX_WORLD] * vertex;
normal = normalize((gm_Matrices[MATRIX_WORLD] * vec4(normal, 0.0)).xyz);
tangent = normalize((gm_Matrices[MATRIX_WORLD] * vec4(tangent, 0.0)).xyz);
bitangent = normalize((gm_Matrices[MATRIX_WORLD] * vec4(bitangent, 0.0)).xyz);
}
////////////////////////////////////////////////////////////////////////////////
//
// Main
//
void main()
{
vec4 position = in_Position;
vec3 normal = in_Normal;
vec3 tangent = in_TangentW.xyz;
vec3 bitangent = cross(normal, tangent) * in_TangentW.w;
Transform(position, normal, tangent, bitangent);
vec4 positionWVP = gm_Matrices[MATRIX_PROJECTION] * (gm_Matrices[MATRIX_VIEW] * position);
v_vVertex = position.xyz;
gl_Position = positionWVP;
v_vPosition = positionWVP;
v_vTexCoord = bbmod_TextureOffset + in_TextureCoord0 * bbmod_TextureScale;
v_mTBN = mat3(tangent, bitangent, normal);
}