1
头图

background

This article is included in the "Front-end Reading Club" column

The above introduced the content related to textures, and used WebGL to implement the 2D implementation.Today, the continuation of the content of the previous lesson is also considered to have absorbed the MDN-Tutorial mode for the 3D implementation of textures. I feel that this learning track is also considered the original intention ( Every time I talk about the theory of graphics, I'm afraid that you and I will not stick to it. ) It is the best way at present, and I can have an idea of learning WebGL or learning graphics. Not much to talk about starting today's content (most of the code explanations are as fast as possible to complete some basic APIs...the first step is to become an API engineer)

above introduces texture-related content, if necessary, please refer to

Outline of this article

  1. What is the difference between 2D and 3D? Drawing ideas?
  2. coding (Simple use of textures in WebGL)
The coding part introduces webgl-utils (some useprogram, linkProgram abbreviation does not have much magic) & martix (some matrix generation/calculation...) tool library

The difference between 1.2d and 3d

First of all, we all know that 2D is just a plane and 3D can be understood as 6 planes, so this article mainly solves how to add 5 planes (of course the addition will be accompanied by some problems, it doesn't matter step by step)

This article will correct some of the feedback above, such as too few code comments. . ok i try to write more

WebGl coding first review the steps

  1. shader
  2. Create program
  3. Processing coordinates and texture related
  4. Obtain and bind coordinate information
  5. Draw
It looks so simple, so let's write it together

coding

Look at the effect before coding

If a gif is missing, find a place with a computer tomorrow to add it.

image.png

image.png

1. shader
Some friends reported that the shader part should take care of novices, so I will add a comment line by line to introduce it. Of course, you still have to look at the relevant information for more details. I'm not good at speaking (-- mainly lazy cancer patients)
// 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);
}

I have written this comment, I admire it. Haha don't understand, remember to leave a message. I let you ask, but you don't ask. If you don’t know, just ask, there’s nothing embarrassing to learn, that’s your own strength, you

2. Create a program
// 用到了webgl-Utils 其实就是useVertex 和useFragment 然后linkProgram...
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-3d", "fragment-shader-3d"]);
3. Processing coordinates and texture related
// 顶点坐标 发生了变换 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. Obtain and bind coordinate information
  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. Use program and provide buffer to fetch data and then draw
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, the effect is achieved in this way. For your practice, please note that the above code texture uses one texture. If you want to change multiple images, you can use multiple textures. It can also be combined into one texture and adjusted by coordinate information.

all the code, please go to github to download and use

At last

Finally, I strongly hope that everyone learns relevant theoretical knowledge; theory may be used in very few places in daily life, but it can determine how far you go. (Some people ask what to do, practice hard), the writing speed of this column I will speed up (1-2 articles a week) other columns (1 article) basic knowledge related to computer graphics will be brought again. Then, I mainly write the data visualization direction in the follow-up.

What should I write in the next article? I personally end the contents of the 160f77fae67358 MDN-Tutorial Then start the formal visualization session (you can introduce a few commonly used libraries for 2D and 3D, let’s see if there are any useful libraries that I need to go through together). Or everyone to comment!


wlove
6.9k 声望1.8k 粉丝

wx:wywin2023