向 vanilla wegl 中的变换立方体添加定向光 [英] Adding a directional light to a transforming cube in vanilla wegl

查看:47
本文介绍了向 vanilla wegl 中的变换立方体添加定向光的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何向 webGL 中的变换立方体添加方向光.

我知道它需要法线并且我已将它们添加到代码段中(我已将它们注释掉)

它还需要在顶点着色器中进行一些数学运算.不幸的是,当我取消注释时,此代码不起作用.

属性vec4坐标;统一 mat4 变换矩阵;属性 vec3 正常;属性 vec4 颜色;统一的 vec3 lightColor;统一 vec3 lightDirection;变化的 vec4 变化的颜色;统一 mat4 透视矩阵;无效主(无效){vec3 规范 = 规范化(正常);vec3 ld = 标准化(lightDirection);float dotProduct = max(dot(norm, ld), 0.0);vec3 vertexColor = lightColor * 颜色 * dotProduct;变化颜色 = vec4(vertexColor, 1);gl_Position = 透视矩阵 * 变换矩阵 * 坐标;}

var gl,着色器程序,顶点,矩阵 = mat4.create(),顶点数,索引计数,q = quat.create(),翻译 =[-3, 0, -10],比例 = [1,1,1],枢轴 = [0,0,0];翻译2 = [0, 0, -8],scale2 = [3,3,3],枢轴2 = [1,1,1]initGL();创建着色器();创建顶点();创建索引();画();函数 initGL() {var canvas = document.getElementById("canvas");gl = canvas.getContext("webgl");gl.启用(gl.DEPTH_TEST);gl.viewport(0, 0, canvas.width, canvas.height);gl.clearColor(1, 1, 1, 1);}函数 createShaders() {var vertexShader = getShader(gl, "shader-vs");var fragmentShader = getShader(gl, "shader-fs");shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);gl.useProgram(shaderProgram);}函数 createVertices() {顶点 = [-1, -1, -1, 1, 0, 0, 1,//01, -1, -1, 1, 1, 0, 1,//1-1, 1, -1, 0, 1, 1, 1,//21, 1, -1, 0, 0, 1, 1,//3-1, 1, 1, 1, 0.5, 0, 1,//41, 1, 1, 0.5, 1, 1, 1,//5-1, -1, 1, 1, 0, 0.5, 1,//61, -1, 1, 0.5, 0, 1, 1,//7];vertexCount = vertices.length/7;var buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,缓冲区);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);var coords = gl.getAttribLocation(shaderProgram, "coords");gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, 0);gl.enableVertexAttribArray(coords);/**var 法线 = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0];var normalBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);var normalLocation = gl.getAttribLocation(shaderProgram, "normal");gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0);gl.enableVertexAttribArray(normalLocation);gl.bindBuffer(gl.ARRAY_BUFFER, null);var lightColor = gl.getUniformLocation(shaderProgram, "lightColor");gl.uniform3f(lightColor, 1, 1, 1);var lightDirection = gl.getUniformLocation(shaderProgram, "lightDirection");gl.uniform3f(lightDirection, 0.5, 1, 0);*/var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, Float32Array.BYTES_PER_ELEMENT * 3);gl.enableVertexAttribArray(colorsLocation);gl.bindBuffer(gl.ARRAY_BUFFER, null);varperspectiveMatrix = mat4.create();mat4.perspective(perspectiveMatrix, 1, canvas.width/canvas.height, 0.1, 11);varperspectiveLoc = gl.getUniformLocation(shaderProgram, "perspectiveMatrix");gl.uniformMatrix4fv(perspectiveLoc,假,透视矩阵);}函数创建索引(){变量索引 = [0, 1, 2, 1, 2, 3,2, 3, 4, 3, 4, 5,4, 5, 6, 5, 6, 7,6, 7, 0, 7, 0, 1,0, 2, 6, 2, 6, 4,1, 3, 7, 3, 7, 5];indexCount = 索引长度;var indexBuffer = gl.createBuffer();gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);}函数绘制(timeMs){请求动画帧(绘制);让间隔 = timeMs/3000让 t = 间隔 - Math.floor(interval);让 trans_t = vec3.lerp([], translate, translate2, t);让 scale_t = vec3.lerp([], scale, scale2, t);让pivot_t = vec3.lerp([],pivot,pivot2,t);mat4.fromRotationTranslationScaleOrigin(matrix, q, trans_t, scale_t, pivot_t);var transformMatrix = gl.getUniformLocation(shaderProgram, "transformMatrix");gl.uniformMatrix4fv(transformMatrix, false, matrix);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);}/** https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context*/函数 getShader(gl, id) {var shaderScript, theSource, currentChild, shader;shaderScript = document.getElementById(id);如果(!shaderScript){返回空;}theSource = "";currentChild = shaderScript.firstChild;而(当前孩子){如果(currentChild.nodeType == currentChild.TEXT_NODE){theSource += currentChild.textContent;}currentChild = currentChild.nextSibling;}if (shaderScript.type == "x-shader/x-fragment") {着色器 = gl.createShader(gl.FRAGMENT_SHADER);} else if (shaderScript.type == "x-shader/x-vertex") {着色器 = gl.createShader(gl.VERTEX_SHADER);} 别的 {//未知着色器类型返回空;}gl.shaderSource(shader, theSource);//编译着色器程序gl.compileShader(shader);//查看是否编译成功如果(!gl.getShaderParameter(着色器,gl.COMPILE_STATUS)){alert("编译着色器时出错:" + gl.getShaderInfoLog(shader));返回空;}返回着色器;}

<script id="shader-fs" type="x-shader/x-fragment">精密中等浮点数;统一的 vec4 颜色;变化的 vec4 变化的颜色;无效主(无效){gl_FragColor = 变化的颜色;}<canvas id="canvas" width="600" height="600"></canvas><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>

解决方案

着色器代码存在问题:

<块引用>

vec3 vertexColor = lightColor * colors * dotProduct;

color的类型是vec4,而vertexColor的类型是vec3,所以必须是:

vec3 vertexColor = lightColor * colors.rgb * dotProduct;

您不能将 vec4 类型的变量分配给 vec3 类型的变量.

<小时>

gl.vertexAttribPointer 被调用时,必须先绑定合适的顶点缓冲区.在您指定 colorsLocation 属性的地方,带有 normals 的缓冲区被绑定,而不是带有顶点和颜色(vertices>).

<小时>

顶点坐标及其属性是元组.如果一个顶点坐标被使用两次(或在三个边上使用 3 次)并且每次它都与不同的法向量相关联,那么该坐标必须被复制".每个顶点坐标恰好与 1 个法向量相关联.
请参阅渲染具有多个索引的网格.

想象一个 3 维顶点坐标和一个 3 维法向量为 1,但 6 维属性.

创建一个线性化的属性数组:

vertices = [[-1, -1, -1, 1, 0, 0, 1],//0[ 1, -1, -1, 1, 1, 0, 1],//1[-1, 1, -1, 0, 1, 1, 1],//2[ 1, 1, -1, 0, 0, 1, 1],//3[-1, 1, 1, 1, 0.5, 0, 1],//4[1, 1, 1, 0.5, 1, 1, 1],//5[-1, -1, 1, 1, 0, 0.5, 1],//6[1, -1, 1, 0.5, 0, 1, 1],//7];var 法线 = [[0, 0, 1], [0, 1, 0], [0, 0, -1],[0, -1, 0], [-1, 0, 0], [1, 0, 0] ];变量索引 = [[0, 1, 2, 1, 2, 3],[2, 3, 4, 3, 4, 5],[4, 5, 6, 5, 6, 7],[6, 7, 0, 7, 0, 1],[0, 2, 6, 2, 6, 4],[1, 3, 7, 3, 7, 5]];var 属性 = []for(let side=0; side 

创建缓冲区并定义顶点属性的通用数组:

var buffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, 缓冲区);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes), gl.STATIC_DRAW);var coords = gl.getAttribLocation(shaderProgram, "coords");gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, 0);gl.enableVertexAttribArray(coords);var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 3);gl.enableVertexAttribArray(colorsLocation);var normalLocation = gl.getAttribLocation(shaderProgram, "normal");gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 7);gl.enableVertexAttribArray(normalLocation);

使用 .drawArrays 而不是 .drawElements 来绘制网格:

//gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);gl.drawArrays(gl.TRIANGLES, 0, vertexCount);

<小时>

查看示例,其中我将建议应用于您的代码:

var gl,着色器程序,顶点,矩阵 = mat4.create(),顶点数,索引计数,q = quat.create(),翻译 =[-3, 0, -10],比例 = [1,1,1],枢轴 = [0,0,0];翻译2 = [0, 0, -8],scale2 = [3,3,3],枢轴2 = [1,1,1]initGL();创建着色器();创建顶点();画();函数 initGL() {var canvas = document.getElementById("canvas");gl = canvas.getContext("webgl");gl.启用(gl.DEPTH_TEST);gl.viewport(0, 0, canvas.width, canvas.height);gl.clearColor(1, 1, 1, 1);}函数 createShaders() {var vertexShader = getShader(gl, "shader-vs");var fragmentShader = getShader(gl, "shader-fs");shaderProgram = gl.createProgram();gl.attachShader(shaderProgram, vertexShader);gl.attachShader(shaderProgram, fragmentShader);gl.linkProgram(shaderProgram);gl.useProgram(shaderProgram);}函数 createVertices() {顶点 = [[-1, -1, -1, 1, 0, 0, 1],//0[ 1, -1, -1, 1, 1, 0, 1],//1[-1, 1, -1, 0, 1, 1, 1],//2[ 1, 1, -1, 0, 0, 1, 1],//3[-1, 1, 1, 1, 0.5, 0, 1],//4[1, 1, 1, 0.5, 1, 1, 1],//5[-1, -1, 1, 1, 0, 0.5, 1],//6[1, -1, 1, 0.5, 0, 1, 1],//7];var 法线 = [[0, 0, 1], [0, 1, 0], [0, 0, -1],[0, -1, 0], [-1, 0, 0], [1, 0, 0] ];变量索引 = [[0, 1, 2, 1, 2, 3],[2, 3, 4, 3, 4, 5],[4, 5, 6, 5, 6, 7],[6, 7, 0, 7, 0, 1],[0, 2, 6, 2, 6, 4],[1, 3, 7, 3, 7, 5]];var 属性 = []for(let side=0; side 

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script><script id="shader-vs" type="x-shader/x-vertex">属性 vec4 坐标;统一 mat4 变换矩阵;属性 vec3 正常;属性 vec4 颜色;统一的 vec3 lightColor;统一 vec3 lightDirection;变化的 vec4 变化的颜色;统一 mat4 透视矩阵;无效主(无效){vec3 规范 = 规范化(正常);vec3 ld = 标准化(lightDirection);float dotProduct = max(dot(norm, ld), 0.0);vec3 vertexColor = lightColor * colors.rgb * dotProduct;变化颜色 = vec4(vertexColor, 1);gl_Position = 透视矩阵 * 变换矩阵 * 坐标;}<script id="shader-fs" type="x-shader/x-fragment">精密中等浮点数;统一的 vec4 颜色;变化的 vec4 变化的颜色;无效主(无效){gl_FragColor = 变化的颜色;}</script>

How can I add a direction light to a transforming cube in webGL.

I know it requires normals and i've add them in the snippet (i've commented them out)

It will also require some math in the vertex shader. unfortunatly this code doesnt work when i uncomment.

attribute vec4 coords;
  uniform mat4 transformMatrix;
  attribute vec3 normal;
  attribute vec4 colors;
  uniform vec3 lightColor;
  uniform vec3 lightDirection;
  varying vec4 varyingColors;
  uniform mat4 perspectiveMatrix;
  void main(void) {
    vec3 norm = normalize(normal);
    vec3 ld = normalize(lightDirection);
    float dotProduct = max(dot(norm, ld), 0.0);
    vec3 vertexColor = lightColor * colors * dotProduct;
    varyingColors = vec4(vertexColor, 1);
    gl_Position = perspectiveMatrix * transformMatrix  * coords;
  }

var gl,
    shaderProgram,
    vertices,
    matrix = mat4.create(),
    vertexCount,
    indexCount,
    q = quat.create(),
    translate =[-3, 0, -10],
    scale = [1,1,1],
    pivot = [0,0,0];
    
    translate2 = [0, 0, -8],
    scale2 = [3,3,3],
    pivot2 = [1,1,1]


initGL();
createShaders();
createVertices();
createIndices();
draw();

function initGL() {
  var canvas = document.getElementById("canvas");
  gl = canvas.getContext("webgl");
  gl.enable(gl.DEPTH_TEST);
  gl.viewport(0, 0, canvas.width, canvas.height);
  gl.clearColor(1, 1, 1, 1);
}

function createShaders() {
  var vertexShader = getShader(gl, "shader-vs");
  var fragmentShader = getShader(gl, "shader-fs");

  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
}

function createVertices() {
  vertices = [
    -1, -1, -1,     1, 0, 0, 1,     // 0
     1, -1, -1,     1, 1, 0, 1,     // 1
    -1,  1, -1,     0, 1, 1, 1,     // 2
     1,  1, -1,     0, 0, 1, 1,     // 3
    -1,  1,  1,     1, 0.5, 0, 1,   // 4
     1,  1,  1,     0.5, 1, 1, 1,   // 5
    -1, -1,  1,     1, 0, 0.5, 1,   // 6
     1, -1,  1,     0.5, 0, 1, 1,   // 7
  ];

  vertexCount = vertices.length / 7;

  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

  var coords = gl.getAttribLocation(shaderProgram, "coords");
  gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, 0);
  gl.enableVertexAttribArray(coords); 


/**
var normals = [
    0, 0, 1,   0, 0, 1,    0, 0, 1,   0, 0, 1,
    0, 1, 0,   0, 1, 0,    0, 1, 0,   0, 1, 0,
    0, 0, -1,  0, 0, -1,   0, 0, -1,  0, 0, -1,
    0, -1, 0,  0, -1, 0,   0, -1, 0,  0, -1, 0,
    -1, 0, 0,  -1, 0, 0,   -1, 0, 0,  -1, 0, 0,
    1, 0, 0,   1, 0, 0,    1, 0, 0,   1, 0, 0
  ];
  
  var normalBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
  
  var normalLocation = gl.getAttribLocation(shaderProgram, "normal");
  gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(normalLocation);  
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  
  var lightColor = gl.getUniformLocation(shaderProgram, "lightColor");
  gl.uniform3f(lightColor, 1, 1, 1);
  
  var lightDirection = gl.getUniformLocation(shaderProgram, "lightDirection");
  gl.uniform3f(lightDirection, 0.5, 1, 0);
 */


  var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");
  gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 7, Float32Array.BYTES_PER_ELEMENT * 3);

  gl.enableVertexAttribArray(colorsLocation);
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  

  var perspectiveMatrix = mat4.create();
  mat4.perspective(perspectiveMatrix, 1, canvas.width / canvas.height, 0.1, 11);
  var perspectiveLoc = gl.getUniformLocation(shaderProgram, "perspectiveMatrix");
  gl.uniformMatrix4fv(perspectiveLoc, false, perspectiveMatrix);

}

function createIndices() {
  var indices = [
    0, 1, 2,   1, 2, 3,
    2, 3, 4,   3, 4, 5,
    4, 5, 6,   5, 6, 7,
    6, 7, 0,   7, 0, 1,
    0, 2, 6,   2, 6, 4,
    1, 3, 7,   3, 7, 5
  ];
  indexCount = indices.length;

  var indexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);


}

function draw(timeMs) {
  requestAnimationFrame(draw);

  let interval = timeMs / 3000
  let t = interval - Math.floor(interval); 

  let trans_t = vec3.lerp([], translate, translate2, t);
  let scale_t = vec3.lerp([], scale, scale2, t);
  let pivot_t = vec3.lerp([], pivot, pivot2, t);

  mat4.fromRotationTranslationScaleOrigin(matrix, q, trans_t, scale_t, pivot_t);

  var transformMatrix = gl.getUniformLocation(shaderProgram, "transformMatrix");
  gl.uniformMatrix4fv(transformMatrix, false, matrix);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);
}


  /*
   * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
   */
  function getShader(gl, id) {
    var shaderScript, theSource, currentChild, shader;

    shaderScript = document.getElementById(id);

    if (!shaderScript) {
      return null;
    }

    theSource = "";
    currentChild = shaderScript.firstChild;

    while (currentChild) {
      if (currentChild.nodeType == currentChild.TEXT_NODE) {
        theSource += currentChild.textContent;
      }

      currentChild = currentChild.nextSibling;
    }
    if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
      // Unknown shader type
      return null;
    }
    gl.shaderSource(shader, theSource);

// Compile the shader program
    gl.compileShader(shader);

// See if it compiled successfully
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
      return null;
    }

    return shader;
  }

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 coords;
attribute float pointSize;
uniform mat4 transformMatrix;
attribute vec4 colors;
varying vec4 varyingColors;
uniform mat4 perspectiveMatrix;
void main(void) {
  gl_Position = perspectiveMatrix * transformMatrix  * coords;
  gl_PointSize = pointSize;
  varyingColors = colors;
}
</script>

<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 color;
varying vec4 varyingColors;
void main(void) {
  gl_FragColor = varyingColors;
}
</script>

<canvas id="canvas" width="600" height="600"></canvas>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>

解决方案

There is an issue in your shader code:

vec3 vertexColor = lightColor * colors * dotProduct;

The type of color is vec4, but the type of vertexColor is vec3, so it has to be:

vec3 vertexColor = lightColor * colors.rgb * dotProduct;

You can't assigne a variable of type vec4 to a variable of type vec3.


When gl.vertexAttribPointer is called, then the proper vertex buffer has to be bound before. At the point where you specify the colorsLocation attribute, the buffer with the normals is bound, rather than than the buffer with the vertices and colors (vertices).


A vertex coordinate and its attributes are tuples. If a vertex coordinate is used twice (or 3 times for in three sides) and each time it is associated to a different normal vector, then the coordinate has to be "duplicated". Each vertex coordinate is associated to exactly 1 normal vector.
See Rendering meshes with multiple indices.

Imagine a 3 dimensional vertex coordinate and a 3 dimensional normal vector as 1, but 6 dimensional attribute.

Create a linearised array of attributes:

vertices = [
  [-1, -1, -1,     1, 0, 0, 1],     // 0
  [ 1, -1, -1,     1, 1, 0, 1],     // 1
  [-1,  1, -1,     0, 1, 1, 1],     // 2
  [ 1,  1, -1,     0, 0, 1, 1],     // 3
  [-1,  1,  1,     1, 0.5, 0, 1],   // 4
  [1,  1,  1,      0.5, 1, 1, 1],   // 5
  [-1, -1,  1,     1, 0, 0.5, 1],   // 6
  [1, -1,  1,      0.5, 0, 1, 1],   // 7
];

var normals = [
  [0, 0, 1], [0, 1, 0], [0, 0, -1],
  [0, -1, 0], [-1, 0, 0], [1, 0, 0] ];

var indices = [
  [0, 1, 2,   1, 2, 3],
  [2, 3, 4,   3, 4, 5],
  [4, 5, 6,   5, 6, 7],
  [6, 7, 0,   7, 0, 1],
  [0, 2, 6,   2, 6, 4],
  [1, 3, 7,   3, 7, 5]
];

var attributes = []
for(let side=0; side < indices.length; ++side) {
    for(let vi=0; vi < indices[side].length; ++vi) {
        attributes.push(...vertices[indices[side][vi]]);
        attributes.push(...normals[side]);
    }
}

vertexCount = attributes.length / 10;

Create the buffer and define the generic arrays of vertex attributes:

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes), gl.STATIC_DRAW);

var coords = gl.getAttribLocation(shaderProgram, "coords");
gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, 0);
gl.enableVertexAttribArray(coords); 

var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");
gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 3);
gl.enableVertexAttribArray(colorsLocation);

var normalLocation = gl.getAttribLocation(shaderProgram, "normal");
gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 7);
gl.enableVertexAttribArray(normalLocation);  

Use .drawArrays rather than .drawElements to draw the mesh:

//gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);
gl.drawArrays(gl.TRIANGLES, 0, vertexCount);


See the example, where I applied the suggestions to your code:

var gl,
    shaderProgram,
    vertices,
    matrix = mat4.create(),
    vertexCount,
    indexCount,
    q = quat.create(),
    translate =[-3, 0, -10],
    scale = [1,1,1],
    pivot = [0,0,0];
    
    translate2 = [0, 0, -8],
    scale2 = [3,3,3],
    pivot2 = [1,1,1]


initGL();
createShaders();
createVertices();
draw();

function initGL() {
  var canvas = document.getElementById("canvas");
  gl = canvas.getContext("webgl");
  gl.enable(gl.DEPTH_TEST);
  gl.viewport(0, 0, canvas.width, canvas.height);
  gl.clearColor(1, 1, 1, 1);
}

function createShaders() {
  var vertexShader = getShader(gl, "shader-vs");
  var fragmentShader = getShader(gl, "shader-fs");

  shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
}

function createVertices() {
vertices = [
  [-1, -1, -1,     1, 0, 0, 1],     // 0
  [ 1, -1, -1,     1, 1, 0, 1],     // 1
  [-1,  1, -1,     0, 1, 1, 1],     // 2
  [ 1,  1, -1,     0, 0, 1, 1],     // 3
  [-1,  1,  1,     1, 0.5, 0, 1],   // 4
  [1,  1,  1,      0.5, 1, 1, 1],   // 5
  [-1, -1,  1,     1, 0, 0.5, 1],   // 6
  [1, -1,  1,      0.5, 0, 1, 1],   // 7
];

var normals = [
  [0, 0, 1], [0, 1, 0], [0, 0, -1],
  [0, -1, 0], [-1, 0, 0], [1, 0, 0] ];

var indices = [
  [0, 1, 2,   1, 2, 3],
  [2, 3, 4,   3, 4, 5],
  [4, 5, 6,   5, 6, 7],
  [6, 7, 0,   7, 0, 1],
  [0, 2, 6,   2, 6, 4],
  [1, 3, 7,   3, 7, 5]
];

var attributes = []
for(let side=0; side < indices.length; ++side) {
    for(let vi=0; vi < indices[side].length; ++vi) {
        attributes.push(...vertices[indices[side][vi]]);
        attributes.push(...normals[side]);
    }
}

  vertexCount = attributes.length / 10;

  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes), gl.STATIC_DRAW);

  var coords = gl.getAttribLocation(shaderProgram, "coords");
  gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, 0);
  gl.enableVertexAttribArray(coords); 

  var colorsLocation = gl.getAttribLocation(shaderProgram, "colors");
  gl.vertexAttribPointer(colorsLocation, 4, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 3);
  gl.enableVertexAttribArray(colorsLocation);

  var normalLocation = gl.getAttribLocation(shaderProgram, "normal");
  gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, Float32Array.BYTES_PER_ELEMENT * 10, Float32Array.BYTES_PER_ELEMENT * 7);
  gl.enableVertexAttribArray(normalLocation);  
  
  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  
  var lightColor = gl.getUniformLocation(shaderProgram, "lightColor");
  gl.uniform3f(lightColor, 1, 1, 1);
  
  var lightDirection = gl.getUniformLocation(shaderProgram, "lightDirection");
  gl.uniform3f(lightDirection, 0.5, 0.5, -1);


  var perspectiveMatrix = mat4.create();
  mat4.perspective(perspectiveMatrix, 1, canvas.width / canvas.height, 0.1, 11);
  var perspectiveLoc = gl.getUniformLocation(shaderProgram, "perspectiveMatrix");
  gl.uniformMatrix4fv(perspectiveLoc, false, perspectiveMatrix);

}

function draw(timeMs) {
  requestAnimationFrame(draw);

  let interval = timeMs / 3000
  let t = interval - Math.floor(interval); 

  let trans_t = vec3.lerp([], translate, translate2, t);
  let scale_t = vec3.lerp([], scale, scale2, t);
  let pivot_t = vec3.lerp([], pivot, pivot2, t);

  mat4.fromRotationTranslationScaleOrigin(matrix, q, trans_t, scale_t, pivot_t);

  var transformMatrix = gl.getUniformLocation(shaderProgram, "transformMatrix");
  gl.uniformMatrix4fv(transformMatrix, false, matrix);
  gl.clear(gl.COLOR_BUFFER_BIT);

  //gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_BYTE, 0);
  gl.drawArrays(gl.TRIANGLES, 0, vertexCount);
}


  /*
   * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context
   */
  function getShader(gl, id) {
    var shaderScript, theSource, currentChild, shader;

    shaderScript = document.getElementById(id);

    if (!shaderScript) {
      return null;
    }

    theSource = "";
    currentChild = shaderScript.firstChild;

    while (currentChild) {
      if (currentChild.nodeType == currentChild.TEXT_NODE) {
        theSource += currentChild.textContent;
      }

      currentChild = currentChild.nextSibling;
    }
    if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
      // Unknown shader type
      return null;
    }
    gl.shaderSource(shader, theSource);

// Compile the shader program
    gl.compileShader(shader);

// See if it compiled successfully
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
      return null;
    }

    return shader;
  }

<canvas id="canvas" width="600" height="600"></canvas>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 coords;
uniform mat4 transformMatrix;
attribute vec3 normal;
attribute vec4 colors;
uniform vec3 lightColor;
uniform vec3 lightDirection;
varying vec4 varyingColors;
uniform mat4 perspectiveMatrix;
void main(void) {
    vec3 norm = normalize(normal);
    vec3 ld = normalize(lightDirection);
    float dotProduct = max(dot(norm, ld), 0.0);
    vec3 vertexColor = lightColor * colors.rgb * dotProduct;
    varyingColors = vec4(vertexColor, 1);
    gl_Position = perspectiveMatrix * transformMatrix  * coords;
}
</script>

<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 color;
varying vec4 varyingColors;
void main(void) {
  gl_FragColor = varyingColors;
}
</script>

这篇关于向 vanilla wegl 中的变换立方体添加定向光的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆