WebGL 3D 透视
WebGL 3D perspective
我是 WebGL 的新手,我正在学习 https://webglfundamentals.org/ 中的 WebGL 教程。我在我的 canvas 中绘制了一个 3d 立方体,它工作正常。
然后我尝试了 this 的 3D 视角。之后我的立方体拉伸了,看起来像这样。 (我用了gl-matrix
做矩阵计算)
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec4 aColour;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec2 uResolution;
uniform float uFudgeFactor;
varying vec4 vColour;
void main() {
vec4 position = uModelViewMatrix * uProjectionMatrix * aVertexPosition;
vec4 zeroToOne = position / vec4(uResolution, uResolution.x, 1);
vec4 zeroToTwo = zeroToOne * 2.0;
vec4 clipSpace = zeroToTwo - 1.0;
float zToDivideBy = 1.0 + clipSpace.z * uFudgeFactor;
gl_Position = vec4(vec3(clipSpace.xy / zToDivideBy , clipSpace.z) * vec3(1, -1, 1), clipSpace.w);
vColour = aColour;
}
`
const fsSource = `
precision mediump float;
varying vec4 vColour;
void main() {
gl_FragColor = vColour;
}
`
const program = initShaderProgram(vsSource, fsSource)
const programInfo = {
program: program,
attribLocations: {
vertexPosition: gl.getAttribLocation(program, "aVertexPosition"),
color: gl.getAttribLocation(program, "aColour")
},
uniformLocations: {
modelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
projectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
resolution: gl.getUniformLocation(program, "uResolution"),
fudgeFactor: gl.getUniformLocation(program, "uFudgeFactor")
}
}
const model = mat4.create()
mat4.translate(model, model, [400, 200, 400])
const projectionMatrix = mat4.create()
mat4.perspective(projectionMatrix, Math.PI / 3, 2, 1, 1000)
let buffers = initBuffers();
requestAnimationFrame(drawScene);
function drawScene() {
gl.viewport(0, 0, canvas.width, canvas.height)
gl.clearColor(0, 0, 0, 1)
gl.clearDepth(1)
gl.enable(gl.DEPTH_TEST)
gl.depthFunc(gl.LEQUAL)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(programInfo.program)
{
const numComponents = 3;
const type = gl.FLOAT
const normalize = false
const stride = 0
const offset = 0
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position)
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition)
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset)
draw3DBox(0, 0, 0, 100, 100, 100)
}
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color)
gl.enableVertexAttribArray(programInfo.attribLocations.color)
gl.vertexAttribPointer(programInfo.attribLocations.color, 4, gl.FLOAT, false, 0, 0)
setColours()
}
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, model)
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix)
gl.uniform2f(programInfo.uniformLocations.resolution, canvas.width, canvas.height)
gl.uniform1f(programInfo.uniformLocations.fudgeFactor, 0.4)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 24)
requestAnimationFrame(drawScene)
}
function initShaderProgram(vsSource, fsSource) {
const vertexShader = loadShader(gl.VERTEX_SHADER, vsSource)
const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fsSource)
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log("Unable to initialize the shader program >> ", gl.getProgramInfoLog(shaderProgram))
return null
}
return shaderProgram
}
function loadShader(type, source) {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log("[ERROR] error occoured while compiling the shaders >> " + gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return null
}
return shader
}
function initBuffers() {
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
const colorBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
return {
color: colorBuffer,
position: positionBuffer
}
}
function draw3DBox(x, y, z, width, height, depth) {
const positions = new Float32Array([
// front
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z - depth / 2,
// right
x + width / 2, y + height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
// back
x + width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// bottom
x + width / 2, y + height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// left
x - width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z - depth / 2,
// top
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW)
}
function setColours() {
const colours = [
// front
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// right
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// back
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// bottom
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
// left
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// top
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
]
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colours), gl.STATIC_DRAW)
}
<canvas width="800px" height="400px"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
我该如何解决这个问题?我做错了什么吗?
谢谢。
透视着色器代码不正确。
这就是你所拥有的
vec4 position = uModelViewMatrix * uProjectionMatrix * aVertexPosition;
vec4 zeroToOne = position / vec4(uResolution, uResolution.x, 1);
vec4 zeroToTwo = zeroToOne * 2.0;
vec4 clipSpace = zeroToTwo - 1.0;
float zToDivideBy = 1.0 + clipSpace.z * uFudgeFactor;
gl_Position = vec4(vec3(clipSpace.xy / zToDivideBy , clipSpace.z) * vec3(1, -1, 1), clipSpace.w);
这就是你需要的。
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
您说您是从 this 开始的,但是 none zeroToOne
或 u_resolution
内容在那个页面上。事实上,该页面上的结果着色器只是
gl_Position = u_matrix * position;
我还把立方体移到相机前面的中央。它在相机后面。相机俯视-Z默认
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec4 aColour;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec2 uResolution;
uniform float uFudgeFactor;
varying vec4 vColour;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vColour = aColour;
}
`
const fsSource = `
precision mediump float;
varying vec4 vColour;
void main() {
gl_FragColor = vColour;
}
`
const program = initShaderProgram(vsSource, fsSource)
const programInfo = {
program: program,
attribLocations: {
vertexPosition: gl.getAttribLocation(program, "aVertexPosition"),
color: gl.getAttribLocation(program, "aColour")
},
uniformLocations: {
modelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
projectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
}
}
const model = mat4.create()
mat4.translate(model, model, [0, 0, -400])
const projectionMatrix = mat4.create()
mat4.perspective(projectionMatrix, Math.PI / 3, 2, 1, 1000)
let buffers = initBuffers();
requestAnimationFrame(drawScene);
function drawScene() {
gl.viewport(0, 0, canvas.width, canvas.height)
gl.clearColor(0, 0, 0, 1)
gl.clearDepth(1)
gl.enable(gl.DEPTH_TEST)
gl.depthFunc(gl.LEQUAL)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(programInfo.program)
{
const numComponents = 3;
const type = gl.FLOAT
const normalize = false
const stride = 0
const offset = 0
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position)
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition)
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset)
draw3DBox(0, 0, 0, 100, 100, 100)
}
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color)
gl.enableVertexAttribArray(programInfo.attribLocations.color)
gl.vertexAttribPointer(programInfo.attribLocations.color, 4, gl.FLOAT, false, 0, 0)
setColours()
}
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, model)
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 24)
requestAnimationFrame(drawScene)
}
function initShaderProgram(vsSource, fsSource) {
const vertexShader = loadShader(gl.VERTEX_SHADER, vsSource)
const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fsSource)
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log("Unable to initialize the shader program >> ", gl.getProgramInfoLog(shaderProgram))
return null
}
return shaderProgram
}
function loadShader(type, source) {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log("[ERROR] error occoured while compiling the shaders >> " + gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return null
}
return shader
}
function initBuffers() {
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
const colorBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
return {
color: colorBuffer,
position: positionBuffer
}
}
function draw3DBox(x, y, z, width, height, depth) {
const positions = new Float32Array([
// front
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z - depth / 2,
// right
x + width / 2, y + height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
// back
x + width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// bottom
x + width / 2, y + height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// left
x - width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z - depth / 2,
// top
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW)
}
function setColours() {
const colours = [
// front
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// right
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// back
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// bottom
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
// left
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// top
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
]
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colours), gl.STATIC_DRAW)
}
<canvas width="800px" height="400px"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
</script>
我是 WebGL 的新手,我正在学习 https://webglfundamentals.org/ 中的 WebGL 教程。我在我的 canvas 中绘制了一个 3d 立方体,它工作正常。
然后我尝试了 this 的 3D 视角。之后我的立方体拉伸了,看起来像这样。 (我用了gl-matrix
做矩阵计算)
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec4 aColour;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec2 uResolution;
uniform float uFudgeFactor;
varying vec4 vColour;
void main() {
vec4 position = uModelViewMatrix * uProjectionMatrix * aVertexPosition;
vec4 zeroToOne = position / vec4(uResolution, uResolution.x, 1);
vec4 zeroToTwo = zeroToOne * 2.0;
vec4 clipSpace = zeroToTwo - 1.0;
float zToDivideBy = 1.0 + clipSpace.z * uFudgeFactor;
gl_Position = vec4(vec3(clipSpace.xy / zToDivideBy , clipSpace.z) * vec3(1, -1, 1), clipSpace.w);
vColour = aColour;
}
`
const fsSource = `
precision mediump float;
varying vec4 vColour;
void main() {
gl_FragColor = vColour;
}
`
const program = initShaderProgram(vsSource, fsSource)
const programInfo = {
program: program,
attribLocations: {
vertexPosition: gl.getAttribLocation(program, "aVertexPosition"),
color: gl.getAttribLocation(program, "aColour")
},
uniformLocations: {
modelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
projectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
resolution: gl.getUniformLocation(program, "uResolution"),
fudgeFactor: gl.getUniformLocation(program, "uFudgeFactor")
}
}
const model = mat4.create()
mat4.translate(model, model, [400, 200, 400])
const projectionMatrix = mat4.create()
mat4.perspective(projectionMatrix, Math.PI / 3, 2, 1, 1000)
let buffers = initBuffers();
requestAnimationFrame(drawScene);
function drawScene() {
gl.viewport(0, 0, canvas.width, canvas.height)
gl.clearColor(0, 0, 0, 1)
gl.clearDepth(1)
gl.enable(gl.DEPTH_TEST)
gl.depthFunc(gl.LEQUAL)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(programInfo.program)
{
const numComponents = 3;
const type = gl.FLOAT
const normalize = false
const stride = 0
const offset = 0
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position)
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition)
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset)
draw3DBox(0, 0, 0, 100, 100, 100)
}
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color)
gl.enableVertexAttribArray(programInfo.attribLocations.color)
gl.vertexAttribPointer(programInfo.attribLocations.color, 4, gl.FLOAT, false, 0, 0)
setColours()
}
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, model)
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix)
gl.uniform2f(programInfo.uniformLocations.resolution, canvas.width, canvas.height)
gl.uniform1f(programInfo.uniformLocations.fudgeFactor, 0.4)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 24)
requestAnimationFrame(drawScene)
}
function initShaderProgram(vsSource, fsSource) {
const vertexShader = loadShader(gl.VERTEX_SHADER, vsSource)
const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fsSource)
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log("Unable to initialize the shader program >> ", gl.getProgramInfoLog(shaderProgram))
return null
}
return shaderProgram
}
function loadShader(type, source) {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log("[ERROR] error occoured while compiling the shaders >> " + gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return null
}
return shader
}
function initBuffers() {
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
const colorBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
return {
color: colorBuffer,
position: positionBuffer
}
}
function draw3DBox(x, y, z, width, height, depth) {
const positions = new Float32Array([
// front
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z - depth / 2,
// right
x + width / 2, y + height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
// back
x + width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// bottom
x + width / 2, y + height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// left
x - width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z - depth / 2,
// top
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW)
}
function setColours() {
const colours = [
// front
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// right
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// back
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// bottom
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
// left
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// top
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
]
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colours), gl.STATIC_DRAW)
}
<canvas width="800px" height="400px"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
我该如何解决这个问题?我做错了什么吗?
谢谢。
透视着色器代码不正确。
这就是你所拥有的
vec4 position = uModelViewMatrix * uProjectionMatrix * aVertexPosition;
vec4 zeroToOne = position / vec4(uResolution, uResolution.x, 1);
vec4 zeroToTwo = zeroToOne * 2.0;
vec4 clipSpace = zeroToTwo - 1.0;
float zToDivideBy = 1.0 + clipSpace.z * uFudgeFactor;
gl_Position = vec4(vec3(clipSpace.xy / zToDivideBy , clipSpace.z) * vec3(1, -1, 1), clipSpace.w);
这就是你需要的。
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
您说您是从 this 开始的,但是 none zeroToOne
或 u_resolution
内容在那个页面上。事实上,该页面上的结果着色器只是
gl_Position = u_matrix * position;
我还把立方体移到相机前面的中央。它在相机后面。相机俯视-Z默认
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec4 aColour;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec2 uResolution;
uniform float uFudgeFactor;
varying vec4 vColour;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vColour = aColour;
}
`
const fsSource = `
precision mediump float;
varying vec4 vColour;
void main() {
gl_FragColor = vColour;
}
`
const program = initShaderProgram(vsSource, fsSource)
const programInfo = {
program: program,
attribLocations: {
vertexPosition: gl.getAttribLocation(program, "aVertexPosition"),
color: gl.getAttribLocation(program, "aColour")
},
uniformLocations: {
modelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
projectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
}
}
const model = mat4.create()
mat4.translate(model, model, [0, 0, -400])
const projectionMatrix = mat4.create()
mat4.perspective(projectionMatrix, Math.PI / 3, 2, 1, 1000)
let buffers = initBuffers();
requestAnimationFrame(drawScene);
function drawScene() {
gl.viewport(0, 0, canvas.width, canvas.height)
gl.clearColor(0, 0, 0, 1)
gl.clearDepth(1)
gl.enable(gl.DEPTH_TEST)
gl.depthFunc(gl.LEQUAL)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(programInfo.program)
{
const numComponents = 3;
const type = gl.FLOAT
const normalize = false
const stride = 0
const offset = 0
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position)
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition)
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset)
draw3DBox(0, 0, 0, 100, 100, 100)
}
{
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color)
gl.enableVertexAttribArray(programInfo.attribLocations.color)
gl.vertexAttribPointer(programInfo.attribLocations.color, 4, gl.FLOAT, false, 0, 0)
setColours()
}
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, model)
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 24)
requestAnimationFrame(drawScene)
}
function initShaderProgram(vsSource, fsSource) {
const vertexShader = loadShader(gl.VERTEX_SHADER, vsSource)
const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fsSource)
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.log("Unable to initialize the shader program >> ", gl.getProgramInfoLog(shaderProgram))
return null
}
return shaderProgram
}
function loadShader(type, source) {
const shader = gl.createShader(type)
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log("[ERROR] error occoured while compiling the shaders >> " + gl.getShaderInfoLog(shader))
gl.deleteShader(shader)
return null
}
return shader
}
function initBuffers() {
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
const colorBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
return {
color: colorBuffer,
position: positionBuffer
}
}
function draw3DBox(x, y, z, width, height, depth) {
const positions = new Float32Array([
// front
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z - depth / 2,
// right
x + width / 2, y + height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
// back
x + width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// bottom
x + width / 2, y + height / 2, z - depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x + width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z + depth / 2,
// left
x - width / 2, y + height / 2, z + depth / 2,
x - width / 2, y + height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x - width / 2, y - height / 2, z - depth / 2,
// top
x - width / 2, y - height / 2, z - depth / 2,
x + width / 2, y - height / 2, z - depth / 2,
x - width / 2, y - height / 2, z + depth / 2,
x + width / 2, y - height / 2, z + depth / 2,
]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW)
}
function setColours() {
const colours = [
// front
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// right
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// back
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// bottom
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
// left
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// top
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
]
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colours), gl.STATIC_DRAW)
}
<canvas width="800px" height="400px"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
</script>