WebGL点光源问题

问题描述 投票:0回答:1

我已经尝试在WebGL中创建一个旋转的多维数据集,并使用纹理映射技术对其进行纹理化,我认为效果很好。多维数据集旋转以尝试演示我尝试实现的(点)照明,但是它似乎以一种意外的方式起作用,我不确定是什么原因造成的。任何提示将不胜感激,谢谢。

// Vertex shader program
var VSHADER_SOURCE = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  attribute vec4 a_Normal;        
  attribute vec2 vertTexCoord;   

  uniform mat4 u_ModelMatrix;
  uniform mat4 u_NormalMatrix;
  uniform mat4 u_ProjMatrix;

  varying vec4 v_Color;
  varying vec3 v_Normal;
  varying vec2 fragTexCoord; 
  varying vec3 v_Position;

  void main() {
    gl_Position = u_ProjMatrix * u_ModelMatrix * a_Position;
    v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));
    v_Color = a_Color;
    fragTexCoord = vertTexCoord;
  }
  `;

// Fragment shader program
var FSHADER_SOURCE = `
  precision mediump float;
  uniform sampler2D sampler;
  varying vec3 v_Normal;
  varying vec3 v_Position;
  varying vec2 fragTexCoord;
  varying vec4 v_Color;

  uniform vec3 u_LightColor;
  uniform vec3 u_LightPosition;
  uniform vec3 u_AmbientLight;
  void main() {
    vec3 normal = normalize(v_Normal);
    vec3 u_LightDirection = normalize(u_LightPosition - v_Position);
    float nDotL = max(dot(u_LightDirection, normal), 0.0);
    vec4 TexColor = texture2D(sampler, fragTexCoord);
    vec3 diffuse;
    diffuse = u_LightColor * TexColor.rgb * nDotL * 1.2;

    vec3 ambient = u_AmbientLight * v_Color.rgb;
    gl_FragColor = vec4(diffuse + ambient, v_Color.a);
  }
  `;

var modelMatrix = new Matrix4(); // The model matrix
var projMatrix = new Matrix4();  // The projection matrix
var g_normalMatrix = new Matrix4();  // Coordinate transformation matrix for normals

var g_xAngle = 0.0;    // The rotation x angle (degrees)

function main() {

  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');
  canvas.width=document.body.clientWidth;
  canvas.height=document.body.clientHeight;

  // Get the rendering context for WebGL
  gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Set clear color and enable hidden surface removal
  gl.clearColor(1, 1, 1, 1.0);
  gl.enable(gl.DEPTH_TEST);

  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Get the storage locations of uniform attributes
  u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
  u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
  u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
  u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
  u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
  u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');

  if (!u_ModelMatrix || !u_ProjMatrix|| !u_NormalMatrix || !u_LightColor || !u_LightPosition || !u_AmbientLight) { 
    console.log('Failed to get the storage location');
    return;
  }


  // Set the light color (white)
  gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
  // Set the light direction (in the world coordinate)
  gl.uniform3f(u_LightPosition, 1, 1, 1);
  // Set the ambient light
  gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);

  projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);

  function render(now) {
    now *= 0.001;  // convert to seconds
    g_xAngle = (g_xAngle + 1) % 360
    draw();
    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
}

function setTexture(gl, texturetype){
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(
    gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
    gl.UNSIGNED_BYTE, document.getElementById(texturetype)
  );
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

  gl.bindTexture(gl.TEXTURE_2D, null);
  return texture;
}

function initVertexBuffers(gl) {

  var vertices = new Float32Array([   // Coordinates
    -0.5, 0.5, -0.5,   //top
    -0.5, 0.5, 0.5,  
    0.5, 0.5, 0.5,  
    0.5, 0.5, -0.5,

    -0.5, 0.5, 0.5,  //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,   //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,  //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,  //back
    0.5,-0.5,-0.5,  
    -0.5, -0.5,-0.5,   
    -0.5, 0.5,-0.5,

    -0.5,-0.5,-0.5,  //bottom
    -0.5,-0.5, 0.5,   
    0.5,-0.5, 0.5,  
    0.5,-0.5, -0.5,

 ]);

  var texcoords = new Float32Array([
    //u, v : u across, v down. 0,0 top left, 0,1 bottom left etc.
    // Blue
    0.0,  0.0,
    1/3,  0.0,
    1/3,  1/3,
    0,  1/3,

    // Green
    0.0,  1/3,
    1/3,  1/3,
    1/3,  2/3,
    0.0,  2/3,

    // Orange
    1/3,  1/3,
    2/3,  1/3,
    2/3,  2/3,
    1/3,  2/3,

    // Red
    0.0,  2/3,
    1/3,  2/3,
    1/3,  1.0,
    0.0,  1.0,

    // White
    1/3,  2/3,
    2/3,  2/3,
    2/3,  1.0,
    1/3,  1.0,

    // Yellow
    2/3,  2/3,
    1.0,  2/3,
    1.0,  1.0,
    2/3,  1.0,

  ])

  var normals = new Float32Array([    // Normal
    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
  ]);

  var indices = new Uint8Array([
     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
 ]);


  // Write the vertex property to buffers (coordinates, colors and normals)
  if (!initArrayBuffer(gl, 'a_Position', vertices, 3, gl.FLOAT)) return -1;
  if (!initArrayBuffer(gl, 'vertTexCoord', texcoords, 2, gl.FLOAT)) return -1; 
  if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;

  // Write the indices to the buffer object
  var indexBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

  return indices.length;
}

function initArrayBuffer (gl, attribute, data, num, type) {

  // Create a buffer object
  var buffer = gl.createBuffer();
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // Write date into the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  // Assign the buffer object to the attribute variable
  var a_attribute = gl.getAttribLocation(gl.program, attribute);
  if (a_attribute < 0) {
    console.log('Failed to get the storage location of ' + attribute);
    return false;
  }
  gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
  gl.enableVertexAttribArray(a_attribute);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  return true;
}

var g_matrixStack = []; // Array for storing a matrix
function pushMatrix(m) { // Store the specified matrix to the array
  var m2 = new Matrix4(m);
  g_matrixStack.push(m2);
}

function popMatrix() { // Retrieve the matrix from the array
  return g_matrixStack.pop();
}

function draw(){

  gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);

  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  var boxTexture = setTexture(gl,'cube');

  modelMatrix.setTranslate(0, 0, -5);  // Translation (No translation is supported here)
  modelMatrix.rotate(g_xAngle, 1, 1, 0); // Rotate along y axis

  // Model the cube
  pushMatrix(modelMatrix);
    modelMatrix.scale(1,1,1); // Scale
    drawCube(gl, u_ModelMatrix, u_NormalMatrix, n, boxTexture);
  modelMatrix = popMatrix();

}

function drawCube(gl, u_ModelMatrix, u_NormalMatrix, n, texture) {
  pushMatrix(modelMatrix);

    // Pass the model matrix to the uniform variable
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

    // Calculate the normal transformation matrix and pass it to u_NormalMatrix
    g_normalMatrix.setInverseOf(modelMatrix);
    g_normalMatrix.transpose();
    gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.activeTexture(gl.TEXTURE0);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

  modelMatrix = popMatrix();
}

[这里是一个视频,可以看到光线在它看起来所在的位置和所照亮的地方不一致:Youtube cube video

文件:https://github.com/bebeausome/rubixcubewebgl

webgl lighting
1个回答
0
投票

代码有两个问题

问题1:正常计算是错误的

v_Normal = normalize(vec3(u_NormalMatrix * a_Normal));

不会工作。它使用vec4 a_Normal,其中w = 1(默认值),这意味着。您要么需要将a_Normal.w设置为0

v_Normal = normalize(vec3(u_NormalMatrix * vec4(a_Normal,0)));

或仅使用法线矩阵的旋转部分

v_Normal = normalize(mat3(u_NormalMatrix) * a_Normal.xyz);

注意:如果将.xyz声明为a_Normal,则不需要vec3

另一个问题是正常数据有误。

通过在顶点着色器中的位置添加法线很容易检查

gl_Position = u_ProjMatrix * u_ModelMatrix * (a_Position + vec4(a_Normal.xyz * 0.1, 0));

在这种情况下,立方体的每个面都应沿法线方向移动。他们并没有说清楚法线是坏的。

至于步骤。

  • 我让代码正常工作(发布工作代码很有帮助)。
  • 发现您的数学库使用度数而不是弧度(这对IMO不利)
  • 仅尝试绘制带有纹理的(有效)

    注意:这是在属性和统一位置不显示的情况下不会失败的参数

    问题是我只想输入gl_FragColor = TexColor,但是一旦我这样做,JS代码就会失败,因为WebGL优化了所有制服并且严格代码失败了。

    仅打印警告可能会更好,因为它会使调试着色器更加容易。

    要解决这个问题,我必须始终使用每个属性和制服乘以零。

    gl_FragColor = TexColor + 0. * vec4(diffuse + ambient, v_Color.a);
    
  • 仅尝试绘制法线

    gl_FragColor = normal * 0.5 + 0.5 + 0. * ....
    

    很难看到发生了什么,所以将代码更改为仅绕Y旋转

    modelMatrix.rotate(g_xAngle, /* 1 */ 0, 1, 0); 
    

    然后,当它们面对相同的方向时,颜色应该总是相同的。他们不是。

  • 导致其他2个问题。

const m4 = twgl.m4;

class Matrix4 {
  constructor() {
    this.elements = m4.identity();
  }
  setPerspective(fov, aspect, near, far) {
    m4.perspective(fov * Math.PI / 180, aspect, near, far, this.elements);
  }
  setTranslate(x, y, z) {
    m4.translation([x, y, z], this.elements);
  }
  rotate(angle, x, y, z) {
    m4.axisRotate(this.elements, [x, y, z], angle * Math.PI / 180, this.elements);
  }
  scale(x, y, z) {
    m4.scale(this.elements, [x, y, z], this.elements);
  }
  setInverseOf(src) {
    m4.inverse(src.elements, this.elements);
  }
  transpose() {
    m4.transpose(this.elements, this.elements);
  }
}

{
  const ctx = document.querySelector('#cube').getContext('2d');
  for (let i = 0; i < 9; ++i) {
    ctx.fillStyle = `hsl(${i *360 / 9},100%,50%)`;
    ctx.fillRect(i % 3 * 100, (i / 3 | 0) * 50, 100, 50);
  }
}

let boxTexture;

// Vertex shader program
var VSHADER_SOURCE = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  attribute vec4 a_Normal;        
  attribute vec2 vertTexCoord;   

  uniform mat4 u_ModelMatrix;
  uniform mat4 u_NormalMatrix;
  uniform mat4 u_ProjMatrix;

  varying vec4 v_Color;
  varying vec3 v_Normal;
  varying vec2 fragTexCoord; 
  varying vec3 v_Position;

  void main() {
    gl_Position = u_ProjMatrix * u_ModelMatrix * a_Position;
    v_Position = (u_ModelMatrix * a_Position).xyz;
    v_Normal = normalize(mat3(u_ModelMatrix) * a_Normal.xyz);
    v_Color = a_Color + u_NormalMatrix[0][0] * 0.;
    fragTexCoord = vertTexCoord;
  }
  `;

// Fragment shader program
var FSHADER_SOURCE = `
  precision highp float;
  uniform sampler2D sampler;
  varying vec3 v_Normal;
  varying vec3 v_Position;
  varying vec2 fragTexCoord;
  varying vec4 v_Color;

  uniform vec3 u_LightColor;
  uniform vec3 u_LightPosition;
  uniform vec3 u_AmbientLight;
  void main() {
    vec3 normal = normalize(v_Normal);
    vec3 u_LightDirection = normalize(u_LightPosition - v_Position);
    float nDotL = max(dot(u_LightDirection, normal), 0.0);
    vec4 TexColor = texture2D(sampler, fragTexCoord);
    vec3 diffuse;
    diffuse = u_LightColor * TexColor.rgb * nDotL * 1.2;

    vec3 ambient = u_AmbientLight * v_Color.rgb;
    gl_FragColor = vec4(diffuse + ambient, v_Color.a);
  }
  `;

var modelMatrix = new Matrix4(); // The model matrix
var projMatrix = new Matrix4();  // The projection matrix
var g_normalMatrix = new Matrix4();  // Coordinate transformation matrix for normals

var g_xAngle = 0.0;    // The rotation x angle (degrees)

function main() {

  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');
  canvas.width=document.body.clientWidth;
  canvas.height=document.body.clientHeight;

  // Get the rendering context for WebGL
  gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Set clear color and enable hidden surface removal
  gl.clearColor(1, 1, 1, 1.0);
  gl.enable(gl.DEPTH_TEST);

  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Get the storage locations of uniform attributes
  u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
  u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
  u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
  u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');
  u_LightPosition = gl.getUniformLocation(gl.program, 'u_LightPosition');
  u_AmbientLight = gl.getUniformLocation(gl.program, 'u_AmbientLight');

  if (!u_ModelMatrix || !u_ProjMatrix|| !u_NormalMatrix || !u_LightColor || !u_LightPosition || !u_AmbientLight) { 
    console.log('Failed to get the storage location');
    return;
  }


  // Set the light color (white)
  gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);
  // Set the light direction (in the world coordinate)
  gl.uniform3f(u_LightPosition, 1, 1, 1);
  // Set the ambient light
  gl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);

  projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);
  
  boxTexture = setTexture(gl,'cube');

  function render(now) {
    now *= 0.001;  // convert to seconds
    g_xAngle = (g_xAngle + 1) % 360
    draw();
    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
}

function setTexture(gl, texturetype){
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(
    gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
    gl.UNSIGNED_BYTE, document.getElementById(texturetype)
  );
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

  gl.bindTexture(gl.TEXTURE_2D, null);
  return texture;
}

function initVertexBuffers(gl) {
  var vertices = new Float32Array([   // Coordinates
    -0.5, 0.5, -0.5,   //top
    -0.5, 0.5, 0.5,  
    0.5, 0.5, 0.5,  
    0.5, 0.5, -0.5,

    -0.5, 0.5, 0.5,  //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,   //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,  //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,  //back
    0.5,-0.5,-0.5,  
    -0.5, -0.5,-0.5,   
    -0.5, 0.5,-0.5,

    -0.5,-0.5,-0.5,  //bottom
    -0.5,-0.5, 0.5,   
    0.5,-0.5, 0.5,  
    0.5,-0.5, -0.5,

 ]);

  var texcoords = new Float32Array([
    //u, v : u across, v down. 0,0 top left, 0,1 bottom left etc.
    // Blue
    0.0,  0.0,
    1/3,  0.0,
    1/3,  1/3,
    0,  1/3,

    // Green
    0.0,  1/3,
    1/3,  1/3,
    1/3,  2/3,
    0.0,  2/3,

    // Orange
    1/3,  1/3,
    2/3,  1/3,
    2/3,  2/3,
    1/3,  2/3,

    // Red
    0.0,  2/3,
    1/3,  2/3,
    1/3,  1.0,
    0.0,  1.0,

    // White
    1/3,  2/3,
    2/3,  2/3,
    2/3,  1.0,
    1/3,  1.0,

    // Yellow
    2/3,  2/3,
    1.0,  2/3,
    1.0,  1.0,
    2/3,  1.0,

  ])

  var normals = new Float32Array([    // Normal
    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
    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, 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
    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
    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
  ]);

  var indices = new Uint8Array([
     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
 ]);


  // Write the vertex property to buffers (coordinates, colors and normals)
  if (!initArrayBuffer(gl, 'a_Position', vertices, 3, gl.FLOAT)) return -1;
  if (!initArrayBuffer(gl, 'vertTexCoord', texcoords, 2, gl.FLOAT)) return -1; 
  if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;

  // Write the indices to the buffer object
  var indexBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

  return indices.length;
}

function initArrayBuffer (gl, attribute, data, num, type) {

  // Create a buffer object
  var buffer = gl.createBuffer();
  if (!buffer) {
    console.log('Failed to create the buffer object');
    return false;
  }
  // Write date into the buffer object
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  // Assign the buffer object to the attribute variable
  var a_attribute = gl.getAttribLocation(gl.program, attribute);
  if (a_attribute < 0) {
    console.log('Failed to get the storage location of ' + attribute);
    return false;
  }
  gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
  gl.enableVertexAttribArray(a_attribute);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  return true;
}

var g_matrixStack = []; // Array for storing a matrix
function pushMatrix(m) { // Store the specified matrix to the array
  var m2 = new Matrix4(m);
  g_matrixStack.push(m2);
}

function popMatrix() { // Retrieve the matrix from the array
  return g_matrixStack.pop();
}

function draw(){

  gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);

  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  modelMatrix.setTranslate(0, 0, -5);  // Translation (No translation is supported here)
  modelMatrix.rotate(g_xAngle, 1, 1, 0); // Rotate along y axis

  // Model the cube
  pushMatrix(modelMatrix);
    modelMatrix.scale(1,1,1); // Scale
    drawCube(gl, u_ModelMatrix, u_NormalMatrix, n, boxTexture);
  modelMatrix = popMatrix();

}

function drawCube(gl, u_ModelMatrix, u_NormalMatrix, n, texture) {
  pushMatrix(modelMatrix);

    // Pass the model matrix to the uniform variable
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

    // Calculate the normal transformation matrix and pass it to u_NormalMatrix
    g_normalMatrix.setInverseOf(modelMatrix);
    g_normalMatrix.transpose();
    gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);

    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.activeTexture(gl.TEXTURE0);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

  modelMatrix = popMatrix();
}

function getWebGLContext(canvas) { return canvas.getContext('webgl'); }
function initShaders(gl, vs, fs) { 
  // This is BAD!!!!!!! Real WebGL apps have more than one program
  // adding properties to builtins is bad as well.
  gl.program = twgl.createProgram(gl, [vs, fs]); 
  // This is BAD!!!!!!!
  gl.useProgram(gl.program);
  return gl.program;
}

main();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas id="webgl"></canvas>
<canvas id="cube" style="display: none;"></canvas>
© www.soinside.com 2019 - 2024. All rights reserved.