@react-three/fiber 绘制自定义顶点
@react-three/fiber to draw custom vertices
我正在尝试使用@react-three/fiber 在 bufferGeometry 上绘制自定义网格。我看到无数教程教如何画点、球体、盒子、线。但是我不知道如何绘制自定义网格,而且很难阅读 three.js 文档,因为我使用的是具有不同语法的 React。有人能帮我吗?我只想做一些类似两个或更多三角形的事情:
const vertices = [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 1.0,
...
];
return (
<mesh>
<bufferGeometry ???>
<bufferAttribute ??? />
</bufferGeometry>
<meshLambertMaterial attach="material" color="hotpink" />
</mesh>
);
我手头的数据也可以做索引,如果那是更好的解决方案。
受到 Custom BufferGeometry in react-three-fiber
评论的启发
我找到了答案:
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>
);
}
结果如下:
我正在尝试使用@react-three/fiber 在 bufferGeometry 上绘制自定义网格。我看到无数教程教如何画点、球体、盒子、线。但是我不知道如何绘制自定义网格,而且很难阅读 three.js 文档,因为我使用的是具有不同语法的 React。有人能帮我吗?我只想做一些类似两个或更多三角形的事情:
const vertices = [
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 1.0,
...
];
return (
<mesh>
<bufferGeometry ???>
<bufferAttribute ??? />
</bufferGeometry>
<meshLambertMaterial attach="material" color="hotpink" />
</mesh>
);
我手头的数据也可以做索引,如果那是更好的解决方案。
受到 Custom BufferGeometry in react-three-fiber
评论的启发我找到了答案:
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>
);
}
结果如下: