WebGL着色器-绘制函数图像

246 阅读2分钟

在WebGL中绘制函数图像是一项非常有趣且具有挑战性的任务。通过使用顶点着色器和片段着色器,你可以将数学函数直接可视化在WebGL画布上。下面是一个基本的入门指南,教你如何使用WebGL来绘制简单的函数图像。

1. 准备WebGL上下文

首先,你需要一个HTML文件和一个包含WebGL上下文的<canvas>元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebGL函数图像绘制</title>
</head>
<body>
    <canvas id="webgl-canvas" width="500" height="500"></canvas>
    <script src="shader.js"></script>
</body>
</html>

在这个HTML文件中,<canvas>元素用于渲染图像。接下来我们需要用JavaScript代码初始化WebGL上下文。

2. 初始化WebGL

shader.js文件中,我们首先初始化WebGL。

// 获取canvas元素
const canvas = document.getElementById('webgl-canvas');

// 获取WebGL上下文
const gl = canvas.getContext('webgl');

if (!gl) {
    console.log('无法获取WebGL上下文');
    throw new Error('WebGL不支持');
}

// 设置WebGL视口
gl.viewport(0, 0, canvas.width, canvas.height);

// 设置清屏颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

3. 编写顶点着色器

顶点着色器负责定义图形的几何形状。在这个例子中,我们将用简单的顶点位置来定义整个屏幕。

const vertexShaderSource = `
attribute vec4 a_Position;
void main() {
    gl_Position = a_Position;
}
`;

// 创建并编译顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

4. 编写片段着色器

片段着色器负责计算每个像素的颜色。在这个片段着色器中,我们可以定义一个函数,例如f(x) = sin(x),并用它来绘制图像。

const fragmentShaderSource = `
precision mediump float;

void main() {
    // 获取当前片段的坐标
    vec2 st = gl_FragCoord.xy / vec2(500.0, 500.0);

    // 将坐标转换到[-1, 1]范围
    float x = (st.x * 2.0) - 1.0;

    // 定义函数 y = sin(10.0 * x)
    float y = sin(10.0 * x);

    // 如果当前y坐标接近函数值,则设置为白色,否则为黑色
    if (abs(st.y - (y * 0.5 + 0.5)) < 0.01) {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    } else {
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }
}
`;

// 创建并编译片段着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

5. 创建着色器程序并绘制

将顶点和片段着色器链接到一个着色器程序中,并使用这个程序来绘制。

// 创建着色器程序
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

// 使用程序
gl.useProgram(shaderProgram);

// 定义一个覆盖整个画布的三角形
const vertices = new Float32Array([
    -1.0,  1.0,
    -1.0, -1.0,
     1.0,  1.0,
     1.0, -1.0,
]);

// 创建缓冲区
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 获取a_Position属性位置
const a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);

// 绘制图像
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

6. 完整代码

将上述代码整合在一起,你就可以在WebGL画布上绘制出函数图像。此代码绘制的是y = sin(10 * x)的图像。

7. 进阶

你可以尝试修改片段着色器中的函数,或者添加用户交互功能,来实时调整函数的形状和参数。此外,还可以实现更复杂的函数,比如多变量函数,或者使用颜色渐变来表示函数值的大小。

通过这些步骤,你可以初步掌握如何使用WebGL绘制函数图像,并为更复杂的图像渲染打下基础。