为何Three.js中vec3颜色属性在片元着色器中会被插值?
问题根源
你看到的渐变是GPU渲染管线的顶点属性插值机制导致的。PlaneGeometry表面上是4个顶点,但它的内部索引结构会把平面拆分成两个三角形(总共6个顶点索引)。你只给了4个颜色值,GPU在渲染三角形时,会自动对三角形内部的每个片元进行顶点颜色的平滑插值计算,所以最终呈现出渐变效果。
两种解决方法
方法1:为每个三角形顶点分配对应颜色
直接扩展你的颜色数组,给PlaneGeometry的6个顶点索引都分配对应的颜色值(每个三角形的三个顶点用同一种颜色)。比如PlaneGeometry的两个三角形顶点顺序通常是0,1,2和0,2,3,你可以把4个颜色扩展成6个:
// 原始4个颜色 const baseColors = [ new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff), new THREE.Color(0xffff00) ]; // 扩展为6个,对应两个三角形的顶点 const fullColors = [ baseColors[0], baseColors[1], baseColors[2], baseColors[0], baseColors[2], baseColors[3] ]; // 转换为浮点数组 const colorBuffer = new Float32Array(fullColors.length * 3); fullColors.forEach((color, i) => color.toArray(colorBuffer, i * 3)); // 为几何体添加属性 geometry.setAttribute('myColor', new THREE.BufferAttribute(colorBuffer, 3));
这样每个三角形的三个顶点颜色完全一致,GPU插值后就会呈现纯色块。
方法2:使用flat限定符关闭插值
在顶点着色器的varying变量前添加flat关键字,强制GPU不对该变量进行插值,每个三角形会使用其第一个顶点的颜色填充整个面片:
顶点着色器:
attribute vec3 myColor; flat varying vec3 vColor; void main() { vColor = myColor; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }
片元着色器:
flat varying vec3 vColor; void main() { gl_FragColor = vec4(vColor, 1.0); }
这种方法不需要修改颜色数组,适合想保留原始顶点数量的场景。
内容的提问来源于stack exchange,提问作者Justin Seo
相关产品推荐
相关产品推荐

