跟随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);
}

运行成功截图

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

相关推荐
三品吉他手会点灯4 小时前
C语言学习笔记 - 20.C编程预备计算机专业知识 - 变量为什么必须的初始化【重点】
c语言·笔记·学习
sakiko_5 小时前
UIKit学习笔记1-创建项目(使用UIKit)、使用组件
笔记·学习
生信碱移5 小时前
PACells:这个方法可以鉴定疾病/预后相关的重要细胞亚群,作者提供的代码流程可以学习起来了,甚至兼容转录组与 ATAC 两种数据类型!
人工智能·学习·算法·机器学习·数据挖掘·数据分析·r语言
星幻元宇VR7 小时前
VR航空航天科普设备【VR时空直升机】
科技·学习·安全·生活·vr
_李小白7 小时前
【android opencv学习笔记】Day 2: Mat类(图片数据结构体)
android·opencv·学习
harder3218 小时前
RMP模式的创新突破
开发语言·学习·ios·swift·策略模式
程序猿乐锅9 小时前
【Tilas|第三篇】多表SQL语句
数据库·经验分享·笔记·学习·mysql
徐某人..9 小时前
基于i.MX6ULL平台的智能网关系统开发
arm开发·c++·单片机·qt·物联网·学习·arm
AOwhisky10 小时前
Kubernetes 学习笔记:集群管理、命名空间与 Pod 基础
linux·运维·笔记·学习·云原生·kubernetes
光影少年10 小时前
大屏页面,一次多个请求,请求加密导致 点击 全局时间选择器 时出现卡顿咋解决(面板收起会延迟1~2秒)
前端·javascript·vue.js·学习·前端框架·echarts·reactjs