Skip to main content

Varying Variables and Interpolation_WebGL Notes 7

Free2016-01-01#JS#WebGL#webgl varying#webgl interpolation#webgl interpolate#webgl内插

Using varying variables can achieve gradient effects, and can also interpolate various data that cannot be obtained

Preface

In [previous notes](/articles/7 种 webgl 图元-webgl 笔记 6/), we learned about 7 primitives, can draw different things by changing parameters, but specific details were not explained clearly, this starts from how shaders work, and varying variables as data channel between vertex shader and fragment shader, also must be mentioned

I. Varying Variables

Previously explained 2 types of shader variables: attribute variables, uniform variables, and varying variables are the last type of shader variable, slightly more complex than the first 2, because there's interpolation process

Varying variables' function is to pass values from vertex shader to fragment shader, varying variables can only be float type, as long as same-named varying variable is also declared in fragment shader, value assigned to this variable in vertex shader will automatically be passed to fragment shader (before assigning to same-named varying variable in fragment shader, there's interpolation process, 1.0 passed over may not be 1.0)

Note: varying variable values in vertex shader are not directly passed, will first undergo interpolation, interpolation is like tweening animation

II. Interpolation

Interpolation, missing data requires interpolation, for example want to connect a series of scattered points into smooth curve, many points missing between adjacent known points, at this point need to fill missing data through interpolation, finally all points on smooth curve except known points are obtained through interpolation

For example Photoshop's custom gradients, we only need to set colors of several points to automatically generate entire gradient band, colors between these several points are all obtained through built-in interpolation algorithm

Interpolation process performed before varying variable values are passed to fragment shader is called interpolation, similarly, we can also use interpolation to generate gradients

III. Gradient Triangle

As long as same-named varying variable as vertex shader is declared in fragment shader, values will automatically be passed over (of course, there's interpolation process)

1. Shader Source Programs

Declare same-named varying variable in fragment shader, specifically as follows:

// Vertex shader source program
var vsSrc = 'attribute vec4 a_Position;' +
    'attribute vec4 a_Color;' +
    'varying vec4 v_Color;' +       // Declare varying variable
    'void main() {' +
    'gl_Position = a_Position;' +   // Set coordinates
    'gl_PointSize = 7.0;' +         // Set size
    'v_Color = a_Color;' +          // Assign value to varying variable
'}';
// Fragment shader source program
//!!! Need to declare floating point precision, otherwise error No precision specified for (float)
var fsSrc = 'precision mediump float;' +
    'varying vec4 v_Color;' +   // Declare same-named varying variable
    'void main() {' +
    'gl_FragColor = v_Color;' + // Set color
'}';

Note: Cannot directly assign values to varying variables, need to use attribute variables to accept external values, then assign to varying variables inside vertex shader

2. Solid Color Triangle vs Gradient Triangle

Key is whether three vertex colors are consistent, because actual process is:

  1. Read vertex information (coordinates, colors, etc.)

Execute vertex shader, read related data of 1 vertex

  1. Graphics assembly (draw points or lines or triangles)

Assemble isolated vertex coordinates into geometric shapes, shape category determined by first parameter of gl.drawArrays, for example gl.POINTS, gl.TRIANGLES

  1. Rasterization (determine which pixels need coloring)

Convert assembled geometric shapes into fragments, convert vector geometric shapes into rasterized fragments (pixels)

  1. Execute fragment shader (coloring)

Color each fragment

  1. Return to first step, exit when finished reading, if not finished read next vertex and do it again

So vertex shader is executed per vertex, fragment shader is executed per fragment, like a double loop, outer loop traverses vertices, inner loop traverses fragments. Above process shown in diagram below:

[caption id="attachment_913" align="alignnone" width="773"]webgl-vertex-shader-execution webgl-vertex-shader-execution[/caption]

[caption id="attachment_914" align="alignnone" width="738"]webgl-varying webgl-varying[/caption]

In previous DEMOs colors were all hardcoded in fragment shader, for example gl_FragColor = vec4(1.0, 0.0, 1.0, 0.75), so all things drawn are solid colors, but more scientific way is to pass vertex colors into vertex shader, interpolate color of each fragment according to vertex colors. For example draw an isolated line segment, fragments between 2 same-color vertices are all that color after interpolation, fragments between 2 different-color vertices will have other colors after interpolation

3. Draw Gradient Triangle

Set 3 vertices to different colors, as follows:

var arrVtx = new Float32Array([
    // x, y, r, g, b
    -0.5, 0.5, 1.0, 0.0, 1.0, 1.0,  // Red
    0.5, 0.5, 0.0, 1.0, 0.0, 1.0,   // Green
    -0.5, -0.5, 0.0, 0.0, 1.0, 1.0  // Blue
]);
//...Vertex array written to buffer
// Draw points
gl.drawArrays(gl.POINTS, 0, arrVtx.length / 6);
setTimeout(function() {
    gl.clear(gl.COLOR_BUFFER_BIT);
    // Draw triangle
    gl.drawArrays(gl.TRIANGLES, 0, arrVtx.length / 6);
}, 2000);

We first draw 3 isolated points (red green blue), draw triangle after 2s, gradient triangle appears, this also shows setting gl_PointSize is only effective when drawing points, drawing triangles will automatically ignore this value

IV. DEMO

Complete examples containing above code, please view:

Set fragment color according to coordinates, verify fragment shader executes per fragment process

Note: Fragment shader's built-in variable gl_FragCoord stores fragment coordinate information (gl_FragCoord.x, gl_FragCoord.y), if can output, will discover fragment shader executes per vertex process, but API doesn't provide method to output information to console, we can verify by setting color according to fragment coordinates

V. Summary

Varying variables not only can achieve gradient effects, can also use it to interpolate various numerical values that cannot be obtained, such as fragment's world coordinates, fragment's coordinates in light source coordinate system, etc., very useful

We can now draw colored graphics, another characteristic related to color is texture mapping (texture mapping), this is content of next notes

References

  • "WebGL Programming Guide"

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment