mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 19:02:55 +02:00
Better naming and simpler template maybe
This commit is contained in:
parent
34203c67b0
commit
4078be3df5
5 changed files with 52 additions and 197 deletions
|
@ -24,11 +24,6 @@ struct TexMapArray {
|
||||||
|
|
||||||
<@func declareMaterialTexMapArrayBuffer()@>
|
<@func declareMaterialTexMapArrayBuffer()@>
|
||||||
|
|
||||||
//layout(binding=GRAPHICS_BUFFER_TEXMAPARRAY) uniform texMapArrayBuffer {
|
|
||||||
// TexMapArray _texMapArray;
|
|
||||||
//};
|
|
||||||
|
|
||||||
|
|
||||||
<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@>
|
<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@>
|
||||||
{
|
{
|
||||||
<$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st;
|
<$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st;
|
||||||
|
|
|
@ -11,44 +11,8 @@
|
||||||
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
||||||
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
||||||
|
|
||||||
<!<@include graphics/ShaderConstants.h@>!>
|
|
||||||
<@include graphics/Material.slh@>
|
<@include graphics/Material.slh@>
|
||||||
|
|
||||||
<!
|
|
||||||
<@func declareMaterialTexMapArrayBuffer()@>
|
|
||||||
|
|
||||||
const int MAX_TEXCOORDS = 2;
|
|
||||||
|
|
||||||
struct TexMapArray {
|
|
||||||
// mat4 _texcoordTransforms[MAX_TEXCOORDS];
|
|
||||||
mat4 _texcoordTransforms0;
|
|
||||||
mat4 _texcoordTransforms1;
|
|
||||||
vec4 _lightmapParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding=GRAPHICS_BUFFER_TEXMAPARRAY) uniform texMapArrayBuffer {
|
|
||||||
TexMapArray _texMapArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
TexMapArray getTexMapArray() {
|
|
||||||
return _texMapArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@>
|
|
||||||
{
|
|
||||||
<$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st;
|
|
||||||
}
|
|
||||||
<@endfunc@>
|
|
||||||
|
|
||||||
<@func evalTexMapArrayTexcoord1(texMapArray, inTexcoord1, outTexcoord1)@>
|
|
||||||
{
|
|
||||||
<$outTexcoord1$> = (<$texMapArray$>._texcoordTransforms1 * vec4(<$inTexcoord1$>.st, 0.0, 1.0)).st;
|
|
||||||
}
|
|
||||||
<@endfunc@>
|
|
||||||
|
|
||||||
<@endfunc@>
|
|
||||||
!>
|
|
||||||
|
|
||||||
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
||||||
|
|
||||||
#define TAA_TEXTURE_LOD_BIAS -1.0
|
#define TAA_TEXTURE_LOD_BIAS -1.0
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<@if not BLENDSHAPE_SLH@>
|
<@if not BLENDSHAPE_SLH@>
|
||||||
<@def BLENDSHAPE_SLH@>
|
<@def BLENDSHAPE_SLH@>
|
||||||
|
|
||||||
<@func declareApplyBlendshapeOffsets(USE_NORMAL, USE_TANGENT)@>
|
<@func declareBlendshape(USE_NORMAL, USE_TANGENT)@>
|
||||||
|
|
||||||
struct BlendshapeOffset {
|
struct BlendshapeOffset {
|
||||||
vec4 position;
|
vec4 position;
|
||||||
|
@ -39,7 +39,7 @@ BlendshapeOffset getBlendshapeOffset(int i) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void applyBlendshapeOffset(int i, vec4 inPosition, out vec4 position
|
void evalBlendshape(int i, vec4 inPosition, out vec4 position
|
||||||
<@if USE_NORMAL@>
|
<@if USE_NORMAL@>
|
||||||
, vec3 inNormal, out vec3 normal
|
, vec3 inNormal, out vec3 normal
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
|
@ -14,12 +14,12 @@
|
||||||
|
|
||||||
<@if USE_SKINNING@>
|
<@if USE_SKINNING@>
|
||||||
<@include Skinning.slh@>
|
<@include Skinning.slh@>
|
||||||
<$declareUseDualQuaternionSkinning($USE_DUAL_QUATERNION$) $>
|
<$declareSkinning($USE_DUAL_QUATERNION$, $USE_NORMAL$, $USE_TANGENT$)$>
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
<@if USE_BLENDSHAPE@>
|
<@if USE_BLENDSHAPE@>
|
||||||
<@include Blendshape.slh@>
|
<@include Blendshape.slh@>
|
||||||
<$declareApplyBlendshapeOffsets($USE_NORMAL$, $USE_TANGENT$)$>
|
<$declareBlendshape($USE_NORMAL$, $USE_TANGENT$)$>
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
void evalMeshDeformer(vec4 inPosition, out vec4 outPosition
|
void evalMeshDeformer(vec4 inPosition, out vec4 outPosition
|
||||||
|
@ -47,30 +47,28 @@ void evalMeshDeformer(vec4 inPosition, out vec4 outPosition
|
||||||
|
|
||||||
<@if USE_BLENDSHAPE@>
|
<@if USE_BLENDSHAPE@>
|
||||||
if (isBlendshapeEnabled) {
|
if (isBlendshapeEnabled) {
|
||||||
|
evalBlendshape(vertexIndex, inPosition, _deformedPosition
|
||||||
<@if USE_TANGENT@>
|
|
||||||
applyBlendshapeOffset(vertexIndex, inPosition, _deformedPosition, inNormal, _deformedNormal, inTangent, _deformedTangent);
|
|
||||||
<@else@>
|
|
||||||
<@if USE_NORMAL@>
|
<@if USE_NORMAL@>
|
||||||
applyBlendshapeOffset(vertexIndex, inPosition, _deformedPosition, inNormal, _deformedNormal);
|
, inNormal, _deformedNormal
|
||||||
<@else@>
|
|
||||||
applyBlendshapeOffset(vertexIndex, inPosition, _deformedPosition);
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
|
, inTangent, _deformedTangent
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
<@if USE_SKINNING@>
|
<@if USE_SKINNING@>
|
||||||
if (isSkinningEnabled) {
|
if (isSkinningEnabled) {
|
||||||
<@if USE_TANGENT@>
|
|
||||||
skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, _deformedPosition, _deformedNormal, _deformedTangent, _deformedPosition, _deformedNormal, _deformedTangent);
|
evalSkinning(inSkinClusterIndex, inSkinClusterWeight, _deformedPosition, _deformedPosition
|
||||||
<@else@>
|
|
||||||
<@if USE_NORMAL@>
|
<@if USE_NORMAL@>
|
||||||
skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, _deformedPosition, _deformedNormal, _deformedPosition, _deformedNormal);
|
, _deformedNormal, _deformedNormal
|
||||||
<@else@>
|
|
||||||
skinPosition(inSkinClusterIndex, inSkinClusterWeight, _deformedPosition, _deformedPosition);
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
|
, _deformedTangent, _deformedTangent
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
|
|
||||||
<@include graphics/ShaderConstants.h@>
|
<@include graphics/ShaderConstants.h@>
|
||||||
|
|
||||||
|
<@func declareSkinning(USE_DUAL_QUATERNION_SKINNING, USE_NORMAL, USE_TANGENT)@>
|
||||||
|
|
||||||
const int MAX_CLUSTERS = 128;
|
const int MAX_CLUSTERS = 128;
|
||||||
const int INDICES_PER_VERTEX = 4;
|
const int INDICES_PER_VERTEX = 4;
|
||||||
|
|
||||||
<@func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)@>
|
|
||||||
|
|
||||||
layout(std140, binding=GRAPHICS_BUFFER_SKINNING) uniform skinClusterBuffer {
|
layout(std140, binding=GRAPHICS_BUFFER_SKINNING) uniform skinClusterBuffer {
|
||||||
mat4 clusterMatrices[MAX_CLUSTERS];
|
mat4 clusterMatrices[MAX_CLUSTERS];
|
||||||
};
|
};
|
||||||
|
@ -55,7 +55,14 @@ mat4 dualQuatToMat4(vec4 real, vec4 dual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// dual quaternion linear blending
|
// dual quaternion linear blending
|
||||||
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
|
void evalSkinning(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition
|
||||||
|
<@if USE_NORMAL@>
|
||||||
|
, vec3 inNormal, out vec3 skinnedNormal
|
||||||
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
|
, vec3 inTangent, out vec3 skinnedTangent
|
||||||
|
<@endif@>
|
||||||
|
) {
|
||||||
|
|
||||||
// linearly blend scale and dual quaternion components
|
// linearly blend scale and dual quaternion components
|
||||||
vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
@ -102,166 +109,57 @@ void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio
|
||||||
sAccum.w = 1.0;
|
sAccum.w = 1.0;
|
||||||
skinnedPosition = m * (sAccum * inPosition);
|
skinnedPosition = m * (sAccum * inPosition);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
|
|
||||||
out vec4 skinnedPosition, out vec3 skinnedNormal) {
|
|
||||||
|
|
||||||
// linearly blend scale and dual quaternion components
|
|
||||||
vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
|
|
||||||
|
|
||||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
|
||||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
|
||||||
float clusterWeight = skinClusterWeight[i];
|
|
||||||
|
|
||||||
vec4 scale = clusterMatrix[0];
|
|
||||||
vec4 real = clusterMatrix[1];
|
|
||||||
vec4 dual = clusterMatrix[2];
|
|
||||||
vec4 cauterizedPos = clusterMatrix[3];
|
|
||||||
|
|
||||||
// to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.
|
|
||||||
float dqClusterWeight = clusterWeight;
|
|
||||||
if (dot(real, polarityReference) < 0.0) {
|
|
||||||
dqClusterWeight = -clusterWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
sAccum += scale * clusterWeight;
|
|
||||||
rAccum += real * dqClusterWeight;
|
|
||||||
dAccum += dual * dqClusterWeight;
|
|
||||||
cAccum += cauterizedPos * clusterWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalize dual quaternion
|
|
||||||
float norm = length(rAccum);
|
|
||||||
rAccum /= norm;
|
|
||||||
dAccum /= norm;
|
|
||||||
|
|
||||||
// conversion from dual quaternion to 4x4 matrix.
|
|
||||||
mat4 m = dualQuatToMat4(rAccum, dAccum);
|
|
||||||
|
|
||||||
// sAccum.w indicates the amount of cauterization for this vertex.
|
|
||||||
// 0 indicates no cauterization and 1 indicates full cauterization.
|
|
||||||
// TODO: make this cauterization smoother or implement full dual-quaternion scale support.
|
|
||||||
const float CAUTERIZATION_THRESHOLD = 0.1;
|
|
||||||
if (sAccum.w > CAUTERIZATION_THRESHOLD) {
|
|
||||||
skinnedPosition = cAccum;
|
|
||||||
} else {
|
|
||||||
sAccum.w = 1.0;
|
|
||||||
skinnedPosition = m * (sAccum * inPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
skinnedNormal = vec3(m * vec4(inNormal, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
|
|
||||||
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
|
|
||||||
|
|
||||||
// linearly blend scale and dual quaternion components
|
|
||||||
vec4 sAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 dAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 cAccum = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 polarityReference = clusterMatrices[skinClusterIndex[0]][1];
|
|
||||||
|
|
||||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
|
||||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
|
||||||
float clusterWeight = skinClusterWeight[i];
|
|
||||||
|
|
||||||
vec4 scale = clusterMatrix[0];
|
|
||||||
vec4 real = clusterMatrix[1];
|
|
||||||
vec4 dual = clusterMatrix[2];
|
|
||||||
vec4 cauterizedPos = clusterMatrix[3];
|
|
||||||
|
|
||||||
// to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity.
|
|
||||||
float dqClusterWeight = clusterWeight;
|
|
||||||
if (dot(real, polarityReference) < 0.0) {
|
|
||||||
dqClusterWeight = -clusterWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
sAccum += scale * clusterWeight;
|
|
||||||
rAccum += real * dqClusterWeight;
|
|
||||||
dAccum += dual * dqClusterWeight;
|
|
||||||
cAccum += cauterizedPos * clusterWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalize dual quaternion
|
|
||||||
float norm = length(rAccum);
|
|
||||||
rAccum /= norm;
|
|
||||||
dAccum /= norm;
|
|
||||||
|
|
||||||
// conversion from dual quaternion to 4x4 matrix.
|
|
||||||
mat4 m = dualQuatToMat4(rAccum, dAccum);
|
|
||||||
|
|
||||||
// sAccum.w indicates the amount of cauterization for this vertex.
|
|
||||||
// 0 indicates no cauterization and 1 indicates full cauterization.
|
|
||||||
// TODO: make this cauterization smoother or implement full dual-quaternion scale support.
|
|
||||||
const float CAUTERIZATION_THRESHOLD = 0.1;
|
|
||||||
if (sAccum.w > CAUTERIZATION_THRESHOLD) {
|
|
||||||
skinnedPosition = cAccum;
|
|
||||||
} else {
|
|
||||||
sAccum.w = 1.0;
|
|
||||||
skinnedPosition = m * (sAccum * inPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<@if USE_NORMAL@>
|
||||||
skinnedNormal = vec3(m * vec4(inNormal, 0));
|
skinnedNormal = vec3(m * vec4(inNormal, 0));
|
||||||
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
skinnedTangent = vec3(m * vec4(inTangent, 0));
|
skinnedTangent = vec3(m * vec4(inTangent, 0));
|
||||||
|
<@endif@>
|
||||||
}
|
}
|
||||||
|
|
||||||
<@else@> // USE_DUAL_QUATERNION_SKINNING
|
<@else@> // NOT USE_DUAL_QUATERNION_SKINNING
|
||||||
|
|
||||||
void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) {
|
// LiNEAR BLENDING
|
||||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
void evalSkinning(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition
|
||||||
|
<@if USE_NORMAL@>
|
||||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
, vec3 inNormal, out vec3 skinnedNormal
|
||||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
<@endif@>
|
||||||
float clusterWeight = skinClusterWeight[i];
|
<@if USE_TANGENT@>
|
||||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
, vec3 inTangent, out vec3 skinnedTangent
|
||||||
}
|
<@endif@>
|
||||||
|
) {
|
||||||
skinnedPosition = newPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal,
|
|
||||||
out vec4 skinnedPosition, out vec3 skinnedNormal) {
|
|
||||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
|
|
||||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
|
||||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
|
||||||
float clusterWeight = skinClusterWeight[i];
|
|
||||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
|
||||||
newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
skinnedPosition = newPosition;
|
|
||||||
skinnedNormal = newNormal.xyz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent,
|
|
||||||
out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) {
|
|
||||||
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
<@if USE_NORMAL@>
|
||||||
vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
vec4 newNormal = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);
|
vec4 newTangent = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||||
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])];
|
||||||
float clusterWeight = skinClusterWeight[i];
|
float clusterWeight = skinClusterWeight[i];
|
||||||
newPosition += clusterMatrix * inPosition * clusterWeight;
|
newPosition += clusterMatrix * inPosition * clusterWeight;
|
||||||
|
<@if USE_NORMAL@>
|
||||||
newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
|
newNormal += clusterMatrix * vec4(inNormal.xyz, 0.0) * clusterWeight;
|
||||||
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;
|
newTangent += clusterMatrix * vec4(inTangent.xyz, 0.0) * clusterWeight;
|
||||||
|
<@endif@>
|
||||||
}
|
}
|
||||||
|
|
||||||
skinnedPosition = newPosition;
|
skinnedPosition = newPosition;
|
||||||
|
<@if USE_NORMAL@>
|
||||||
skinnedNormal = newNormal.xyz;
|
skinnedNormal = newNormal.xyz;
|
||||||
|
<@endif@>
|
||||||
|
<@if USE_TANGENT@>
|
||||||
skinnedTangent = newTangent.xyz;
|
skinnedTangent = newTangent.xyz;
|
||||||
|
<@endif@>
|
||||||
}
|
}
|
||||||
|
|
||||||
<@endif@> // if USE_DUAL_QUATERNION_SKINNING
|
<@endif@> // if USE_DUAL_QUATERNION_SKINNING
|
||||||
|
|
||||||
<@endfunc@> // func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)
|
<@endfunc@> // func declareSkinning()
|
||||||
|
|
||||||
<@endif@> // if not SKINNING_SLH
|
<@endif@> // if not SKINNING_SLH
|
||||||
|
|
Loading…
Reference in a new issue