forked from Mirrors/openclonk
128 lines
4.5 KiB
GLSL
128 lines
4.5 KiB
GLSL
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 2015, The OpenClonk Team and contributors
|
|
*
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
* "COPYING" for details.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
* See accompanying file "TRADEMARK" for details.
|
|
*
|
|
* To redistribute this file separately, substitute the full license texts
|
|
* for the above references.
|
|
*/
|
|
|
|
// Default Vertex Shader for mesh-based objects.
|
|
|
|
// Input uniforms, if OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS is NOT defined:
|
|
// bones: array of 4x3 bone transformation matrices.
|
|
|
|
// Input uniforms, if OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS is defined:
|
|
// bones: array of 3x4 transposed bone transformation matrices.
|
|
|
|
// Input vertex attributes:
|
|
// oc_BoneWeights0 and oc_BoneWeight1: vectors of bone influence weights.
|
|
// The sum of weights must be 1. Each component of these vectors will be
|
|
// matched up with its corresponding component of the oc_BoneIndices0 or
|
|
// oc_BoneIndices1 vectors to specify a vertex bone assignment.
|
|
// oc_BoneIndices0 and oc_BoneIndices1: vectors of bone influence indices.
|
|
// The integer part of every component of these vectors selects one of the
|
|
// bones from the bone matrix array to influence the current vertex.
|
|
|
|
// If the vertex is not influenced by any bones, it must use a dummy entry
|
|
// inside the bone matrix array that contains the identity matrix, with a bone
|
|
// weight of 1.0.
|
|
|
|
#define MAX_BONE_COUNT 80
|
|
|
|
in vec3 oc_Position;
|
|
in vec3 oc_Normal;
|
|
in vec2 oc_TexCoord;
|
|
|
|
out vec3 vtxNormal;
|
|
out vec2 texcoord;
|
|
|
|
uniform mat4 projectionMatrix;
|
|
uniform mat4 modelviewMatrix;
|
|
uniform mat3 normalMatrix;
|
|
|
|
#ifndef OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS
|
|
uniform mat4x3 bones[MAX_BONE_COUNT];
|
|
#else
|
|
uniform mat3x4 bones[MAX_BONE_COUNT];
|
|
#endif
|
|
|
|
// For more performance, this should be set by the engine, and this shader
|
|
// should be compiled three times: with BONE_COUNT set to 0, 4, and 8,
|
|
// respectively. (Or we could split it even further.)
|
|
#define BONE_COUNT 8
|
|
|
|
in vec4 oc_BoneIndices0;
|
|
in vec4 oc_BoneWeights0;
|
|
|
|
#if BONE_COUNT > 4
|
|
in vec4 oc_BoneIndices1;
|
|
in vec4 oc_BoneWeights1;
|
|
#endif
|
|
|
|
#ifndef OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS
|
|
vec4 merge_bone(vec4 vertex, vec4 original, mat4x3 bone, float weight)
|
|
{
|
|
return (mat4(bone) * original) * weight + vertex;
|
|
}
|
|
#else
|
|
vec4 merge_bone(vec4 vertex, vec4 original, mat3x4 bone, float weight)
|
|
{
|
|
return (mat4(transpose(bone)) * original) * weight + vertex;
|
|
}
|
|
#endif
|
|
|
|
slice(position)
|
|
{
|
|
vec4 origVertex = vec4(oc_Position, 1.0);
|
|
|
|
#if BONE_COUNT == 0
|
|
gl_Position = projectionMatrix * modelviewMatrix * origVertex;
|
|
#else
|
|
vec4 vertex = vec4(0, 0, 0, 0);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices0.x)], oc_BoneWeights0.x);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices0.y)], oc_BoneWeights0.y);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices0.z)], oc_BoneWeights0.z);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices0.w)], oc_BoneWeights0.w);
|
|
#if BONE_COUNT > 4
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices1.x)], oc_BoneWeights1.x);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices1.y)], oc_BoneWeights1.y);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
|
vertex = merge_bone(vertex, origVertex, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
|
#endif
|
|
gl_Position = projectionMatrix * modelviewMatrix * vertex;
|
|
#endif
|
|
}
|
|
|
|
slice(texcoord)
|
|
{
|
|
texcoord = oc_TexCoord;
|
|
}
|
|
|
|
slice(normal)
|
|
{
|
|
#if BONE_COUNT == 0
|
|
vtxNormal = normalize(normalMatrix * oc_Normal);
|
|
#else
|
|
vec4 base_normal = vec4(oc_Normal, 0.0);
|
|
vec4 normal = vec4(0, 0, 0, 0);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices0.x)], oc_BoneWeights0.x);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices0.y)], oc_BoneWeights0.y);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices0.z)], oc_BoneWeights0.z);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices0.w)], oc_BoneWeights0.w);
|
|
#if BONE_COUNT > 4
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.x)], oc_BoneWeights1.x);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.y)], oc_BoneWeights1.y);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
|
#endif
|
|
vtxNormal = normalize(normalMatrix * normal.xyz);
|
|
#endif
|
|
}
|