Use VAOs to simplify rendering logic

This commit is contained in:
keanutaufan 2024-09-18 23:12:44 +07:00
parent ecfe53f705
commit 0e281bcbbc
No known key found for this signature in database
GPG Key ID: 0E2EF5BE1DA75288
8 changed files with 71 additions and 45 deletions

View File

@ -3,6 +3,9 @@ import Vector2D from "./Vector2D";
export default class Shape2D {
constructor(
public position: Vector2D,
public vertices: Float32Array,
public scale: number,
public color: [number, number, number],
public verticesCount: number,
public vao: WebGLVertexArrayObject,
) {}
}

View File

@ -1,10 +0,0 @@
import Shape2D from "./Shape2D";
import Vector2D from "./Vector2D";
export default class Triangle extends Shape2D {
constructor(
public position: Vector2D,
) {
super(position, new Float32Array([0.0, -0.5, 0.3, 0.5, -0.3, 0.5]));
}
}

View File

@ -3,12 +3,13 @@ import "./style.css";
import vsSource from "./shaders/basic.vert?raw";
import fsSource from "./shaders/basic.frag?raw";
import { drawVertex, loadBuffer, loadProgram, loadShader } from "./shaderUtils";
import { loadBuffer, loadProgram, loadShader } from "./shaderUtils";
import Triangle from "./geometry/Triangle";
import Vector2D from "./geometry/Vector2D";
import { createBasicVao } from "./vaoUtils";
import Shape2D from "./geometry/Shape2D";
const triangle = new Triangle(new Vector2D(0, 0));
import triangle from "./verts/triangle.json";
function render() {
const canvas = document.querySelector<HTMLCanvasElement>("#canvas");
@ -23,7 +24,6 @@ function render() {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const program = loadProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
@ -32,17 +32,44 @@ function render() {
throw new Error("Failed to get attrib location for vertexPosition");
}
const verts = new Float32Array(triangle.vertices);
const buffer = loadBuffer(gl, verts);
const triangleVerts = new Float32Array(triangle.vertices);
const triangleBuffer = loadBuffer(gl, triangleVerts);
const triangleVao = createBasicVao(gl, triangleBuffer, vertexPositionAttribLocation);
const fragmentColor = gl.getUniformLocation(program, "uColor");
if (!fragmentColor) {
throw new Error("Uniform uColor not found");
const shapes: Shape2D[] = [
new Shape2D(new Vector2D(300, 300), 200, [0.22745, 0.35294, 0.25098], 3, triangleVao),
new Shape2D(new Vector2D(800, 300), 100, [0.22745, 0.35294, 0.25098], 3, triangleVao),
]
const fragmentColorUniform = gl.getUniformLocation(program, "uColor");
const canvasSizeUniform = gl.getUniformLocation(program, "uCanvasSize");
const shapeLocationUniform = gl.getUniformLocation(program, "uLocation");
const shapeScaleUniform = gl.getUniformLocation(program, "uScale");
if (!(fragmentColorUniform && canvasSizeUniform && shapeLocationUniform && shapeScaleUniform)) {
throw new Error(`Some uniform not found:
${fragmentColorUniform ? "" : "uColor"};
${canvasSizeUniform ? "" : "uCanvasSize"};
${shapeLocationUniform ? "" : "uLocation"};
${shapeScaleUniform ? "" : "uScale"};
`);
}
gl.uniform4f(fragmentColor, 0.22745, 0.35294, 0.25098, 1.0);
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.uniform2f(canvasSizeUniform, canvas.width, canvas.height);
shapes.forEach((shape) => {
gl.uniform3f(fragmentColorUniform, shape.color[0], shape.color[1], shape.color[2]);
gl.uniform2f(shapeLocationUniform, shape.position.x, shape.position.y);
gl.uniform1f(shapeScaleUniform, shape.scale);
gl.bindVertexArray(shape.vao);
gl.drawArrays(gl.TRIANGLES, 0, shape.verticesCount);
})
drawVertex(gl, vertexPositionAttribLocation, buffer, gl.TRIANGLES, verts.length);
}
try {

View File

@ -35,26 +35,6 @@ export function loadProgram(gl: WebGL2RenderingContext, vertexShader: WebGLShade
}
export function drawVertex(gl: WebGL2RenderingContext, vertexAttribArrayLocation: GLuint, buffer: WebGLBuffer, mode: GLenum, length: number) {
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enableVertexAttribArray(vertexAttribArrayLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(
vertexAttribArrayLocation,
2,
gl.FLOAT,
false,
2 * Float32Array.BYTES_PER_ELEMENT,
0,
);
gl.drawArrays(mode, 0, length / 2);
}
export function loadBuffer(gl: WebGL2RenderingContext, vertices: Float32Array) {
const buffer = gl.createBuffer();
if (!buffer) {

View File

@ -1,9 +1,10 @@
#version 300 es
precision mediump float;
uniform vec4 uColor;
uniform vec3 uColor;
out vec4 fragColor;
void main() {
fragColor = uColor;
fragColor = vec4(uColor, 1.0);
}

View File

@ -1,8 +1,15 @@
#version 300 es
precision mediump float;
uniform vec2 uCanvasSize;
uniform vec2 uLocation;
uniform float uScale;
in vec2 vertexPosition;
void main() {
gl_Position = vec4(vertexPosition, 0.0, 1.0);
vec2 finalVertexPosition = vertexPosition * uScale + uLocation;
vec2 clipPosition = (finalVertexPosition / uCanvasSize) * 2.0 - 1.0;
gl_Position = vec4(clipPosition, 0.0, 1.0);
}

15
src/vaoUtils.ts Normal file
View File

@ -0,0 +1,15 @@
export function createBasicVao(gl: WebGL2RenderingContext, buffer: WebGLBuffer, attrib: number) {
const vao = gl.createVertexArray();
if (!vao) {
throw new Error("Failed to create VAO");
}
gl.bindVertexArray(vao);
gl.enableVertexAttribArray(attrib);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(attrib, 2, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);
return vao;
}

3
src/verts/triangle.json Normal file
View File

@ -0,0 +1,3 @@
{
"vertices": [0.0, -1, 0.6, 1, -0.6, 1]
}