灵感来自Custom BufferGeometry in react-three-fiber的cmets
我找到了答案:
const vertices = new Float32Array([
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0
]);
return (
<mesh>
<bufferGeometry>
<bufferAttribute
attachObject={["attributes", "position"]}
array={vertices}
itemSize={3}
count={6}
/>
</bufferGeometry>
<meshStandardMaterial attach="material" color="hotpink" flatShading={true} />
</mesh>
)
我注意到,three.js 仅在法线(来自著名的右手定则)指向屏幕外时才显示表面。因此,以下将不会显示:
const vertices = new Float32Array([
0.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 1.0, 0.0
]);
更高级的使用需要自定义着色器。制服和属性允许用户传入对象的颜色(制服)或顶点的颜色(属性)。但是,需要更多的包来做用 glsl 编写的自定义着色器。
下面是一个使用属性传递颜色,同时使用变量插入颜色的示例。
/**
* Documentation: https://threejs.org/docs/#api/en/renderers/webgl/WebGLProgram
*
* default vertex attributes provided by Geometry and BufferGeometry
* attribute vec3 position;
* attribute vec3 normal;
* attribute vec2 uv;
*/
import React from 'react';
import { extend } from "@react-three/fiber";
import { shaderMaterial } from '@react-three/drei';
import * as THREE from 'three';
import glsl from 'babel-plugin-glsl/macro';
export default function Square() {
const vertices = new Float32Array([
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
1.0, 1.0, 0.0,
0.0, 1.0, 0.0
]);
const colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
]);
// shaderMaterial's name must be <Something>ShaderMaterial
// use extend below to add it to shader component
// The component's first letter need to be uppercase when defined but lowercase when called.
const SquareShaderMaterial = shaderMaterial(
// Uniform -> Allow to pass data in object level from react component to glsl
{
uColor: new THREE.Color(0.0, 0.0, 1.0)
},
// Vertex Shader -> Corner points of polygons
glsl`
attribute vec3 color;
varying lowp vec3 vColor;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vColor = color;
}
`,
// Fragment Shader -> Color the polygon surface
glsl`
uniform vec3 uColor;
varying lowp vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0); // modify to uColor if using uniform
}
`
);
extend({ SquareShaderMaterial });
return (
<mesh>
<bufferGeometry>
<bufferAttribute
attachObject={["attributes", "position"]}
array={vertices}
itemSize={3}
count={6}
/>
<bufferAttribute
attachObject={["attributes", "color"]}
array={colors}
itemSize={3}
count={6}
/>
</bufferGeometry>
<squareShaderMaterial uColor="hotpink"/>
</mesh>
);
}
结果如下: