You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebGL实现3D狗模型头部到尾部强度递减棋盘格纹理咨询

嘿,这个从头部到尾部线性递减的棋盘格纹理效果,其实不用修改你现有的纹理生成代码,核心是在片元着色器里结合模型的位置信息来做混合!我给你拆解几个关键步骤:


第一步:传递模型/世界空间的位置到片元着色器

我们需要一个能区分“头部”和“尾部”的坐标——比如假设你的狗狗模型头尾是沿着Z轴延伸的(你可以根据自己的模型调整为X/Y轴),每个顶点的位置就能帮我们计算当前片元的纹理强度。

方案A:用世界空间位置(不用改顶点数据)

在顶点着色器里,把模型矩阵转换后的世界位置传给片元着色器:

// 顶点着色器
attribute vec4 aPosition;
attribute vec2 aTexCoord;
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;

varying vec2 vTexCoord;
varying vec3 vWorldPos; // 传递世界空间位置到片元

void main() {
    vTexCoord = aTexCoord;
    vec4 worldPos = uModelMatrix * aPosition;
    vWorldPos = worldPos.xyz;
    gl_Position = uProjectionMatrix * uViewMatrix * worldPos;
}

方案B:用模型空间原始位置(需要修改顶点数据)

如果你的顶点数组里本来就存了模型空间的原始位置,直接把它作为顶点属性传递就行,原理和上面一样,只是不用乘模型矩阵。


第二步:在片元着色器里计算强度并混合纹理

这一步是核心:先采样棋盘格纹理,再根据位置计算强度,最后把纹理色和模型基础色混合。

// 片元着色器
precision mediump float;

varying vec2 vTexCoord;
varying vec3 vWorldPos;
uniform sampler2D uCheckerboardTex;

// 你需要根据自己的模型调整这两个值:头部对应的最大Z,尾部对应的最小Z
uniform float uMaxZ; 
uniform float uMinZ;

void main() {
    // 1. 采样棋盘格纹理
    vec4 checkerColor = texture2D(uCheckerboardTex, vTexCoord);
    
    // 2. 计算线性递减的强度:头部(uMaxZ)强度为1,尾部(uMinZ)强度为0
    // clamp确保强度不会超出0-1范围(比如耳朵、爪子这类超出头尾范围的部位)
    float intensity = clamp((vWorldPos.z - uMinZ) / (uMaxZ - uMinZ), 0.0, 1.0);
    // 如果你的头部Z值更小,就反过来算:intensity = clamp((uMaxZ - vWorldPos.z)/(uMaxZ - uMinZ), 0.0, 1.0);
    
    // 3. 混合纹理色和模型基础色(这里假设模型基础色是白色,你可以换成自己的模型颜色变量)
    vec4 baseColor = vec4(1.0); // 替换成你的模型基础色,比如varying vec3 vColor;
    vec4 finalColor = mix(baseColor, checkerColor, intensity);
    
    gl_FragColor = finalColor;
}

第三步:在JS里传递必要的Uniform变量

你需要在JS里把uMaxZ、uMinZ和uCheckerboardTex传给着色器:

// 先遍历你的模型顶点,找到Z轴的最大最小值(假设你的顶点数组是vertices)
let minZ = Infinity;
let maxZ = -Infinity;
for(let i=0; i<vertices.length; i+=3) { // 假设每个顶点是x,y,z三个值
    const z = vertices[i+2];
    if(z < minZ) minZ = z;
    if(z > maxZ) maxZ = z;
}

// 在渲染循环里(或者初始化时)传递uniform
const maxZLoc = gl.getUniformLocation(program, 'uMaxZ');
const minZLoc = gl.getUniformLocation(program, 'uMinZ');
const texLoc = gl.getUniformLocation(program, 'uCheckerboardTex');

gl.uniform1f(maxZLoc, maxZ);
gl.uniform1f(minZLoc, minZ);
gl.uniform1i(texLoc, 0); // 绑定到纹理单元0

小提示

  • 如果你的狗狗头尾不是Z轴,把代码里的vWorldPos.z换成vWorldPos.x或vWorldPos.y就行;
  • 要是想让纹理从头部到尾部逐渐消失(而不是和基础色混合),可以直接把checkerColor的alpha通道乘上强度:checkerColor.a *= intensity;,然后和基础色混合;
  • 你现有的纹理生成代码完全不用改,保持原来的棋盘格生成逻辑就好!

内容的提问来源于stack exchange,提问作者user9516512

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:27:45