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

背景

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

上文介绍了纹理相干的内容,并应用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的都能够,大家看看有什么好用的库须要我一起过一下的呢)。或者大家提提意见!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理