关于javascript:图形学之WebGL实现3D效果-纹理的使用

36次阅读

共计 4526 个字符,预计需要花费 12 分钟才能阅读完成。

背景

本篇收录于《前端读书会》专栏

上文介绍了纹理相干的内容, 并应用 WebGL 进行了 2d 的实现, 明天连续上节课的内容对于纹理的 3D 实现 也算是汲取了 MDN-Tutorial 的模式, 感觉这样的学习轨道 也算是初衷 ( 每次简明扼要的讲图形学的实践我怕我和你都保持不上来 ) 目前来说最好的形式了,对于 WebGL 的学习还是图形学的学习都能有一个意识。话不多说开始明天的内容(大部分是 code 的解说 尽可能疾速过完一些根底的 API… 第一步成为一个 API 工程师)

上文介绍了纹理相干的内容, 有须要能够参考上文

本篇纲要

  1. 2D 与 3D 的区别? 绘制思路?
  2. coding (WebGL 中简略应用纹理)

coding 局部引入 webgl-utils(方面一些 useprogram,linkProgram 的简写 无太大魔力)&martix(矩阵的一些生成 / 计算..)工具类库

1.2d 与 3d 的区别

首先咱们都晓得 2D 只是一个立体 3D 能够了解为是 6 个立体, 那么本篇文章最次要解决如何给增加 5 个立体就好(当然增加会随同着一些问题, 没关系 一步步的来)

本篇会对于上文的一些反馈进行改过 例如 code 正文太少。。ok 我尽量多写点

WebGl coding 首先回顾一下步骤

  1. shader
  2. 创立 program
  3. 解决坐标还有纹理相干
  4. 获取并绑定坐标信息
  5. 绘制 draw

看着是如此简略 那么接下来咱们一起来写一下

coding

coding 开始之前先看看成果

缺一个 gif 图 今天找个有电脑的中央补充一下。

1. shader

有敌人反馈 shader 局部要关照老手, 那么我逐行加下正文介绍下。当然更多细节信息还是得去看看相干材料呢。我讲的不好(– 次要是懒癌患者)

// vertex shader  
// attribute 变量 只能作用于顶点着色器 vec4 是矢量 a_position 一个变量名
attribute vec4 a_position;
// attribute 变量 只能作用于顶点着色器 vec4 是矢量 a_position 一个变量名
attribute vec2 a_texcoord;
// uniform 变量(全局) 能够在顶点和片元应用(如果俩个着色命名同名 可进行共享) mat4 是矩阵 u_matrix 变量名
uniform mat4 u_matrix;
// varying 变量(全局) 目标就是为了给片元传输数据 vec2 矢量 v_texcoord 变量名
varying vec2 v_texcoord;
// main 相似主执行函数 然而是必须的 C/C++ 用法相似
void main() {
    // gl_Position 顶点坐标
   gl_Position = u_matrix * a_position;
   // 将纹理坐标传给片断着色器
   v_texcoord = a_texcoord;
}

// fragment shader 
// 精度限定  mediump 中度精度 float 数据类型 对了 SL 语言中是辨别整型和浮点型的哦~
precision mediump float;
// varying 变量(全局) 接管传输过去的数据 vec2 矢量 v_texcoord 变量名
varying vec2 v_texcoord;
// uniform 变量(只读 全局)  sampler2D 纹理 u_texture 变量名
uniform sampler2D u_texture;
// 主执行函数
void main() {
   // gl_FragColor 色彩信息  此处是纹理  texture2D 是取样器纹理 v_texcoord 纹理坐标 看 js 代码交叉了解
   gl_FragColor = texture2D(u_texture, v_texcoord);
}

我这个正文写的 我都拜服。哈哈 不懂记得留言。我都让你们问, 你们也不问。要晓得不会就问没什么不好意思的 学会了那是本人的 弱小本人升职加薪 加油

2. 创立 program

// 用到了 webgl-Utils 其实就是 useVertex 和 useFragment 而后 linkProgram...
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);

3. 解决坐标还有纹理相干

// 顶点坐标 产生了变换 6 个面 
var positions = new Float32Array(
    [
    -0.5, -0.5,  -0.5,
    -0.5,  0.5,  -0.5,
     0.5, -0.5,  -0.5,
    -0.5,  0.5,  -0.5,
     0.5,  0.5,  -0.5,
     0.5, -0.5,  -0.5,

    -0.5, -0.5,   0.5,
     0.5, -0.5,   0.5,
    -0.5,  0.5,   0.5,
    -0.5,  0.5,   0.5,
     0.5, -0.5,   0.5,
     0.5,  0.5,   0.5,

    -0.5,   0.5, -0.5,
    -0.5,   0.5,  0.5,
     0.5,   0.5, -0.5,
    -0.5,   0.5,  0.5,
     0.5,   0.5,  0.5,
     0.5,   0.5, -0.5,

    -0.5,  -0.5, -0.5,
     0.5,  -0.5, -0.5,
    -0.5,  -0.5,  0.5,
    -0.5,  -0.5,  0.5,
     0.5,  -0.5, -0.5,
     0.5,  -0.5,  0.5,

    -0.5,  -0.5, -0.5,
    -0.5,  -0.5,  0.5,
    -0.5,   0.5, -0.5,
    -0.5,  -0.5,  0.5,
    -0.5,   0.5,  0.5,
    -0.5,   0.5, -0.5,

     0.5,  -0.5, -0.5,
     0.5,   0.5, -0.5,
     0.5,  -0.5,  0.5,
     0.5,  -0.5,  0.5,
     0.5,   0.5, -0.5,
     0.5,   0.5,  0.5,

    ]);
// 解决图片跨域问题  当然形式很多你也能够绘制 canvas2d 而后创立纹理 canvas 在规范上反对了图片跨域 有趣味能够查查
function requestCORSIfNotSameOrigin(img, url) {if ((new URL(url, window.location.href)).origin !== window.location.origin) {img.crossOrigin = "";}
}
// 加载图片 并在 load 实现绑定纹理
function loadImageAndCreateTextureInfo(url) {var tex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, tex);
   
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
                  new Uint8Array([0, 0, 255, 255]));

    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);

    var textureInfo = {
      width: 1,  
      height: 1,
      texture: tex,
    };
    var img = new Image();
    img.addEventListener('load', function() {
      textureInfo.width = img.width;
      textureInfo.height = img.height;

      gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture);
      // 调用 texImage2D() 把曾经加载的图片图形数据写到纹理
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
    });
    requestCORSIfNotSameOrigin(img, url);
    img.src = url;

    return textureInfo;
  }
  var texInfo = loadImageAndCreateTextureInfo('https://webglfundamentals.org/webgl/resources/leaves.jpg');

4. 获取并绑定坐标信息

  var positionLocation = gl.getAttribLocation(program, "a_position");
  var texcoordLocation = gl.getAttribLocation(program, "a_texcoord");

  var matrixLocation = gl.getUniformLocation(program, "u_matrix");
  var textureLocation = gl.getUniformLocation(program, "u_texture");

  var positionBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  setGeometry(gl);

  var texcoordBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  setTexcoords(gl);

  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
                new Uint8Array([0, 0, 255, 255]));

5. 应用 program 并提供 buffer 取数据 而后绘制

gl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset);

// 启用 texcoord 属性
gl.enableVertexAttribArray(texcoordLocation);

// 绑定 texcoord buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);

....
gl.drawArrays(gl.TRIANGLES, 0, 6 * 6);

ok, 成果就这样实现了. 为了大家的练习, 阐明一下须要留神的中央是下面的代码 纹理是采纳了一个纹理 如果要改多个图片能够采取多个纹理。也能够合并成一个纹理 通过坐标信息进行调节。

全副代码请去 github 下载并应用

最初

最初强烈心愿大家学习相干理论知识; 实践可能日常用到的中央很少, 然而它能决定你走多远。(有的人问难怎么办, 勤于练习吧), 写作速度呢 该专栏我减速(一周 1 - 2 篇) 其余专栏(1 篇) 计算机图形学相干的基础知识都会带一遍。而后后续次要写数据可视化方向。

下一篇写点什么呢? 集体筹备把 MDN-Tutorial 局部的内容结个尾。而后开始正式的可视化环节(能够介绍几个大家罕用的库 2D 3D 的都能够, 大家看看有什么好用的库须要我一起过一下的呢)。或者大家提提意见!

正文完
 0