OpENgL
Former-commit-id: 64c9625b85553dcdb32306c9e03d69dc3d913ef3
This commit is contained in:
28
client/public/brick-renderer/basic.fs
Normal file
28
client/public/brick-renderer/basic.fs
Normal file
@@ -0,0 +1,28 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
|
||||
uniform SceneUniforms {
|
||||
mat4 viewProj;
|
||||
vec4 eyePosition;
|
||||
vec4 lightPosition;
|
||||
} uScene;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec3 vPosition;
|
||||
in vec3 vNormal;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec3 color = vNormal;
|
||||
|
||||
vec3 normal = normalize(vNormal);
|
||||
vec3 eyeVec = normalize(uScene.eyePosition.xyz - vPosition);
|
||||
vec3 incidentVec = normalize(vPosition - uScene.lightPosition.xyz);
|
||||
vec3 lightVec = -incidentVec;
|
||||
float diffuse = max(dot(lightVec, normal), 0.0);
|
||||
float highlight = pow(max(dot(eyeVec, reflect(incidentVec, normal)), 0.0), 100.0);
|
||||
float ambient = 0.1;
|
||||
fragColor = vec4(color * (diffuse + highlight + ambient), 1.0);
|
||||
}
|
||||
24
client/public/brick-renderer/basic.vs
Normal file
24
client/public/brick-renderer/basic.vs
Normal file
@@ -0,0 +1,24 @@
|
||||
#version 300 es
|
||||
|
||||
layout(std140, column_major) uniform;
|
||||
|
||||
layout(location=0) in vec4 position;
|
||||
layout(location=1) in vec4 normal;
|
||||
|
||||
uniform SceneUniforms {
|
||||
mat4 viewProj;
|
||||
vec4 eyePosition;
|
||||
vec4 lightPosition;
|
||||
} uScene;
|
||||
|
||||
uniform mat4 uModel;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main() {
|
||||
vec4 worldPosition = uModel * position;
|
||||
vPosition = worldPosition.xyz;
|
||||
vNormal = (uModel * normal).xyz;
|
||||
gl_Position = uScene.viewProj * worldPosition;
|
||||
}
|
||||
134
client/public/brick-renderer/box.mjs
Normal file
134
client/public/brick-renderer/box.mjs
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
export default class Box {
|
||||
constructor(gl, options) {
|
||||
this.gl = gl;
|
||||
this.options = options;
|
||||
|
||||
this.vao = gl.createVertexArray();
|
||||
gl.bindVertexArray(this.vao);
|
||||
}
|
||||
|
||||
get vertexCount() {
|
||||
return this.verticies;
|
||||
}
|
||||
|
||||
bind() {
|
||||
this.gl.bindVertexArray(this.vao);
|
||||
}
|
||||
|
||||
create(options) {
|
||||
const { positions, normals } = this.boxVerticies(options);
|
||||
this.verticies = positions.length / 3;
|
||||
|
||||
this.gl.bindVertexArray(this.vao);
|
||||
|
||||
const positionBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);
|
||||
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
||||
this.gl.vertexAttribPointer(0, 3, this.gl.FLOAT, false, 0, 0);
|
||||
this.gl.enableVertexAttribArray(0);
|
||||
|
||||
const normalBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, normalBuffer);
|
||||
this.gl.bufferData(this.gl.ARRAY_BUFFER, normals, this.gl.STATIC_DRAW);
|
||||
this.gl.vertexAttribPointer(2, 3, this.gl.FLOAT, false, 0, 0);
|
||||
this.gl.enableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
// TODO: Use indicies ffs
|
||||
boxVerticies(options) {
|
||||
options = options || {};
|
||||
|
||||
const dimensions = options.dimensions || [1, 1, 1];
|
||||
const position = options.position || [-dimensions[0] / 2, -dimensions[1] / 2, -dimensions[2] / 2];
|
||||
const x = position[0];
|
||||
const y = position[1];
|
||||
const z = position[2];
|
||||
const width = dimensions[0];
|
||||
const height = dimensions[1];
|
||||
const depth = dimensions[2];
|
||||
|
||||
const fbl = { x, y, z: z + depth };
|
||||
const fbr = { x: x + width, y, z: z + depth };
|
||||
const ftl = { x, y: y + height, z: z + depth };
|
||||
const ftr = { x: x + width, y: y + height, z: z + depth };
|
||||
const bbl = { x, y, z };
|
||||
const bbr = { x: x + width, y, z };
|
||||
const btl = { x, y: y + height, z };
|
||||
const btr = { x: x + width, y: y + height, z };
|
||||
|
||||
const positions = new Float32Array([
|
||||
// front
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
|
||||
// right
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
|
||||
// back
|
||||
fbr.x, bbr.y, bbr.z,
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
|
||||
// left
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
|
||||
// top
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
|
||||
// bottom
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
]);
|
||||
|
||||
const normals = new Float32Array(positions.length);
|
||||
let ni;
|
||||
|
||||
for (let i = 0, count = positions.length / 3; i < count; i++) {
|
||||
ni = i * 3;
|
||||
|
||||
normals[ni] = parseInt(i / 6, 10) === 1
|
||||
? 1
|
||||
: parseInt(i / 6, 10) === 3 ? -1 : 0;
|
||||
|
||||
normals[ni + 1] = parseInt(i / 6, 10) === 4
|
||||
? 1
|
||||
: parseInt(i / 6, 10) === 5 ? -1 : 0;
|
||||
|
||||
normals[ni + 2] = parseInt(i / 6, 10) === 0
|
||||
? 1
|
||||
: parseInt(i / 6, 10) === 2 ? -1 : 0;
|
||||
}
|
||||
|
||||
return {
|
||||
positions,
|
||||
normals,
|
||||
};
|
||||
}
|
||||
}
|
||||
4470
client/public/brick-renderer/glm.mjs
Normal file
4470
client/public/brick-renderer/glm.mjs
Normal file
File diff suppressed because it is too large
Load Diff
82
client/public/brick-renderer/index.mjs
Normal file
82
client/public/brick-renderer/index.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as glm from './glm.mjs';
|
||||
import Shader from './shader.mjs';
|
||||
import Box from './box.mjs';
|
||||
|
||||
let BasicVsource, BasicFSource;
|
||||
|
||||
export async function RendererPreInit() {
|
||||
BasicFSource = await fetch('./brick-renderer/basic.fs').then(r => r.text());
|
||||
BasicVsource = await fetch('./brick-renderer/basic.vs').then(r => r.text());
|
||||
}
|
||||
|
||||
class BaseRenderer {
|
||||
constructor(canvas) {
|
||||
this.canvas = canvas;
|
||||
this.gl = canvas.getContext('webgl2');
|
||||
this.gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
this.gl.clearColor(0.84313, 0.76078, 1.0, 1.0);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||
this.gl.enable(this.gl.DEPTH_TEST);
|
||||
|
||||
this.shader = new Shader(this.gl, BasicVsource, BasicFSource);
|
||||
this.shader.link();
|
||||
}
|
||||
}
|
||||
|
||||
export class BrickRenderer extends BaseRenderer {
|
||||
constructor(canvas, options) {
|
||||
super(canvas);
|
||||
|
||||
const sceneUniformLocation = this.shader.getUniformBlock('SceneUniforms');
|
||||
const modelMatrixLocation = this.shader.getUniform('uModel');
|
||||
this.shader.attatch();
|
||||
|
||||
const boxObj = new Box(this.gl, { dimensions: [0.5, 0.6, 0.5] });
|
||||
|
||||
const projMatrix = glm.mat4.create();
|
||||
glm.mat4.perspective(projMatrix, Math.PI / 2, this.gl.drawingBufferWidth / this.gl.drawingBufferHeight, 0.1, 10.0);
|
||||
|
||||
const viewMatrix = glm.mat4.create();
|
||||
const eyePosition = glm.vec3.fromValues(1, 1, 1);
|
||||
glm.mat4.lookAt(viewMatrix, eyePosition, glm.vec3.fromValues(0, 0, 0), glm.vec3.fromValues(0, 1, 0));
|
||||
|
||||
const viewProjMatrix = glm.mat4.create();
|
||||
glm.mat4.multiply(viewProjMatrix, projMatrix, viewMatrix);
|
||||
|
||||
const lightPosition = glm.vec3.fromValues(1, 1, 0.5);
|
||||
|
||||
const modelMatrix = glm.mat4.create();
|
||||
const rotateXMatrix = glm.mat4.create();
|
||||
const rotateYMatrix = glm.mat4.create();
|
||||
const sceneUniformData = new Float32Array(24);
|
||||
sceneUniformData.set(viewProjMatrix);
|
||||
sceneUniformData.set(eyePosition, 16);
|
||||
sceneUniformData.set(lightPosition, 20);
|
||||
|
||||
const sceneUniformBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBufferBase(this.gl.UNIFORM_BUFFER, 0, sceneUniformBuffer);
|
||||
this.gl.bufferData(this.gl.UNIFORM_BUFFER, sceneUniformData, this.gl.STATIC_DRAW);
|
||||
|
||||
let angleX = 0;
|
||||
let angleY = 0;
|
||||
|
||||
|
||||
function draw() {
|
||||
angleX += 0.01;
|
||||
angleY += 0.015;
|
||||
|
||||
glm.mat4.fromXRotation(rotateXMatrix, angleX);
|
||||
glm.mat4.fromYRotation(rotateYMatrix, angleY);
|
||||
glm.mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
|
||||
|
||||
this.gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
|
||||
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||
this.gl.drawArrays(this.gl.TRIANGLES, 0, boxObj.vertexCount);
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
}
|
||||
127
client/public/brick-renderer/shader.mjs
Normal file
127
client/public/brick-renderer/shader.mjs
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
export default class Shader {
|
||||
constructor(gl, vSource, fSource) {
|
||||
this.gl = gl;
|
||||
this.vSource = vSource;
|
||||
this.fSource = fSource;
|
||||
this.uniformBlockNum = 0;
|
||||
this.shaderProgram = 123;
|
||||
|
||||
this.vShader = this.gl.createShader(this.gl.VERTEX_SHADER);
|
||||
this.gl.shaderSource(this.vShader, this.vSource);
|
||||
this.gl.compileShader(this.vShader);
|
||||
|
||||
if (!this.gl.getShaderParameter(this.vShader, this.gl.COMPILE_STATUS)) {
|
||||
console.error(this.gl.getShaderInfoLog(this.vShader));
|
||||
}
|
||||
|
||||
this.fShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
|
||||
this.gl.shaderSource(this.fShader, this.fSource);
|
||||
this.gl.compileShader(this.fShader);
|
||||
|
||||
if (!this.gl.getShaderParameter(this.fShader, this.gl.COMPILE_STATUS)) {
|
||||
console.error(this.gl.getShaderInfoLog(this.fShader));
|
||||
}
|
||||
}
|
||||
|
||||
get vertexShader() {
|
||||
return this.vShader;
|
||||
}
|
||||
|
||||
get fragmentShader() {
|
||||
return this.fShader;
|
||||
}
|
||||
|
||||
get program() {
|
||||
return this.shaderProgram;
|
||||
}
|
||||
|
||||
getUniformBlock(name) {
|
||||
const location = this.gl.getUniformBlockIndex(this.shaderProgram, name);
|
||||
this.gl.uniformBlockBinding(this.shaderProgram, location, this.uniformBlockNum);
|
||||
this.uniformBlockNum++;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
getUniform(name) {
|
||||
return this.gl.getUniformLocation(this.shaderProgram, name);
|
||||
}
|
||||
|
||||
attribLocation(location, name) {
|
||||
this.gl.bindAttribLocation(this.shaderProgram, location, name);
|
||||
}
|
||||
|
||||
setUniform(uniform, value) {
|
||||
switch (uniform.type) {
|
||||
case this.gl.FLOAT:
|
||||
this.gl.uniform1f(uniform, value);
|
||||
break;
|
||||
case this.gl.FLOAT_VEC2:
|
||||
this.gl.uniform2f(uniform, value[0], value[1]);
|
||||
break;
|
||||
case this.gl.FLOAT_VEC3:
|
||||
this.gl.uniform3f(uniform, value[0], value[1], value[2]);
|
||||
break;
|
||||
case this.gl.FLOAT_VEC4:
|
||||
this.gl.uniform4f(uniform, value[0], value[1], value[2], value[3]);
|
||||
break;
|
||||
case this.gl.INT:
|
||||
this.gl.uniform1i(uniform, value);
|
||||
break;
|
||||
case this.gl.INT_VEC2:
|
||||
this.gl.uniform2i(uniform, value[0], value[1]);
|
||||
break;
|
||||
case this.gl.INT_VEC3:
|
||||
this.gl.uniform3i(uniform, value[0], value[1], value[2]);
|
||||
break;
|
||||
case this.gl.INT_VEC4:
|
||||
this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]);
|
||||
break;
|
||||
case this.gl.BOOL:
|
||||
this.gl.uniform1i(uniform, value);
|
||||
break;
|
||||
case this.gl.BOOL_VEC2:
|
||||
this.gl.uniform2i(uniform, value[0], value[1]);
|
||||
break;
|
||||
case this.gl.BOOL_VEC3:
|
||||
this.gl.uniform3i(uniform, value[0], value[1], value[2]);
|
||||
break;
|
||||
case this.gl.BOOL_VEC4:
|
||||
this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]);
|
||||
break;
|
||||
case this.gl.FLOAT_MAT2:
|
||||
this.gl.uniformMatrix2fv(uniform, false, value);
|
||||
break;
|
||||
case this.gl.FLOAT_MAT3:
|
||||
this.gl.uniformMatrix3fv(uniform, false, value);
|
||||
break;
|
||||
case this.gl.FLOAT_MAT4:
|
||||
this.gl.uniformMatrix4fv(uniform, false, value);
|
||||
break;
|
||||
case this.gl.SAMPLER_2D:
|
||||
this.gl.uniform1i(uniform, value);
|
||||
break;
|
||||
case this.gl.SAMPLER_CUBE:
|
||||
this.gl.uniform1i(uniform, value);
|
||||
break;
|
||||
default:
|
||||
console.error(`Unsupported uniform type ${uniform.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
link() {
|
||||
this.shaderProgram = this.gl.createProgram();
|
||||
this.gl.attachShader(this.shaderProgram, this.vShader);
|
||||
this.gl.attachShader(this.shaderProgram, this.fShader);
|
||||
this.gl.linkProgram(this.shaderProgram);
|
||||
|
||||
if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) {
|
||||
console.error(this.gl.getProgramParameter(this.shaderProgram));
|
||||
}
|
||||
}
|
||||
|
||||
attatch() {
|
||||
this.gl.useProgram(this.shaderProgram);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,11 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans&display=swap" rel="stylesheet">
|
||||
<script src="components/components.js"></script>
|
||||
|
||||
<script src="gl-matrix.js"></script>
|
||||
<script src="utils.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/glm-js@0.0.6-c/build/glm-js.min.js"></script>
|
||||
<script src="index.js"></script>
|
||||
<script type="module" src="brick-renderer/glm.mjs"></script>
|
||||
<script type="module" src="brick-renderer/shader.mjs"></script>
|
||||
<script type="module" src="brick-renderer/index.mjs"></script>
|
||||
|
||||
<script type="module" src="index.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<loading-component></loading-component>
|
||||
@@ -33,66 +34,6 @@
|
||||
</content-margin>
|
||||
|
||||
<canvas id="webglviewer" width="640" height="480"></canvas>
|
||||
<script type="x-shader/vs" id="vertex-draw">
|
||||
#version 300 es
|
||||
|
||||
layout(std140, column_major) uniform;
|
||||
|
||||
layout(location=0) in vec4 position;
|
||||
layout(location=1) in vec2 uv;
|
||||
layout(location=2) in vec4 normal;
|
||||
|
||||
uniform SceneUniforms {
|
||||
mat4 viewProj;
|
||||
vec4 eyePosition;
|
||||
vec4 lightPosition;
|
||||
} uScene;
|
||||
|
||||
uniform mat4 uModel;
|
||||
|
||||
out vec3 vPosition;
|
||||
out vec2 vUV;
|
||||
out vec3 vNormal;
|
||||
void main() {
|
||||
vec4 worldPosition = uModel * position;
|
||||
vPosition = worldPosition.xyz;
|
||||
vUV = uv;
|
||||
vNormal = (uModel * normal).xyz;
|
||||
gl_Position = uScene.viewProj * worldPosition;
|
||||
}
|
||||
</script>
|
||||
<script type="x-shader/vf" id="fragment-draw">
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
|
||||
layout(std140, column_major) uniform;
|
||||
|
||||
uniform SceneUniforms {
|
||||
mat4 viewProj;
|
||||
vec4 eyePosition;
|
||||
vec4 lightPosition;
|
||||
} uScene;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec3 vPosition;
|
||||
in vec2 vUV;
|
||||
in vec3 vNormal;
|
||||
|
||||
out vec4 fragColor;
|
||||
void main() {
|
||||
vec3 color = vec3(vUV, 1.0);
|
||||
|
||||
vec3 normal = normalize(vNormal);
|
||||
vec3 eyeVec = normalize(uScene.eyePosition.xyz - vPosition);
|
||||
vec3 incidentVec = normalize(vPosition - uScene.lightPosition.xyz);
|
||||
vec3 lightVec = -incidentVec;
|
||||
float diffuse = max(dot(lightVec, normal), 0.0);
|
||||
float highlight = pow(max(dot(eyeVec, reflect(incidentVec, normal)), 0.0), 100.0);
|
||||
float ambient = 0.1;
|
||||
fragColor = vec4(color * (diffuse + highlight + ambient), 1.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
</limited-margin>
|
||||
</body>
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
function main() {
|
||||
const canvas = document.querySelector('#webglviewer');
|
||||
const gl = canvas.getContext('webgl2');
|
||||
|
||||
// Only continue if WebGL is available and working
|
||||
if (gl === null) {
|
||||
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Set clear color to black, fully opaque
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
// Clear the color buffer with specified clear color
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
|
||||
const vsSource = document.getElementById('vertex-draw').text.trim();
|
||||
const fsSource = document.getElementById('fragment-draw').text.trim();
|
||||
|
||||
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
||||
gl.shaderSource(vertexShader, vsSource);
|
||||
gl.compileShader(vertexShader);
|
||||
|
||||
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
|
||||
console.error(gl.getShaderInfoLog(vertexShader));
|
||||
}
|
||||
|
||||
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fragmentShader, fsSource);
|
||||
gl.compileShader(fragmentShader);
|
||||
|
||||
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
|
||||
console.error(gl.getShaderInfoLog(fragmentShader));
|
||||
}
|
||||
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
console.error(gl.getProgramInfoLog(program));
|
||||
}
|
||||
|
||||
const sceneUniformsLocation = gl.getUniformBlockIndex(program, 'SceneUniforms');
|
||||
gl.uniformBlockBinding(program, sceneUniformsLocation, 0);
|
||||
|
||||
const modelMatrixLocation = gl.getUniformLocation(program, 'uModel');
|
||||
|
||||
gl.useProgram(program);
|
||||
|
||||
const box = utils.createBox({dimensions: [.5, .6, .5]});
|
||||
const numVertices = box.positions.length / 3;
|
||||
|
||||
const cubeArray = gl.createVertexArray();
|
||||
gl.bindVertexArray(cubeArray);
|
||||
|
||||
const positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, box.positions, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(0);
|
||||
|
||||
const uvBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, box.uvs, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(1);
|
||||
|
||||
const normalBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, box.normals, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(2);
|
||||
|
||||
|
||||
const projMatrix = mat4.create();
|
||||
mat4.perspective(projMatrix, Math.PI / 2, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 10.0);
|
||||
|
||||
const viewMatrix = mat4.create();
|
||||
const eyePosition = vec3.fromValues(1, 1, 1);
|
||||
mat4.lookAt(viewMatrix, eyePosition, vec3.fromValues(0, 0, 0), vec3.fromValues(0, 1, 0));
|
||||
|
||||
const viewProjMatrix = mat4.create();
|
||||
mat4.multiply(viewProjMatrix, projMatrix, viewMatrix);
|
||||
|
||||
const lightPosition = vec3.fromValues(1, 1, 0.5);
|
||||
|
||||
const modelMatrix = mat4.create();
|
||||
const rotateXMatrix = mat4.create();
|
||||
const rotateYMatrix = mat4.create();
|
||||
|
||||
const sceneUniformData = new Float32Array(24);
|
||||
sceneUniformData.set(viewProjMatrix);
|
||||
sceneUniformData.set(eyePosition, 16);
|
||||
sceneUniformData.set(lightPosition, 20);
|
||||
|
||||
const sceneUniformBuffer = gl.createBuffer();
|
||||
gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, sceneUniformBuffer);
|
||||
gl.bufferData(gl.UNIFORM_BUFFER, sceneUniformData, gl.STATIC_DRAW);
|
||||
|
||||
let angleX = 0;
|
||||
let angleY = 0;
|
||||
|
||||
|
||||
function draw() {
|
||||
angleX += 0.01;
|
||||
angleY += 0.015;
|
||||
|
||||
mat4.fromXRotation(rotateXMatrix, angleX);
|
||||
mat4.fromYRotation(rotateYMatrix, angleY);
|
||||
mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
|
||||
|
||||
gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, numVertices);
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
10
client/public/index.mjs
Normal file
10
client/public/index.mjs
Normal file
@@ -0,0 +1,10 @@
|
||||
import { RendererPreInit, BrickRenderer } from './brick-renderer/index.mjs';
|
||||
|
||||
async function main() {
|
||||
await RendererPreInit();
|
||||
|
||||
const canvas = document.querySelector('#webglviewer');
|
||||
const Renderer = new BrickRenderer(canvas);
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
@@ -1,374 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 Tarek Sherif
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
(function() {
|
||||
var translateMat = mat4.create();
|
||||
var rotateXMat = mat4.create();
|
||||
var rotateYMat = mat4.create();
|
||||
var rotateZMat = mat4.create();
|
||||
var scaleMat = mat4.create();
|
||||
|
||||
var zeros = [0, 0, 0];
|
||||
var ones = [1, 1, 1];
|
||||
|
||||
window.utils = {
|
||||
xformMatrix: function xformMatrix(xform, translate, rotate, scale) {
|
||||
translate = translate || zeros;
|
||||
rotate = rotate || zeros;
|
||||
scale = scale || ones;
|
||||
|
||||
mat4.fromTranslation(translateMat, translate);
|
||||
mat4.fromXRotation(rotateXMat, rotate[0]);
|
||||
mat4.fromYRotation(rotateYMat, rotate[1]);
|
||||
mat4.fromZRotation(rotateZMat, rotate[2]);
|
||||
mat4.fromScaling(scaleMat, scale);
|
||||
|
||||
mat4.multiply(xform, rotateXMat, scaleMat);
|
||||
mat4.multiply(xform, rotateYMat, xform);
|
||||
mat4.multiply(xform, rotateZMat, xform);
|
||||
mat4.multiply(xform, translateMat, xform);
|
||||
},
|
||||
|
||||
loadCubemapImages: function loadCubeMapImages(urls, ok) {
|
||||
var numImages = 6;
|
||||
|
||||
var negX = new Image();
|
||||
var posX = new Image();
|
||||
var negY = new Image();
|
||||
var posY = new Image();
|
||||
var negZ = new Image();
|
||||
var posZ = new Image();
|
||||
|
||||
function onload() {
|
||||
if (--numImages === 0) {
|
||||
ok(negX, posX, negY, posY, negZ, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
negX.onload = onload;
|
||||
posX.onload = onload;
|
||||
negY.onload = onload;
|
||||
posY.onload = onload;
|
||||
negZ.onload = onload;
|
||||
posZ.onload = onload;
|
||||
|
||||
negX.src = urls.negX;
|
||||
posX.src = urls.posX;
|
||||
negY.src = urls.negY;
|
||||
posY.src = urls.posY;
|
||||
negZ.src = urls.negZ;
|
||||
posZ.src = urls.posZ;
|
||||
},
|
||||
|
||||
createBox: function createBox(options) {
|
||||
options = options || {};
|
||||
|
||||
var dimensions = options.dimensions || [1, 1, 1];
|
||||
var position = options.position || [-dimensions[0] / 2, -dimensions[1] / 2, -dimensions[2] / 2];
|
||||
var x = position[0];
|
||||
var y = position[1];
|
||||
var z = position[2];
|
||||
var width = dimensions[0];
|
||||
var height = dimensions[1];
|
||||
var depth = dimensions[2];
|
||||
|
||||
var fbl = {x: x, y: y, z: z + depth};
|
||||
var fbr = {x: x + width, y: y, z: z + depth};
|
||||
var ftl = {x: x, y: y + height, z: z + depth};
|
||||
var ftr = {x: x + width, y: y + height, z: z + depth};
|
||||
var bbl = {x: x, y: y, z: z };
|
||||
var bbr = {x: x + width, y: y, z: z };
|
||||
var btl = {x: x, y: y + height, z: z };
|
||||
var btr = {x: x + width, y: y + height, z: z };
|
||||
|
||||
var positions = new Float32Array([
|
||||
//front
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
|
||||
//right
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
|
||||
//back
|
||||
fbr.x, bbr.y, bbr.z,
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
|
||||
//left
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
|
||||
//top
|
||||
ftl.x, ftl.y, ftl.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
btl.x, btl.y, btl.z,
|
||||
ftr.x, ftr.y, ftr.z,
|
||||
btr.x, btr.y, btr.z,
|
||||
|
||||
//bottom
|
||||
bbl.x, bbl.y, bbl.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
fbl.x, fbl.y, fbl.z,
|
||||
bbr.x, bbr.y, bbr.z,
|
||||
fbr.x, fbr.y, fbr.z,
|
||||
]);
|
||||
|
||||
var uvs = new Float32Array([
|
||||
//front
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1,
|
||||
|
||||
//right
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1,
|
||||
|
||||
//back
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1,
|
||||
|
||||
//left
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1,
|
||||
|
||||
//top
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1,
|
||||
|
||||
//bottom
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 1,
|
||||
1, 0,
|
||||
1, 1
|
||||
]);
|
||||
|
||||
var normals = new Float32Array(positions.length);
|
||||
var i, count;
|
||||
var ni;
|
||||
|
||||
for (i = 0, count = positions.length / 3; i < count; i++) {
|
||||
ni = i * 3;
|
||||
|
||||
normals[ni] = parseInt(i / 6, 10) === 1 ? 1 :
|
||||
parseInt(i / 6, 10) === 3 ? -1 : 0;
|
||||
|
||||
normals[ni+1] = parseInt(i / 6, 10) === 4 ? 1 :
|
||||
parseInt(i / 6, 10) === 5 ? -1 : 0;
|
||||
|
||||
normals[ni+2] = parseInt(i / 6, 10) === 0 ? 1 :
|
||||
parseInt(i / 6, 10) === 2 ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
positions: positions,
|
||||
normals: normals,
|
||||
uvs: uvs
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
createSphere: function createSphere(options) {
|
||||
options = options || {};
|
||||
|
||||
var long_bands = options.long_bands || 32;
|
||||
var lat_bands = options.lat_bands || 32;
|
||||
var radius = options.radius || 1;
|
||||
var lat_step = Math.PI / lat_bands;
|
||||
var long_step = 2 * Math.PI / long_bands;
|
||||
var num_positions = long_bands * lat_bands * 4;
|
||||
var num_indices = long_bands * lat_bands * 6;
|
||||
var lat_angle, long_angle;
|
||||
var positions = new Float32Array(num_positions * 3);
|
||||
var normals = new Float32Array(num_positions * 3);
|
||||
var uvs = new Float32Array(num_positions * 2);
|
||||
var indices = new Uint16Array(num_indices);
|
||||
var x1, x2, x3, x4,
|
||||
y1, y2,
|
||||
z1, z2, z3, z4,
|
||||
u1, u2,
|
||||
v1, v2;
|
||||
var i, j;
|
||||
var k = 0, l = 0;
|
||||
var vi, ti;
|
||||
|
||||
for (i = 0; i < lat_bands; i++) {
|
||||
lat_angle = i * lat_step;
|
||||
y1 = Math.cos(lat_angle);
|
||||
y2 = Math.cos(lat_angle + lat_step);
|
||||
for (j = 0; j < long_bands; j++) {
|
||||
long_angle = j * long_step;
|
||||
x1 = Math.sin(lat_angle) * Math.cos(long_angle);
|
||||
x2 = Math.sin(lat_angle) * Math.cos(long_angle + long_step);
|
||||
x3 = Math.sin(lat_angle + lat_step) * Math.cos(long_angle);
|
||||
x4 = Math.sin(lat_angle + lat_step) * Math.cos(long_angle + long_step);
|
||||
z1 = Math.sin(lat_angle) * Math.sin(long_angle);
|
||||
z2 = Math.sin(lat_angle) * Math.sin(long_angle + long_step);
|
||||
z3 = Math.sin(lat_angle + lat_step) * Math.sin(long_angle);
|
||||
z4 = Math.sin(lat_angle + lat_step) * Math.sin(long_angle + long_step);
|
||||
u1 = 1 - j / long_bands;
|
||||
u2 = 1 - (j + 1) / long_bands;
|
||||
v1 = 1 - i / lat_bands;
|
||||
v2 = 1 - (i + 1) / lat_bands;
|
||||
vi = k * 3;
|
||||
ti = k * 2;
|
||||
|
||||
positions[vi] = x1 * radius;
|
||||
positions[vi+1] = y1 * radius;
|
||||
positions[vi+2] = z1 * radius; //v0
|
||||
|
||||
positions[vi+3] = x2 * radius;
|
||||
positions[vi+4] = y1 * radius;
|
||||
positions[vi+5] = z2 * radius; //v1
|
||||
|
||||
positions[vi+6] = x3 * radius;
|
||||
positions[vi+7] = y2 * radius;
|
||||
positions[vi+8] = z3 * radius; // v2
|
||||
|
||||
|
||||
positions[vi+9] = x4 * radius;
|
||||
positions[vi+10] = y2 * radius;
|
||||
positions[vi+11] = z4 * radius; // v3
|
||||
|
||||
normals[vi] = x1;
|
||||
normals[vi+1] = y1;
|
||||
normals[vi+2] = z1;
|
||||
|
||||
normals[vi+3] = x2;
|
||||
normals[vi+4] = y1;
|
||||
normals[vi+5] = z2;
|
||||
|
||||
normals[vi+6] = x3;
|
||||
normals[vi+7] = y2;
|
||||
normals[vi+8] = z3;
|
||||
|
||||
normals[vi+9] = x4;
|
||||
normals[vi+10] = y2;
|
||||
normals[vi+11] = z4;
|
||||
|
||||
uvs[ti] = u1;
|
||||
uvs[ti+1] = v1;
|
||||
|
||||
uvs[ti+2] = u2;
|
||||
uvs[ti+3] = v1;
|
||||
|
||||
uvs[ti+4] = u1;
|
||||
uvs[ti+5] = v2;
|
||||
|
||||
uvs[ti+6] = u2;
|
||||
uvs[ti+7] = v2;
|
||||
|
||||
indices[l ] = k;
|
||||
indices[l + 1] = k + 1;
|
||||
indices[l + 2] = k + 2;
|
||||
indices[l + 3] = k + 2;
|
||||
indices[l + 4] = k + 1;
|
||||
indices[l + 5] = k + 3;
|
||||
|
||||
k += 4;
|
||||
l += 6;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
positions: positions,
|
||||
normals: normals,
|
||||
uvs: uvs,
|
||||
indices: indices
|
||||
};
|
||||
},
|
||||
|
||||
computeBoundingBox: function (position, options) {
|
||||
options = options || {};
|
||||
var geo = options.geo || false;
|
||||
|
||||
var res = {
|
||||
min: vec3.create(),
|
||||
max: vec3.create()
|
||||
};
|
||||
vec3.set(res.min, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
||||
vec3.set(res.max, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
|
||||
for ( var i = 0, len = position.length; i < len; i+=3 ) {
|
||||
res.min[0] = Math.min(position[i], res.min[0]);
|
||||
res.max[0] = Math.max(position[i], res.max[0]);
|
||||
res.min[1] = Math.min(position[i], res.min[1]);
|
||||
res.max[1] = Math.max(position[i], res.max[1]);
|
||||
res.min[2] = Math.min(position[i], res.min[2]);
|
||||
res.max[2] = Math.max(position[i], res.max[2]);
|
||||
}
|
||||
|
||||
if (geo) {
|
||||
var size = vec3.create();
|
||||
vec3.subtract(size, res.max, res.min);
|
||||
res.geo = utils.createBox({
|
||||
position: res.min,
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
depth: size[2]
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user