luma.gl/docs/tutorials/hello-triangle.mdx
2023-05-29 07:13:17 -04:00

181 lines
4.0 KiB
Plaintext

import {DeviceTabs} from '@site/src/react-luma';
import {HelloTriangleExample} from '@site';
# Hello Triangle
This tutorial will demonstrate how to draw a triangle using luma.gl's high-level APIs.
<DeviceTabs />
<HelloTriangleExample />
It is assumed you've set up your development environment as described in
[Getting Started](/docs/getting-started). Your `index.js` file should look like the following:
```typescript
import {AnimationLoop} from '@luma.gl/engine';
import {clear} from '@luma.gl/webgl';
class AppAnimationLoop extends AnimationLoop ({
override onInitialize({device}) {
// Setup logic goes here
},
override onRender({device}) {
// Drawing logic goes here
clear(device, {color: [0, 0, 0, 1]});
}
});
const loop = new AppAnimationLoop();
loop.start();
```
First, we'll need to update our imports with the classes we'll be using, `Buffer` and `Model`:
```typescript
import {AnimationLoop, Model} from '@luma.gl/engine';
import {clear} from '@luma.gl/webgl';
```
Now let's create some buffers in the `onInitialize` method to hold our attribute data:
```typescript
override onInitialize({device}) {
// Setup logic goes here
const positionBuffer = device.createBuffer(new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]));
const colorBuffer = device.createBuffer(new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
]));
}
```
Next let's add the vertex and fragment shader code we'll be using to draw:
```typescript
override onInitialize({device}) {
// Setup logic goes here
// Buffers...
const vs = `
attribute vec2 position;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fs = `
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
`;
}
```
As a final step in our initialization, we'll create a `Model` in `onInitialize`:
```typescript
override onInitialize({device}) {
// Setup logic goes here
// Buffers...
// Shaders...
this.model = new Model(device, {
vs,
fs,
attributes: {
position: positionBuffer,
color: colorBuffer
},
vertexCount: 3
});
return {model};
}
```
A `Model` can be thought of as gathering all the WebGL pieces necessary for a single draw call: programs, attributes, uniforms. Also note that we return the `Model` instance we created. This will make it available to the `onRender` method.
Our `onRender` method is comparitavely much simpler:
```typescript
override onRender({device}) {
clear(device, {color: [0, 0, 0, 1]});
this.model.draw();
}
```
This clears the canvas and draws the `Model`. If all went well, you should see a tri-color triangle on a black background.
The entire application should look like the following:
```typescript
import {AnimationLoop, Model} from '@luma.gl/engine';
import {clear} from '@luma.gl/webgl';
class AppAnimationLoop extends AnimationLoop {
override onInitialize({device}) {
const positionBuffer = device.createBuffer(new Float32Array([-0.5, -0.5, 0.5, -0.5, 0.0, 0.5]));
const colorBuffer = device.createBuffer(new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]));
const vs = `
attribute vec2 position;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fs = `
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
`;
const model = new Model(device, {
vs,
fs,
attributes: {
position: positionBuffer,
color: colorBuffer
},
vertexCount: 3
});
return {model};
},
override onRender({device, model}) {
clear(device, {color: [0, 0, 0, 1]});
model.draw();
}
};
const loop = new AppAnimationLoop();
loop.start();
```