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

运行成功截图

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/329040.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot的美食分享平台(程序+数据库+文档)

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目 希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一、研究背景 1.1 课题背景 二…

合适的索引顺序

一.前言 正确的顺序依赖于使用索引的查询,并且同时需要考虑如何更好地满足排序和分组的需要。因为哈希或者其他类型的索引并不会像 B-Tree索引一样顺序存储数据,所以这里只针对B-Tree展开讨论。 二.合适的索引顺序 1. 概念 对于如何选择索引顺序有一个经验法则: 将选择性最…

【驱动】TI AM437x(内核调试-06):网卡(PHY和MAC)、七层OSI

1、网络基础知识 1.1 七层OSI 第一层:物理层。 1)需求: 两个电脑之间如何进行通信? 具体就是一台发比特流,另一台能够收到。于是就有了物理层:主要是定义设备标准,如网线的额接口类型、管线的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流,就是从1/0…

C++设计模式(李建忠)笔记1

C设计模式&#xff08;李建忠&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考链接 Youtube: C设计模式 Gtihub源码与PPT&#xff1a;https://github.com/ZachL1/Bilibili-plus 豆瓣: 设计模式–可复用面向对象软件的基础 文章目录 C设计模…

WSL deepin的开荒之路

WSL deepin的开荒之路 问题1:sudo apt-get install ***报错无法定位包&#xff08;Unable to locate package&#xff09;问题2&#xff1a;如果在子系统中访问windows下的其他分区 windows11安装deepin直通车https://editor.csdn.net/md/?articleId135648217 问题1:sudo apt…

企业网盘:实现文件共享与协同办公的利器

企业网盘无疑是当下热门的信息管理工具&#xff0c;集存储、管理和协作功能于一体&#xff0c;以其高性价比、便捷易用、高效安全等特质&#xff0c;捕获各行各业的青睐。一跃成为2023年度大热的企业工具之一。 那么企业网盘究竟有何种魅力呢&#xff1f;换而言之&#xff0c;对…

解析Transformer模型

原文地址&#xff1a;https://zhanghan.xyz/posts/17281/ 进入Transformer RNN很难处理冗长的文本序列&#xff0c;且很容易受到所谓梯度消失/爆炸的问题。RNN是按顺序处理单词的&#xff0c;所以很难并行化。 用一句话总结Transformer&#xff1a;当一个扩展性极佳的模型和一…

STM32——ADC知识总结及多通道采样实验

1.ADC概念 ADC&#xff0c;全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 2 STM32各系列ADC的主要特性 3.F4框图 4.转换序列与转换时间 A/D转换被组织为两组&#xff1a;规则组&#xff08;常规转换组&#xff09;和注入组&#xff08;注入…

JNI笔记

JNI笔记 背景Demo代码JNI.javaMainActivity.javaAndroid.mkApplication.mkcom_stone_javacallc_JNI.hjavacallc.cbuild.gradle 背景 Demo代码 代码结构 JNI.java package com.stone.javacallc;/*** Created by stoneWang* Created on 2024/1/16* java调用C*/ public class …

mysql常见的需求,对于关键字的使用

如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能 如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能&#xff0c;也可以根据实际需求自定义一个函数。这种技术在一些需要对数据进…

架构师之超时未支付的订单进行取消操作的几种解决方案

今天给大家上一盘硬菜&#xff0c;并且是支付中非常重要的一个技术解决方案&#xff0c;有这块业务的同学注意自己尝试一把哈&#xff01; 一、需求如下&#xff1a; 生成订单30分钟未支付&#xff0c;自动取消 生成订单60秒后,给用户发短信 对上述的需求&#xff0c;我们给…

leetcode—矩阵

1 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 方法一&#xf…

知识库建设教程来啦,赶紧收藏起来

播种知识&#xff0c;收获效率。知识库&#xff0c;这个企业内部服务的“大百科”&#xff0c;可能是你下一步需要建立的重要工具哦&#xff01;今天&#xff0c;就让我们一起来看一下如何进行知识库的建设和维护。 首先&#xff0c;让我们理解一下知识库的定义。知识库就像是一…

探索Python数据结构与算法:解锁编程的无限可能

文章目录 一、引言1.1 数据结构与算法对于编程的重要性1.2 Python作为实现数据结构与算法的强大工具 二、列表和元组2.1 列表&#xff1a;创建列表、索引、切片和常用操作2.2 元组&#xff1a;不可变序列的特性和使用场景 三、字符串操作和正则表达式3.1 字符串的常见操作和方法…

第36期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

c语言-库函数strstr()、strtok()、strerror()介绍

文章目录 前言一、库函数strstr()1.1 strstr()介绍1.2 strstr()模拟实现 二、库函数strtok()2.1 strtok()介绍 三、库函数strerror()3.1 strerror()介绍 总结 前言 本篇文章介绍c语言库函数strstr()、strtok()、strerror()的使用。 一、库函数strstr() 1.1 strstr()介绍 str…

Linux/Networked

Enumeration nmap 网站更新之后有了一个引导模式&#xff0c;更利于学习了&#xff0c;之前看ippsec的视频&#xff0c;要不总是没有思路&#xff0c;现在出现的问题多了提示也更多了&#xff0c;还没有使用&#xff0c;一会用用再说 首先&#xff0c;第一个问题是“目标上正…

RocketMQ源码阅读-Producer消息发送

RocketMQ源码阅读-Producer消息发送 1. 从单元测试入手2. 启动过程3. 同步消息发送过程4. 异步消息发送过程5. 小结 Producer是消息的生产者。 Producer和Consummer对Rocket来说都是Client&#xff0c;Server是Broker。 客户端在源码中是一个单独的Model&#xff0c;目录为rock…

WordPress后台仪表盘自定义添加删除概览项目插件Glance That

成功搭建WordPress站点&#xff0c;登录后台后可以在“仪表盘 – 概览”中看到包括多少篇文章、多少个页面、多少条评论和当前WordPress版本号及所使用的主题。具体如下图所示&#xff1a; 但是如果我们的WordPress站点还有自定义文章类型&#xff0c;也想在概览中显示出来应该…

《计算机视觉处理设计开发工程师》

计算机视觉&#xff08;Computer Vision&#xff09;是一门研究如何让计算机能够理解和分析数字图像或视频的学科。简单来说&#xff0c;计算机视觉的目标是让计算机能够像人类一样对视觉信息进行处理和理解。为实现这个目标&#xff0c;计算机视觉结合了图像处理、机器学习、模…