Created
July 22, 2024 01:00
-
-
Save jeantimex/0dcd6c5b1c20112a49695c5048925ce7 to your computer and use it in GitHub Desktop.
Load glTF for a simple cube
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"asset" : { | |
"generator" : "Khronos glTF Blender I/O v1.7.33", | |
"version" : "2.0" | |
}, | |
"scene" : 0, | |
"scenes" : [ | |
{ | |
"name" : "Scene", | |
"nodes" : [ | |
0 | |
] | |
} | |
], | |
"nodes" : [ | |
{ | |
"mesh" : 0, | |
"name" : "Cube" | |
} | |
], | |
"materials" : [ | |
{ | |
"doubleSided" : true, | |
"name" : "Material", | |
"pbrMetallicRoughness" : { | |
"baseColorFactor" : [ | |
0.800000011920929, | |
0.800000011920929, | |
0.800000011920929, | |
1 | |
], | |
"metallicFactor" : 0, | |
"roughnessFactor" : 0.4000000059604645 | |
} | |
} | |
], | |
"meshes" : [ | |
{ | |
"name" : "Cube", | |
"primitives" : [ | |
{ | |
"attributes" : { | |
"POSITION" : 0, | |
"NORMAL" : 1 | |
}, | |
"indices" : 2, | |
"material" : 0 | |
} | |
] | |
} | |
], | |
"accessors" : [ | |
{ | |
"bufferView" : 0, | |
"componentType" : 5126, | |
"count" : 24, | |
"max" : [ | |
1, | |
1, | |
1 | |
], | |
"min" : [ | |
-1, | |
-1, | |
-1 | |
], | |
"type" : "VEC3" | |
}, | |
{ | |
"bufferView" : 1, | |
"componentType" : 5126, | |
"count" : 24, | |
"type" : "VEC3" | |
}, | |
{ | |
"bufferView" : 2, | |
"componentType" : 5123, | |
"count" : 36, | |
"type" : "SCALAR" | |
} | |
], | |
"bufferViews" : [ | |
{ | |
"buffer" : 0, | |
"byteLength" : 288, | |
"byteOffset" : 0 | |
}, | |
{ | |
"buffer" : 0, | |
"byteLength" : 288, | |
"byteOffset" : 288 | |
}, | |
{ | |
"buffer" : 0, | |
"byteLength" : 72, | |
"byteOffset" : 576 | |
} | |
], | |
"buffers" : [ | |
{ | |
"byteLength" : 648, | |
"uri" : "BoxBlender3.bin" | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Loading a cube from gltf 2.0. WebGL, JavaScript</title> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/gl-matrix-min.js"></script> | |
</head> | |
<body> | |
<canvas id="renderCanvas" width="400" height="400"></canvas> | |
<script> | |
loadFile("assets/BoxBlender3.gltf", (content) => | |
{ | |
const gltf = JSON.parse(content); | |
loadBin("assets/BoxBlender3.bin", (binData) => | |
{ | |
const canvas = document.getElementById("renderCanvas"); | |
const gl = canvas.getContext("webgl"); | |
gl.enable(gl.DEPTH_TEST); | |
const vertShaderSource = | |
`attribute vec4 aPosition; | |
attribute vec4 aNormal; | |
uniform mat4 uMvpMatrix; | |
uniform mat4 uModelMatrix; | |
uniform mat4 uNormalMatrix; | |
varying vec3 vPosition; | |
varying vec3 vNormal; | |
void main() | |
{ | |
gl_Position = uMvpMatrix * aPosition; | |
vPosition = vec3(uModelMatrix * aPosition); | |
vNormal = normalize(vec3(uNormalMatrix * aNormal)); | |
}`; | |
const fragShaderSource = | |
`precision mediump float; | |
const vec3 lightColor = vec3(1.0, 1.0, 1.0); | |
const vec3 ambientLight = vec3(0.2, 0.2, 0.2); | |
uniform vec3 uLightPosition; | |
varying vec3 vPosition; | |
varying vec3 vNormal; | |
void main() | |
{ | |
vec4 color = vec4(0.5, 1.0, 0.5, 1.0); | |
vec3 normal = normalize(vNormal); | |
vec3 lightDirection = normalize(uLightPosition - vPosition); | |
float nDotL = max(dot(lightDirection, normal), 0.0); | |
vec3 diffuse = lightColor * color.rgb * nDotL; | |
vec3 ambient = ambientLight * color.rgb; | |
gl_FragColor = vec4(diffuse + ambient, color.a); | |
}`; | |
const vShader = gl.createShader(gl.VERTEX_SHADER); | |
gl.shaderSource(vShader, vertShaderSource); | |
gl.compileShader(vShader); | |
let ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS); | |
if (!ok) { console.log("vert: " + gl.getShaderInfoLog(vShader)); }; | |
const fShader = gl.createShader(gl.FRAGMENT_SHADER); | |
gl.shaderSource(fShader, fragShaderSource); | |
gl.compileShader(fShader); | |
ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS); | |
if (!ok) { console.log("frag: " + gl.getShaderInfoLog(fShader)); }; | |
const program = gl.createProgram(); | |
gl.attachShader(program, vShader); | |
gl.attachShader(program, fShader); | |
gl.bindAttribLocation(program, 0, "aPosition"); | |
gl.bindAttribLocation(program, 1, "aNormal"); | |
gl.linkProgram(program); | |
ok = gl.getProgramParameter(program, gl.LINK_STATUS); | |
if (!ok) { console.log("link: " + gl.getProgramInfoLog(program)); }; | |
gl.useProgram(program); | |
// Create a cube | |
// v6----- v5 | |
// /| /| | |
// v1------v0| | |
// | | | | | |
// | |v7---|-|v4 | |
// |/ |/ | |
// v2------v3 | |
// const vertPositions = [ | |
// 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, // v0-v1-v2-v3 front | |
// 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, // v0-v3-v4-v5 right | |
// 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, // v0-v5-v6-v1 up | |
// -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, // v1-v6-v7-v2 left | |
// -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, // v7-v4-v3-v2 down | |
// 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5 // v4-v7-v6-v5 back | |
// ]; | |
const vertPosBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer); | |
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW); | |
// const vertPosData = new Uint8Array(binData, 0, 288); | |
const vertPosData = new Float32Array(binData, 0, 288 / Float32Array.BYTES_PER_ELEMENT); | |
gl.bufferData(gl.ARRAY_BUFFER, vertPosData, gl.STATIC_DRAW); | |
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); | |
gl.enableVertexAttribArray(0); | |
// const normals = [ | |
// 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front | |
// 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right | |
// 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up | |
// -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left | |
// 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down | |
// 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0 // v4-v7-v6-v5 back | |
// ]; | |
const normalBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); | |
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW); | |
// const normalData = new Uint8Array(binData, 288, 288); | |
const normalData = new Float32Array(binData, 288, 288 / Float32Array.BYTES_PER_ELEMENT); | |
gl.bufferData(gl.ARRAY_BUFFER, normalData, gl.STATIC_DRAW); | |
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0); | |
gl.enableVertexAttribArray(1); | |
// const indices = [ | |
// 0, 1, 2, 0, 2, 3, // front | |
// 4, 5, 6, 4, 6, 7, // right | |
// 8, 9, 10, 8, 10, 11, // up | |
// 12, 13, 14, 12, 14, 15, // left | |
// 16, 17, 18, 16, 18, 19, // down | |
// 20, 21, 22, 20, 22, 23 // back | |
// ]; | |
const indexBuffer = gl.createBuffer(); | |
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); | |
// const indexData = new Uint8Array(binData, 576, 72); | |
const indexData = new Uint16Array(binData, 576, 36); | |
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW); | |
const projMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.perspective(projMatrix, 55 * Math.PI / 180, 1, 0.1, 500); | |
const viewMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.lookAt(viewMatrix, [10, 15, 20], [0, 0, 0], [0, 1, 0]); | |
const projViewMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.mul(projViewMatrix, projMatrix, viewMatrix); | |
const modelMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.fromTranslation(modelMatrix, [0, 0, 0]); | |
glMatrix.mat4.rotate(modelMatrix, modelMatrix, 0 * Math.PI / 180, [1, 0, 0]); | |
glMatrix.mat4.scale(modelMatrix, modelMatrix, [5, 5, 5]); | |
const mvpMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.mul(mvpMatrix, projViewMatrix, modelMatrix); | |
const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix"); | |
gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix); | |
const uModelMatrixLocation = gl.getUniformLocation(program, "uModelMatrix"); | |
gl.uniformMatrix4fv(uModelMatrixLocation, false, modelMatrix); | |
const normalMatrix = glMatrix.mat4.create(); | |
glMatrix.mat4.invert(normalMatrix, modelMatrix); | |
glMatrix.mat4.transpose(normalMatrix, normalMatrix); | |
const uNormalMatrixLocation = gl.getUniformLocation(program, "uNormalMatrix"); | |
gl.uniformMatrix4fv(uNormalMatrixLocation, false, normalMatrix); | |
const lightPosition = glMatrix.vec3.fromValues(7, 8, 9); | |
const uLightPositionLocation = gl.getUniformLocation(program, "uLightPosition"); | |
gl.uniform3fv(uLightPositionLocation, lightPosition); | |
gl.clearColor(0.2, 0.2, 0.2, 1); | |
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0); | |
}); | |
}); | |
function loadFile(path, callback) | |
{ | |
const xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = () => | |
{ | |
if (xhr.readyState === 4 && xhr.status != 404) | |
{ | |
callback(xhr.responseText); | |
} | |
}; | |
xhr.open("GET", path, true); | |
xhr.send(); | |
} | |
function loadBin(path, callback) | |
{ | |
const xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = () => | |
{ | |
if (xhr.readyState === 4 && xhr.status != 404) | |
{ | |
callback(xhr.response); | |
} | |
}; | |
xhr.open("GET", path, true); | |
xhr.responseType = "arraybuffer"; | |
xhr.send(); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://plnkr.co/edit/BYseznZdUBTrUmRa?preview