mirror of
https://github.com/cocos/cocos-engine.git
synced 2026-09-07 08:09:13 +08:00
129 lines
4.1 KiB
Plaintext
129 lines
4.1 KiB
Plaintext
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
|
|
|
|
#include <common> // decode32
|
|
#pragma define-meta CC_MORPH_TARGET_COUNT range([2, 8])
|
|
|
|
#pragma builtin(local)
|
|
layout(set = 2, binding = 4) uniform CCMorph {
|
|
vec4 cc_displacementWeights[15];
|
|
vec4 cc_displacementTextureInfo;
|
|
};
|
|
|
|
/**
|
|
* Fetch n-th pixel from texture, row by row.
|
|
*/
|
|
vec2 getPixelLocation(vec2 textureResolution, int pixelIndex) {
|
|
float pixelIndexF = float(pixelIndex);
|
|
float x = mod(pixelIndexF, textureResolution.x);
|
|
float y = floor(pixelIndexF / textureResolution.x);
|
|
return vec2(x, y);
|
|
}
|
|
|
|
vec2 getPixelCoordFromLocation(vec2 location, vec2 textureResolution) {
|
|
return (vec2(location.x, location.y) + .5) / textureResolution;
|
|
}
|
|
|
|
#if CC_DEVICE_SUPPORT_FLOAT_TEXTURE
|
|
#if __VERSION__ >= 300
|
|
vec4 fetchVec3ArrayFromTexture(sampler2D tex, int pixelIndex) {
|
|
ivec2 texSize = textureSize(tex, 0);
|
|
return texelFetch(tex, ivec2(pixelIndex % texSize.x, pixelIndex / texSize.x), 0);
|
|
}
|
|
#else
|
|
vec4 fetchVec3ArrayFromTexture(sampler2D tex, int elementIndex) {
|
|
int pixelIndex = elementIndex;
|
|
vec2 location = getPixelLocation(cc_displacementTextureInfo.xy, pixelIndex);
|
|
vec2 uv = getPixelCoordFromLocation(location, cc_displacementTextureInfo.xy);
|
|
return texture(tex, uv);
|
|
}
|
|
#endif
|
|
#else
|
|
vec4 fetchVec3ArrayFromTexture(sampler2D tex, int elementIndex) {
|
|
int pixelIndex = elementIndex * 4;
|
|
vec2 location = getPixelLocation(cc_displacementTextureInfo.xy, pixelIndex);
|
|
// Here implies that the texture's width must be multiple of 4.
|
|
vec2 x = getPixelCoordFromLocation(location + vec2(0.0, 0.0), cc_displacementTextureInfo.xy);
|
|
vec2 y = getPixelCoordFromLocation(location + vec2(1.0, 0.0), cc_displacementTextureInfo.xy);
|
|
vec2 z = getPixelCoordFromLocation(location + vec2(2.0, 0.0), cc_displacementTextureInfo.xy);
|
|
return vec4(
|
|
decode32(texture(tex, x)),
|
|
decode32(texture(tex, y)),
|
|
decode32(texture(tex, z)),
|
|
1.0
|
|
);
|
|
}
|
|
#endif
|
|
|
|
float getDisplacementWeight(int index) {
|
|
int quot = index / 4;
|
|
int remainder = index - quot * 4;
|
|
if (remainder == 0) {
|
|
return cc_displacementWeights[quot].x;
|
|
} else if (remainder == 1) {
|
|
return cc_displacementWeights[quot].y;
|
|
} else if (remainder == 2) {
|
|
return cc_displacementWeights[quot].z;
|
|
} else {
|
|
return cc_displacementWeights[quot].w;
|
|
}
|
|
}
|
|
|
|
vec3 getVec3DisplacementFromTexture(sampler2D tex, int vertexIndex) {
|
|
#if CC_MORPH_PRECOMPUTED
|
|
return fetchVec3ArrayFromTexture(tex, vertexIndex).rgb;
|
|
#else
|
|
vec3 result = vec3(0, 0, 0);
|
|
int nVertices = int(cc_displacementTextureInfo.z);
|
|
for (int iTarget = 0; iTarget < CC_MORPH_TARGET_COUNT; ++iTarget) {
|
|
result += (fetchVec3ArrayFromTexture(tex, nVertices * iTarget + vertexIndex).rgb * getDisplacementWeight(iTarget));
|
|
}
|
|
return result;
|
|
#endif
|
|
}
|
|
|
|
#if CC_MORPH_TARGET_HAS_POSITION
|
|
#pragma builtin(local)
|
|
layout(set = 2, binding = 7) uniform sampler2D cc_PositionDisplacements;
|
|
vec3 getPositionDisplacement(int vertexId) {
|
|
return getVec3DisplacementFromTexture(cc_PositionDisplacements, vertexId);
|
|
}
|
|
#endif
|
|
|
|
#if CC_MORPH_TARGET_HAS_NORMAL
|
|
#pragma builtin(local)
|
|
layout(set = 2, binding = 8) uniform sampler2D cc_NormalDisplacements;
|
|
vec3 getNormalDisplacement(int vertexId) {
|
|
return getVec3DisplacementFromTexture(cc_NormalDisplacements, vertexId);
|
|
}
|
|
#endif
|
|
|
|
#if CC_MORPH_TARGET_HAS_TANGENT
|
|
#pragma builtin(local)
|
|
layout(set = 2, binding = 9) uniform sampler2D cc_TangentDisplacements;
|
|
vec3 getTangentDisplacement(int vertexId) {
|
|
return getVec3DisplacementFromTexture(cc_TangentDisplacements, vertexId);
|
|
}
|
|
#endif
|
|
|
|
void applyMorph (inout vec4 position, inout vec3 normal, inout vec4 tangent) {
|
|
int vertexId = getVertexId();
|
|
|
|
#if CC_MORPH_TARGET_HAS_POSITION
|
|
position.xyz = position.xyz + getPositionDisplacement(vertexId);
|
|
#endif
|
|
|
|
#if CC_MORPH_TARGET_HAS_NORMAL
|
|
normal.xyz = normal.xyz + getNormalDisplacement(vertexId);
|
|
#endif
|
|
|
|
#if CC_MORPH_TARGET_HAS_TANGENT
|
|
tangent.xyz = tangent.xyz + getTangentDisplacement(vertexId);
|
|
#endif
|
|
}
|
|
|
|
void applyMorph (inout vec4 position) {
|
|
#if CC_MORPH_TARGET_HAS_POSITION
|
|
position.xyz = position.xyz + getPositionDisplacement(getVertexId());
|
|
#endif
|
|
}
|