受到react-three-fiber中自定义BufferGeometry评论的启发,我找到了答案:
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
]);
更高级的用法需要自定义着色器。Uniforms 和 attributes 允许用户传递对象的颜色(uniform)或顶点的颜色(attribute)。但是,需要更多的包才能编写 glsl 的自定义着色器。以下是使用 attributes 传递颜色并使用 varying 插值颜色的示例。
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,
]);
const SquareShaderMaterial = shaderMaterial(
{
uColor: new THREE.Color(0.0, 0.0, 1.0)
},
glsl`
attribute vec3 color;
varying lowp vec3 vColor;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vColor = color;
}
`,
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>
);
}
The result is the following:
![React three fiber custom shader 101](https://istack.dev59.com/EDAbU.webp)