跟随chatgpt学习如何使用GLSL进行简单的图形渲染

1. 准备一个HTML文件:创建一个新的HTML文件,将 HTML 文件命名为 `index.html`,并添加一个用于显示图形的<canvas>元素。

复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Simple WebGL Rendering</title>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100%; }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script src="script.js"></script>
</body>
</html>

2. 创建JavaScript文件:创建一个名为`script.js`的 JavaScript 文件来处理图形的渲染逻辑。

复制代码
// 获取canvas元素
const canvas = document.getElementById("canvas");

// 创建WebGL上下文
const gl = canvas.getContext("webgl");

// 定义顶点着色器代码
const vertexShaderSource = `
    attribute vec2 position;
    
    void main() {
        gl_Position = vec4(position, 0.0, 1.0);
    }
`;

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

// 检查顶点着色器是否编译成功
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    console.error("Vertex shader compilation error:", gl.getShaderInfoLog(vertexShader));
}

// 定义片段着色器代码
const fragmentShaderSource = `
    precision mediump float;
    
    void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
`;

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

// 检查片段着色器是否编译成功
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
    console.error("Fragment shader compilation error:", gl.getShaderInfoLog(fragmentShader));
}

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

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

// 渲染图形
const vertices = [-0.5, -0.5,
    0.5, -0.5,
    0.0, 0.5
];

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

const positionAttributeLocation = gl.getAttribLocation(shaderProgram, "position");
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);

运行成功页面

一个简单的glsl小实验成功了,不过我想要这个三角形动起来。

修改后的script代码如下

复制代码
// 获取画布元素和 WebGL 上下文
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");

// 顶点着色器代码
const vertexShaderSource = `
    attribute vec2 a_position;
    uniform vec2 u_translation;

    void main() {
        gl_Position = vec4(a_position + u_translation, 0, 1);
    }
`;

// 片段着色器代码
const fragmentShaderSource = `
    precision mediump float;

    void main() {
        gl_FragColor = vec4(1, 0, 0, 1);
    }
`;

// 创建着色器程序
var program = createProgram(gl, vertexShaderSource, fragmentShaderSource);

// 获取顶点位置 attribute 的位置
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");

// 创建并绑定顶点缓冲区
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

// 定义一个简单的三角形顶点位置数组
var positions = [
    0, 0,
    -0.5, -0.5,
    0.5, -0.5
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// 设置顶点属性指针
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// 清空画布
gl.clearColor(0, 0, 0, 1);

// 设置着色器程序
gl.useProgram(program);

// 获取着色器程序中 uniform 变量的位置
var translationUniformLocation = gl.getUniformLocation(program, "u_translation");

// 更新平移向量
function updateTranslation() {
    var time = new Date().getTime() * 0.001; // 获取时间并转换为秒
    var translation = [
        Math.sin(time), // x 轴上的移动,使用正弦函数模拟
        Math.cos(time)  // y 轴上的移动,使用余弦函数模拟
    ];
    gl.uniform2fv(translationUniformLocation, translation);
}

// 动画循环
function animate() {
    // 清空画布
    gl.clear(gl.COLOR_BUFFER_BIT);

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

    // 更新平移向量
    updateTranslation();

    // 请求下一次动画循环
    requestAnimationFrame(animate);
}

// 开始动画循环
animate();

// 创建着色器程序的函数
function createProgram(gl, vertexShaderSource, fragmentShaderSource) {
    // 创建顶点着色器和片段着色器
    var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
    var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

    // 创建着色器程序
    var program = gl.createProgram();

    // 附加着色器到着色器程序
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);

    // 链接着色器程序
    gl.linkProgram(program);

    // 检查链接状态
    var success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (success) {
        return program;
    }

    // 链接错误,打印错误信息
    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
}

// 创建着色器的函数
function createShader(gl, type, source) {
    // 创建着色器
    var shader = gl.createShader(type);

    // 附加着色器源代码到着色器
    gl.shaderSource(shader, source);

    // 编译着色器
    gl.compileShader(shader);

    // 检查编译状态
    var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (success) {
        return shader;
    }

    // 编译错误,打印错误信息
    console.log(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
}

运行成功截图

他现在就是一个游来游去的红色三角形了。太神奇了!~

相关推荐
茯苓gao1 天前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾1 天前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT1 天前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa1 天前
HTML和CSS学习
前端·css·学习·html
看海天一色听风起雨落1 天前
Python学习之装饰器
开发语言·python·学习
speop1 天前
llm的一点学习笔记
笔记·学习
非凡ghost1 天前
FxSound:提升音频体验,让音乐更动听
前端·学习·音视频·生活·软件需求
ue星空1 天前
月2期学习笔记
学习·游戏·ue5
萧邀人1 天前
第二课、熟悉Cocos Creator 编辑器界面
学习
m0_571372821 天前
嵌入式ARM架构学习2——汇编
arm开发·学习