I draw a 2D rectangle on the 3D world by using pure WebGL 2.0 API.
Play on CodeSandbox: https://codesandbox.io/s/webgl-fundamental-rectangle-o5kem
More fascinating models will come soon…
index.html
<!DOCTYPE html>
<html>
<head>
<title>WebGL Fundamental</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app">
<canvas id="canvas"></canvas>
<div id="uiContainer">
<div id="ui">
<div id="x"></div>
<div id="y"></div>
<div id="angle"></div>
<div id="scaleX"></div>
<div id="scaleY"></div>
</div>
</div>
</div>
<script src="https://webgl2fundamentals.org/webgl/resources/m3.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/webgl-lessons-ui.js"></script>
<script src="src/index.js"></script>
</body>
</html>
src/index.js
import "./styles.css";
var vs = `#version 300 es
in vec2 a_position;
in vec4 a_color;
uniform mat3 u_matrix;
out vec4 v_color;
void main() {
// Multiply the position by the matrix.
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
// Copy the color from the attribute to the varying.
v_color = a_color;
}
`;
var fs = `#version 300 es
precision highp float;
in vec4 v_color;
out vec4 outColor;
void main() {
outColor = v_color;
}
`;
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("#canvas");
var gl = canvas.getContext("webgl2");
if (!gl) {
return;
}
// setup GLSL program
var program = webglUtils.createProgramFromSources(gl, [vs, fs]);
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
var colorLocation = gl.getAttribLocation(program, "a_color");
// lookup uniforms
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
// Create set of attributes
var vao = gl.createVertexArray();
gl.bindVertexArray(vao);
// Create a buffer for the positons.
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// Set Geometry.
setGeometry(gl);
// tell the position attribute how to pull data out of the current ARRAY_BUFFER
gl.enableVertexAttribArray(positionLocation);
var size = 2;
var type = gl.FLOAT;
var normalize = false;
var stride = 0;
var offset = 0;
gl.vertexAttribPointer(
positionLocation,
size,
type,
normalize,
stride,
offset
);
// Create a buffer for the colors.
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// Set the colors.
setColors(gl);
// tell the color attribute how to pull data out of the current ARRAY_BUFFER
gl.enableVertexAttribArray(colorLocation);
var size = 4;
var type = gl.UNSIGNED_BYTE;
var normalize = true;
var stride = 0;
var offset = 0;
gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
var translation = [200, 150];
var angleInRadians = 0;
var scale = [1, 1];
drawScene();
// Setup a ui.
webglLessonsUI.setupSlider("#x", {
value: translation[0],
slide: updatePosition(0),
max: gl.canvas.width
});
webglLessonsUI.setupSlider("#y", {
value: translation[1],
slide: updatePosition(1),
max: gl.canvas.height
});
webglLessonsUI.setupSlider("#angle", { slide: updateAngle, max: 360 });
webglLessonsUI.setupSlider("#scaleX", {
value: scale[0],
slide: updateScale(0),
min: -5,
max: 5,
step: 0.01,
precision: 2
});
webglLessonsUI.setupSlider("#scaleY", {
value: scale[1],
slide: updateScale(1),
min: -5,
max: 5,
step: 0.01,
precision: 2
});
function updatePosition(index) {
return function (event, ui) {
translation[index] = ui.value;
drawScene();
};
}
function updateAngle(event, ui) {
var angleInDegrees = 360 - ui.value;
angleInRadians = (angleInDegrees * Math.PI) / 180;
drawScene();
}
function updateScale(index) {
return function (event, ui) {
scale[index] = ui.value;
drawScene();
};
}
// Draw the scene.
function drawScene() {
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Clear the canvas
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Tell it to use our program (pair of shaders)
gl.useProgram(program);
// Bind the attribute/buffer set we want.
gl.bindVertexArray(vao);
// Compute the matrices
var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
matrix = m3.translate(matrix, translation[0], translation[1]);
matrix = m3.rotate(matrix, angleInRadians);
matrix = m3.scale(matrix, scale[0], scale[1]);
// Set the matrix.
gl.uniformMatrix3fv(matrixLocation, false, matrix);
// Draw the geometry.
var offset = 0;
var count = 6;
gl.drawArrays(gl.TRIANGLES, offset, count);
}
}
// Fill the current buffer with the values that define a rectangle.
function setGeometry(gl) {
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-150,
-100,
150,
-100,
-150,
100,
150,
-100,
-150,
100,
150,
100
]),
gl.STATIC_DRAW
);
}
// Fill the current buffer with colors for the 2 triangles
// that make the rectangle.
function setColors(gl) {
// Pick 2 random colors.
var r1 = Math.random() * 256; // 0 to 255.99999
var b1 = Math.random() * 256; // these values
var g1 = Math.random() * 256; // will be truncated
var r2 = Math.random() * 256; // when stored in the
var b2 = Math.random() * 256; // Uint8Array
var g2 = Math.random() * 256;
gl.bufferData(
gl.ARRAY_BUFFER,
new Uint8Array([
// Uint8Array
r1,
b1,
g1,
255,
r1,
b1,
g1,
255,
r1,
b1,
g1,
255,
r2,
b2,
g2,
255,
r2,
b2,
g2,
255,
r2,
b2,
g2,
255
]),
gl.STATIC_DRAW
);
}
main();
src/styles.css
@import url("https://webgl2fundamentals.org/webgl/resources/webgl-tutorials.css");
body {
margin: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}
Sorry, the comment form is closed at this time.