WebGL simple tutorial (Four): Color

1 Overview

On the tutorial "Easy Tutorial the WebGL (III): to draw a triangle (buffer object)" , the transfer of data objects through the use of a buffer (buffer object) to the vertex shader. So, if these data (data associated with the vertex, such as normals, colors, etc.) need to continue to transmit to the fragment shader how to do it?

Here, for example, for each vertex of the triangle is given a different color, a color rendering triangle. Before this time you need to use ( "WebGL Easy Tutorial (2): The transfer of data to the shader" ) introduced the varying variables.

2. Example: drawing a triangle

An improvement in the triangle drawing code (HelloTriangle.js) of:

// 顶点着色器程序
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' + // attribute variable
  'attribute vec4 a_Color;\n' +
  'varying vec4 v_Color;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
  '  v_Color = a_Color;\n' +
  '}\n';

// 片元着色器程序
var FSHADER_SOURCE = 
  'precision mediump float;\n' +
  'varying vec4 v_Color;\n' +
  'void main() {\n' +
  '  gl_FragColor = v_Color;\n' +
  '}\n';

function main() {
  // 获取 <canvas> 元素
  var canvas = document.getElementById('webgl');

  // 获取WebGL渲染上下文
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // 初始化着色器
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // 设置顶点位置
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }

  // 指定清空<canvas>的颜色
  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // 清空<canvas>
  gl.clear(gl.COLOR_BUFFER_BIT);

  // 绘制三角形
  gl.drawArrays(gl.TRIANGLES, 0, n);
}

function initVertexBuffers(gl) {
  // 顶点坐标和颜色
  var verticesColors = new Float32Array([    
     0.0,  0.5,  1.0,  0.0,  0.0, 
    -0.5, -0.5,  0.0,  1.0,  0.0, 
     0.5, -0.5,  0.0,  0.0,  1.0, 
  ]);

  //
  var n = 3; // 点的个数
  var FSIZE = verticesColors.BYTES_PER_ELEMENT;   //数组中每个元素的字节数

  // 创建缓冲区对象
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  // 将缓冲区对象绑定到目标
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // 向缓冲区对象写入数据
  gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

  //获取着色器中attribute变量a_Position的地址 
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  // 将缓冲区对象分配给a_Position变量
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5*FSIZE, 0);

  // 连接a_Position变量与分配给它的缓冲区对象
  gl.enableVertexAttribArray(a_Position);

  //获取着色器中attribute变量a_Color的地址 
  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
  if(a_Color < 0) {
    console.log('Failed to get the storage location of a_Color');
    return -1;
  }
  // 将缓冲区对象分配给a_Color变量
  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
  // 连接a_Color变量与分配给它的缓冲区对象
  gl.enableVertexAttribArray(a_Color);  

  // 解除绑定
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  return n;
}

1) organization of data

Similar to the previous example, data is still transmitted through the buffer zone to the vertex shader. In the vertex shader, attribute defines two variables, the position and color information representing:

// 顶点着色器程序
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' + // attribute variable
  'attribute vec4 a_Color;\n' +
…
  '}\n';

This means that the data is transmitted to the two vertex shader. The approach taken here is still the write-once and for all positions of the data to the color buffer and the vertex shader incoming batches:

  // 创建缓冲区对象
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

// 将缓冲区对象绑定到目标
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // 向缓冲区对象写入数据
  gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

  //获取着色器中attribute变量a_Position的地址 
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  // 将缓冲区对象分配给a_Position变量
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5*FSIZE, 0);

  // 连接a_Position变量与分配给它的缓冲区对象
  gl.enableVertexAttribArray(a_Position);

  //获取着色器中attribute变量a_Color的地址 
  var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
  if(a_Color < 0) {
    console.log('Failed to get the storage location of a_Color');
    return -1;
  }
  // 将缓冲区对象分配给a_Color变量
  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
  // 连接a_Color变量与分配给它的缓冲区对象
  gl.enableVertexAttribArray(a_Color);  

You can see to create a buffer object, bind to the target buffer object, data is written to the buffer object These three steps are the same. However, attribute variables and distribution attribute variable connection two two steps separately. The key point is that gl.vertexAttribPointer () function. Before use the default values ​​are used for this function, and where the step by setting the offset value, respectively, different buffer access the data.

By gl.vertexAttribPointer () function definition can know, is transmitted to the data buffer 2 (size) and position data 3 (size) of the color data, the stepper parameters are stride 5 (size). First time position data is transferred from the initial position, the offset is 0; when the color data transfer requires a second data offset of the first position, so offfset is 2 (size).

2) varying variables

Before tutorial ( : "transmit data to the shader WebGL Easy Tutorial ()" mentioned in the data can be transmitted to the fragment shader to impart color to render the scene). But here it passes through the data buffer to the vertex shader. Thus, where a vertex shader and fragment shader, each defining a same varying variables:

// 顶点着色器程序
var VSHADER_SOURCE =
  …
  'varying vec4 v_Color;\n' +
  'void main() {\n' +
  …
  '  v_Color = a_Color;\n' +
  '}\n';

// 片元着色器程序
var FSHADER_SOURCE = 
  …
  'varying vec4 v_Color;\n' +
  'void main() {\n' +
  '  gl_FragColor = v_Color;\n' +
  '}\n';

A variable is a variable varying variables expressed, its function is to transfer data from the vertex shader to the fragment shader. In the main function of the vertex shader, buffer object from the acquired attribute variable a_Color varying variables assigned to predefined v_Color; while in another fragment shader defines a varying variables of the same type with the same name v_Color, then vertices shader value of the variable is automatically passed to the fragment shader. Finally, the main function of the fragment shader to gl_FragColor the value passed in the final result is obtained. Which diagram is as follows:

3. Results

The final results are as follows, obtained eventually find a smooth transition of color, three angle of each red, green, and blue color triangle:

4. Understand

1) Assembly and graphics rasterization

Under further reflection, though here it is given to each vertex color values, but why triangular surfaces are given a color, and a smooth transition effect? In fact, the data transfer details are omitted here between the vertex shader and fragment shader - and assembling graphics rasterization.

Process dots line, the line composed of the surface, the basic pattern of isolated dots (primitive) is the pattern assembly. Assembling a data pattern is input vertex shader gl_Position values ​​obtained, determined by the first parameter value () is assembled into what gl.drawArrays primitives. In this example, vertex shader tells WebGL system, prepared three points, the image WebGL assembly, which is assembled into a triangle.

Pattern known assembly is not enough, the theoretical triangle is continuous pattern, and general graphics display device is a discrete sheet element (pixel). Images into fragments, is the process of rasterization.

And the assembly diagram of a graphics rasterizer as follows:

Interpolation process 2)

When the second code sample Detailed mentioned vertex shader and fragment shader are defined the same varying variables v_Color, the data will be passed from the vertex shader to the fragment shader. But in fact, although both of the same name, but not the same thing. In the vertex shader, the variable is associated with varying values ​​of the vertices, after the pattern assembly and rasterization, fragment shader varying variables is the value associated with the fragments. Then, this value is obtained through an interpolation process.

In this example, three vertices given to three different color values. WebGL to plug the color value of each sheet element (pixel) of a triangle according to the color values ​​of three vertices, and passed to the fragment shader. The so-called interpolation process, one can imagine a gradual ribbon, aware of the beginning and ending of the colors, obtaining any position intermediate color.

5. Reference

Originally part of the code and illustrations from "WebGL Programming Guide," the source link: https://share.weiyun.com/5VjlUKo , password: sw0x2x. Follow-up will continue to update the contents of this shared directory.

Guess you like

Origin www.cnblogs.com/charlee44/p/11519697.html