制作过程中突发奇想,让AI帮忙写的,也是把论坛当书签用了
CCEffect %{
techniques:
- name: opaque
passes:
- vert: triplanar-vs:vert
frag: triplanar-fs:frag
depthStencilState:
depthTest: true
depthWrite: true
blendState:
targets:
- blend: false
properties:
mainTexture: { value: white }
tiling: { value: [4.0, 4.0, 4.0, 1.0], editor: { type: vector } }
sharpness: { value: 4.0, editor: { slider: true, min: 1, max: 10 } }
offset: { value: [0.0, 0.0, 0.0, 0.0], editor: { type: vector } }
- name: transparent
passes:
- vert: triplanar-vs:vert
frag: triplanar-fs:frag
depthStencilState:
depthTest: true
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
properties:
mainTexture: { value: white }
tiling: { value: [4.0, 4.0, 4.0, 1.0] }
sharpness: { value: 4.0 }
offset: { value: [0.0, 0.0, 0.0, 0.0] }
}%
CCProgram triplanar-vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec3 a_normal;
out vec3 v_position;
out vec3 v_normal;
vec4 vert () {
// 计算世界空间位置和法线
vec4 worldPos = cc_matWorld * vec4(a_position, 1.0);
v_position = worldPos.xyz;
v_normal = normalize((cc_matWorldIT * vec4(a_normal, 0.0)).xyz);
return cc_matViewProj * worldPos;
}
}%
CCProgram triplanar-fs %{
precision highp float;
#include <legacy/output>
uniform sampler2D mainTexture;
// 关键修正:调整UBO内变量的声明顺序,将所有的vec4类型变量放在一起
uniform TriplanarParams {
vec4 tiling; // vec4 类型变量
vec4 offset; // vec4 类型变量,现在紧挨着另一个vec4声明
float sharpness; // float 类型变量,现在被移到了所有vec4之后
};
in vec3 v_position;
in vec3 v_normal;
vec4 frag () {
// 使用世界坐标减去偏移量,确保贴图跟随物体移动
vec3 worldPosWithOffset = v_position - offset.xyz;
// 计算三个平面的纹理坐标(基于偏移后的世界坐标)
vec2 uvXZ = worldPosWithOffset.xz / tiling.x;
vec2 uvXY = worldPosWithOffset.xy / tiling.y;
vec2 uvZY = worldPosWithOffset.zy / tiling.z;
// 采样纹理
vec4 colXZ = texture(mainTexture, uvXZ);
vec4 colXY = texture(mainTexture, uvXY);
vec4 colZY = texture(mainTexture, uvZY);
// 基于法线计算混合权重
vec3 weights = pow(abs(v_normal), vec3(sharpness));
weights = weights / (weights.x + weights.y + weights.z);
// 混合颜色
vec4 finalColor = colXZ * weights.y + colXY * weights.z + colZY * weights.x;
return CCFragOutput(finalColor);
}
}%
如果需要模型在移动的过程中贴图跟着模型移动而不是停留在原地,可以使用此方法
protected update(deltaTime: number) {
// 获取物体世界坐标
const worldPos = this.node.worldPosition;
// 设置材质的offset参数
if (this.material) {
this.material.setProperty("offset", new Vec4(worldPos.x, worldPos.y, worldPos.z, 0));
}
}