<!doctype html>
<html>
<head>
<style>
canvas {
border: 1px solid #000000;
}
</style>
</head>
<body>
<canvas id="gl" width="300" height="300" style="width:300px; height:300px">
</canvas>
<script id="vertex_shader" type="myshader">
precision mediump int;
precision mediump float;
attribute vec3 a_PointVertex;
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Projection;
varying vec3 va_pos;
void main() {
va_pos = a_PointVertex;
mat4 MVP = u_Projection * u_View * u_Model;
gl_Position = MVP * vec4(a_PointVertex.xyz, 1.0);
}
</script>
<script id="fragment_shader" type="myshader">
precision mediump int;
precision mediump float;
varying vec3 va_pos;
void main() {
vec3 color = (va_pos + 1.0) * 0.5;
gl_FragColor = vec4(color, 1.0);
}
</script>
<script type="text/javascript" src="math.js"></script>
<script type="text/javascript" src="logic.js"></script>
</body>
</html>
function vec3_inverse(a) {
return [-a[0], -a[1], -a[2]];
}
function vec3_minus(a, b) {
return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
}
function vec3_add(a, b) {
return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
}
function vec3_dot(a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
function vec3_normalize(a) {
let l = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
return [a[0] / l, a[1] / l, a[2] / l];
}
function vec3_cross(a, b) {
return [
a[1] * b[2] - b[1] * a[2],
a[2] * b[0] - b[2] * a[0],
a[0] * b[1] - b[0] * a[1]
];
}
function mat4_get_identity() {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
}
function mat4_get_zero() {
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
function mat4_get_lookat(eye, target, up) {
let f = vec3_normalize(vec3_minus(target, eye));
let s = vec3_normalize(vec3_cross(f, up));
let u = vec3_cross(s, f);
let Result = mat4_get_identity();
Result[0] = s[0];
Result[4] = s[1];
Result[8] = s[2];
Result[1] = u[0];
Result[5] = u[1];
Result[9] = u[2];
Result[2] = -f[0];
Result[6] = -f[1];
Result[10] = -f[2];
Result[12] = -(vec3_dot(s, eye));
Result[13] = -(vec3_dot(u, eye));
Result[14] = vec3_dot(f, eye);
return Result;
}
function mat4_get_perspective(near, far, whr, fov) {
let fov_ra = 0.01745329251994329576923690768489 * fov;
let tanHalfFovy = Math.tan(fov_ra / 2);
let Result = mat4_get_zero();
Result[0] = 1 / (whr * tanHalfFovy);
Result[5] = 1 / (tanHalfFovy);
Result[10] = - (far + near) / (far - near);
Result[11] = -1;
Result[14] = - (2 * far * near) / (far - near);
return Result;
}
var pointCanvas = null;
var gl = null;
var u_Model_loc = null;
var u_View_loc = null;
var u_Projection_loc = null;
var program = null;
function Main() {
gl_init();
generateCube(gl);
gl_draw();
}
function generateCube(gl) {
let cube_model = [
1, -1, 1,1, -1, -1,1, 1, 1,1, -1, -1,1, 1, -1, 1, 1, 1,
-1, -1, -1,-1, -1, 1,-1, 1, -1,-1, -1, 1,-1, 1, 1, -1, 1, -1,
1, 1, -1,-1, 1, -1,1, 1, 1,-1, 1, -1,-1, 1, 1, 1, 1, 1,
-1, -1, -1,1, -1, -1,-1, -1, 1,1, -1, -1,1, -1, 1, -1, -1, 1,
-1, 1, 1,-1, -1, 1,1, 1, 1,-1, -1, 1,1, -1, 1, 1, 1, 1,
-1, -1, -1,-1, 1, -1,1, 1, -1,-1, 1, -1,1, 1, -1, 1, -1, -1,
];
for (let index = 0; index < cube_model.length; index++) {
cube_model[index] *= 1;
}
let dateArr = new Float32Array(cube_model);
let glbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glbuffer);
gl.bufferData(gl.ARRAY_BUFFER, dateArr, gl.STATIC_DRAW);
let a_PointVertex_loc = gl.getAttribLocation(program, 'a_PointVertex');
gl.vertexAttribPointer(a_PointVertex_loc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_PointVertex_loc);
}
function gl_init() {
pointCanvas = document.getElementById('gl');
gl = pointCanvas.getContext('webgl', { preserveDrawingBuffer: true });
var vertex_shader_code = document.getElementById('vertex_shader').textContent;
var vertex_shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertex_shader, vertex_shader_code);
gl.compileShader(vertex_shader);
const v_compiled = gl.getShaderParameter(vertex_shader, gl.COMPILE_STATUS);
if (!v_compiled) {
const v_theError = gl.getShaderInfoLog(vertex_shader);
console.error(v_theError);
gl.deleteShader(vertex_shader);
}
var fragment_shader_code = document.getElementById('fragment_shader').textContent;
var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragment_shader, fragment_shader_code);
gl.compileShader(fragment_shader);
const f_compiled = gl.getShaderParameter(fragment_shader, gl.COMPILE_STATUS);
if (!f_compiled) {
const f_theError = gl.getShaderInfoLog(fragment_shader);
console.error(f_theError);
gl.deleteShader(fragment_shader);
}
program = gl.createProgram();
gl.attachShader(program, vertex_shader);
gl.attachShader(program, fragment_shader);
gl.linkProgram(program);
gl.useProgram(program);
uniforms_init(gl);
}
function uniforms_init(gl) {
u_Model_loc = gl.getUniformLocation(program, "u_Model");
u_View_loc = gl.getUniformLocation(program, "u_View");
u_Projection_loc = gl.getUniformLocation(program, "u_Projection");
}
var model_mat = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
var view_mat = [];
var projection_mat = [];
function uniforms_update(gl) {
gl.uniformMatrix4fv(u_Model_loc, false, new Float32Array(model_mat));
view_mat = mat4_get_lookat([-10, 10, 10], [0, 0, 0], [0, 1, 0]);
gl.uniformMatrix4fv(u_View_loc, false, new Float32Array(view_mat));
projection_mat = mat4_get_perspective(0.1, 100, 1, 45);
gl.uniformMatrix4fv(u_Projection_loc, false, new Float32Array(projection_mat));
}
function gl_draw() {
gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
uniforms_update(gl);
gl.drawArrays(gl.LINES, 0, 12 * 3);
}
Main();