环境:
- three.js 0.159.0
正常情况下,我们使用BufferGeometry创建几何体后会向它里面写入:position、uv、normal甚至color属性,那么我们可不可以写入其他任意属性呢?
当然是可以的,比如:
//注意: 因为就3个顶点, 每个顶点一个数据所以是 [0.8, 0.8, 0.8]
geometry.setAttribute("testabc", new THREE.BufferAttribute(new Float32Array([0.8, 0.8, 0.8]), 1));
传入数据后我们就可以在shader中访问了:
const material = new THREE.ShaderMaterial({
vertexShader: `
attribute float testabc;
varying float vTestabc;
void main() {
vTestabc = testabc;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying float vTestabc;
void main() {
gl_FragColor = vec4(vTestabc, 0.0, 0.0, 1.0);
}
`
});
这样就可以通过自定义参数控制shader中的代码对不同的物体有不同的效果,一个简单示例如下:

完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.159.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.159.0/examples/jsm/"
}
}
</script>
</head>
<body>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
let camera, scene, renderer;
//基础对象
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100000);
camera.position.set(500, 500, 500);
camera.updateProjectionMatrix();
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 5;
controls.maxDistance = 100000;
controls.update()
scene = new THREE.Scene();
//坐标轴
const axesHelper = new THREE.AxesHelper(200);
scene.add(axesHelper);
//物体1-几何体
const geometry1 = new THREE.BufferGeometry();
geometry1.setAttribute('position', new THREE.BufferAttribute(new Float32Array([
0, 0, 0,
100, 0, 0,
100, 100, 0
]), 3));
geometry1.setAttribute("testabc", new THREE.BufferAttribute(new Float32Array([0.2, 0.2, 0.2]), 1));
//物体1-几何体
const geometry2 = new THREE.BufferGeometry();
geometry2.setAttribute('position', new THREE.BufferAttribute(new Float32Array([
0, -100, 0,
100, -100, 0,
100, 0, 0
]), 3));
geometry2.setAttribute("testabc", new THREE.BufferAttribute(new Float32Array([0.8, 0.8, 0.8]), 1));
//共用一个shader材质
const material = new THREE.ShaderMaterial({
vertexShader: `
attribute float testabc;
varying float vTestabc;
void main() {
vTestabc = testabc;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying float vTestabc;
void main() {
gl_FragColor = vec4(vTestabc, 0.0, 0.0, 1.0);
}
`
});
scene.add(new THREE.Mesh(geometry1, material));
scene.add(new THREE.Mesh(geometry2, material));
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>

698

被折叠的 条评论
为什么被折叠?



