当前位置: 首页 > news >正文

【WebGL】fbo双pass案例

双pass渲染案例(离线渲染一个三角面,然后渲染到一个占满屏幕的矩阵上)

离线渲染如何需要开启深度测试的话,需要额外操作,这里不展开

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebGL 2 Offline Rendering and Texture Display</title>
</head><body><canvas id="glCanvas" width="800" height="600"></canvas><script>// 将 WebGL 初始化和渲染逻辑封装到一个函数中function initWebGL() {// 获取 canvas 元素const canvas = document.getElementById('glCanvas');// 获取 WebGL 2 上下文const gl = canvas.getContext('webgl2');// 如果无法获取 WebGL 2 上下文,给出提示并结束函数if (!gl) {alert('无法初始化 WebGL 2,你的浏览器可能不支持。');return;}// 离线渲染的着色器代码const offlineVertexShaderSource = `#version 300 esin vec2 a_position;void main() {gl_Position = vec4(a_position, 0.0, 1.0);}`;const offlineFragmentShaderSource = `#version 300 esprecision mediump float;out vec4 fragColor;void main() {fragColor = vec4(1.0, 0.0, 0.0, 1.0);}`;// 最终渲染到屏幕的着色器代码const finalVertexShaderSource = `#version 300 esin vec2 a_position;in vec2 a_texCoord;out vec2 v_texCoord;void main() {gl_Position = vec4(a_position, 0.0, 1.0);v_texCoord = a_texCoord;}`;const finalFragmentShaderSource = `#version 300 esprecision mediump float;in vec2 v_texCoord;uniform sampler2D u_texture;out vec4 fragColor;void main() {fragColor = texture(u_texture, v_texCoord);}`;// 创建着色器函数function createShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);if (success) {return shader;}console.log(gl.getShaderInfoLog(shader));gl.deleteShader(shader);}// 创建着色器程序函数function createProgram(gl, vertexShader, fragmentShader) {const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);const success = gl.getProgramParameter(program, gl.LINK_STATUS);if (success) {return program;}console.log(gl.getProgramInfoLog(program));gl.deleteProgram(program);}// 创建离线渲染的着色器程序const offlineVertexShader = createShader(gl, gl.VERTEX_SHADER, offlineVertexShaderSource);const offlineFragmentShader = createShader(gl, gl.FRAGMENT_SHADER, offlineFragmentShaderSource);const offlineProgram = createProgram(gl, offlineVertexShader, offlineFragmentShader);// 创建最终渲染的着色器程序const finalVertexShader = createShader(gl, gl.VERTEX_SHADER, finalVertexShaderSource);const finalFragmentShader = createShader(gl, gl.FRAGMENT_SHADER, finalFragmentShaderSource);const finalProgram = createProgram(gl, finalVertexShader, finalFragmentShader);// 离线渲染的顶点数据const offlinePositions = [-0.5, -0.5,0.5, -0.5,0.0, 0.5];// 创建离线渲染的顶点缓冲区const offlinePositionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, offlinePositionBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(offlinePositions), gl.STATIC_DRAW);// 获取离线渲染的顶点属性位置const offlinePositionAttributeLocation = gl.getAttribLocation(offlineProgram, 'a_position');gl.enableVertexAttribArray(offlinePositionAttributeLocation);gl.vertexAttribPointer(offlinePositionAttributeLocation, 2, gl.FLOAT, false, 0, 0);// 创建帧缓冲区对象(FBO)const framebuffer = gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);// 创建纹理对象const texture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D, texture);gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);// 将纹理附加到帧缓冲区gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);// 检查帧缓冲区是否完整if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {console.error('帧缓冲区不完整');}// 离线渲染gl.useProgram(offlineProgram);gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);gl.viewport(0, 0, canvas.width, canvas.height);gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);// 最终渲染到屏幕的顶点数据和纹理坐标const finalPositions = [-1.0, -1.0,1.0, -1.0,-1.0, 1.0,-1.0, 1.0,1.0, -1.0,1.0, 1.0];const finalTexCoords = [0.0, 0.0,1.0, 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0, 1.0];// 创建最终渲染的顶点缓冲区和纹理坐标缓冲区const finalPositionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, finalPositionBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(finalPositions), gl.STATIC_DRAW);const finalTexCoordBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, finalTexCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(finalTexCoords), gl.STATIC_DRAW);// 获取最终渲染的顶点属性位置和纹理坐标属性位置const finalPositionAttributeLocation = gl.getAttribLocation(finalProgram, 'a_position');gl.enableVertexAttribArray(finalPositionAttributeLocation);gl.vertexAttribPointer(finalPositionAttributeLocation, 2, gl.FLOAT, false, 0, 0);const finalTexCoordAttributeLocation = gl.getAttribLocation(finalProgram, 'a_texCoord');gl.enableVertexAttribArray(finalTexCoordAttributeLocation);gl.vertexAttribPointer(finalTexCoordAttributeLocation, 2, gl.FLOAT, false, 0, 0);// 获取最终渲染的纹理采样器位置const textureUniformLocation = gl.getUniformLocation(finalProgram, 'u_texture');// 最终渲染到屏幕gl.useProgram(finalProgram);gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.viewport(0, 0, canvas.width, canvas.height);gl.clearColor(0.0, 0.0, 0.0, 1.0);gl.clear(gl.COLOR_BUFFER_BIT);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);gl.uniform1i(textureUniformLocation, 0);gl.drawArrays(gl.TRIANGLES, 0, 6);}// 调用封装好的函数来初始化和渲染 WebGLinitWebGL();</script>
</body></html>

相关文章:

【WebGL】fbo双pass案例

双pass渲染案例&#xff08;离线渲染一个三角面&#xff0c;然后渲染到一个占满屏幕的矩阵上&#xff09; 离线渲染如何需要开启深度测试的话&#xff0c;需要额外操作&#xff0c;这里不展开 <!DOCTYPE html> <html lang"en"><head><meta ch…...

Unity面板介绍_层级面板(23.1.1)

一、Inspector(检视面板) 显示当前选定游戏对象附加的组件及其属性信息。为重要游戏物体选择图标 二、面板详情...

详解Nginx 配置

一、Nginx 介绍 Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。它由俄罗斯的程序设计师 Igor Sysoev 所开发&#xff0c;自 2004 年发布以来&#xff0c;凭借其高性能、低内存消耗、高并发处理能力等特点&#xf…...

数据库系统概念

1. 绪论 数据库的基本概念: 数据(data): 数据库中存储的基本对象, 可以是文字, 声音, 图片, 视频等。 数据库(DB): 概括来说就是永久存储, 有组织, 可共享的大量数据的集合。 数据库管理系统(DBMS): 和操作系统一样是计算机基础软件, 主要有数据定义语言(DDL, 对数据对象的组…...

51单片机学习之旅——定时器

打开软件 1与其它等于其它&#xff0c;0与其它等于0 1或其它等于1&#xff0c;0或其它等于其它 TMODTMOD&0xF0;//0xF01111 0000进行与操作&#xff0c;高四位保持&#xff0c;低四位清零&#xff0c;高四位定时器1&#xff0c;低四位定时器0 TMODTMOD|0x01;//0x010000 0…...

一台服务器将docker image打包去另一天服务器安装这个镜像

一台服务器将docker image打到去另一天服务器安装这个镜像 1. 打包2.另一台服务器执行 1. 打包 docker save -o nebula-graph-studio.tar harbor1.vm.example.lan/dockerio/vesoft/nebula-graph-studioxxx.tar 是打包好的文件 后面的是 docker image 2.另一台服务器执行 docke…...

QT串口通信之二,实现单个温湿度传感器数据的采集(采用Qt-modbus实现)

接上 QT串口通信之一,实现单个温湿度传感器数据的采集 上述文章中用QSerialPort实现了温湿度传感器的采集,实际上比较麻烦的,因为需要自定义解析帧, 接下来,用Qt-modbus-封装度更高的协议,来实现温湿度的采集; #include "MainWindow.h" #include "ui_M…...

基于SpringBoot的校园消费点评管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

【小沐学Java】VSCode搭建Java开发环境

文章目录 1、简介2、安装VSCode2.1 简介2.2 安装 3、安装Java SDK3.1 简介3.2 安装3.3 配置 4、安装插件Java Extension Pack4.1 简介4.2 安装4.3 配置 结语 1、简介 2、安装VSCode 2.1 简介 Visual Studio Code 是一个轻量级但功能强大的源代码编辑器&#xff0c;可在桌面上…...

《操作系统 - 清华大学》8 -4:进程管理:进程控制结构

深度剖析进程控制块&#xff1a;操作系统进程管理的核心关键 在操作系统的复杂体系中&#xff0c;进程控制块&#xff08;PCB&#xff09;是实现高效进程管理的关键所在。接下来&#xff0c;将从多个维度深入剖析进程控制块&#xff0c;帮助更好地理解其在操作系统中的重要作用…...

RPC 框架项目剖析

RPC 框架项目剖析 说明 本文用于梳理一个 rpc项目的实现细节&#xff0c;此项目基于cpp语言 大概三千行左右&#xff0c;用于学习目的。 项目链接&#xff1a;rpc项目 项目底层类 1.抽象消息类 描述&#xff1a; 各种消息的基类 属性&#xff1a; 消息id&#xff0c;消息类型…...

C++ Boost面试题大全及参考答案

目录 boost::thread_group 如何实现批量线程管理? 解释 boost::asio 中 proactor 模式的设计原理 使用 boost::atomic 实现无锁环形缓冲区 boost::mutex 与 std::mutex 在异常安全上的差异 如何用 boost::condition_variable 实现生产者 - 消费者模型 当 boost::shared_p…...

关于Transparent native-to-ascii conversion

1、功能 自动转换ASCII编码&#xff0c;即在文件系统上&#xff0c;文件的编码格式为ascii编码&#xff0c;在编辑器&#xff08;idea/pycharm&#xff09;中&#xff0c;其展现结果为配置的编码格式&#xff0c;仅展现方便阅读 使用UTF-8并勾选自动转换ASCII编码结果&#x…...

js数据类型检测

JavaScript的数据类型检测 typeof操作符 适用场景 基本数据类型快速判断&#xff1a;适用于快速判断变量是否为number、string、boolean、undefined、function等基本数据类型。比如在函数参数检查中&#xff0c;若要求传入数字参数&#xff0c;可用typeof来初步判断。函数类型…...

go 模块管理

go version 查看版本 go version go1.21.12 windows/amd64 需要保证:go的版本升级为1.11以上,go mod依赖的最底版本 go env 查看go的环境变量 go env 开启go mod # 标识开启go的模块管理 set GO111MODULE=on GO111MODULE有三个值:off, on和auto(默认值)。 GO111M…...

记一次复杂分页查询的优化历程:从临时表到普通表的架构演进

1. 问题背景 在项目开发中&#xff0c;我们需要实现一个复杂的分页查询功能&#xff0c;涉及大量 IP 地址数据的处理和多表关联。在我接手这个项目的时候,代码是这样的 要知道代码里面的 ipsList 数据可能几万条甚至更多,这样拼接的sql,必然是要内存溢出的,一味地扩大jvm参数不…...

基于 Python 的项目管理系统开发

基于 Python 的项目管理系统开发 一、引言 在当今快节奏的工作环境中&#xff0c;有效的项目管理对于项目的成功至关重要。借助信息技术手段开发项目管理系统&#xff0c;能够显著提升项目管理的效率和质量。Python 作为一种功能强大、易于学习且具有丰富库支持的编程语言&…...

java面试场景问题

还在补充&#xff0c;这几天工作忙&#xff0c;闲了会把答案附上去&#xff0c;也欢迎各位大佬评论区讨论 1.不用分布式锁如何防重复提交 方法 1&#xff1a;基于唯一请求 ID&#xff08;幂等 Token&#xff09; 思路&#xff1a;前端生成 一个唯一的 requestId&#xff08;…...

JS宏实例:数据透视工具的制作(四)

上一节中&#xff0c;我们完成了核心的计算代码部分&#xff0c;本节中将完善事件代码 一、创建所有需求的事件函数 1、窗体初始化 // 窗体初始化 function pivotForm_Initialize(){} function typeSet_Initialize(){} function valueSet_Initialize(){} function allCol…...

5. Go 方法(结构体的方法成员)

Go语言没有传统的 class &#xff0c;为了让函数和结构体能够关联&#xff0c;Go引入了“方法”的概念。 当普通函数添加了接收者&#xff08;receiver&#xff09;后&#xff0c;就变成了方法。 一、函数和方法示例 // 普通函数 func Check(s string) string {return s }//…...

别再傻傻用pip了!用Anaconda的conda管理Python环境,效率提升不止一点点

从pip到conda&#xff1a;Python环境管理的效率革命 在Python开发的世界里&#xff0c;环境管理一直是个让人头疼的问题。想象一下这样的场景&#xff1a;你正在开发一个新项目&#xff0c;需要特定版本的NumPy和Pandas&#xff0c;但你的另一个项目却依赖这些库的不同版本。传…...

VH6501实战:手把手教你用CANoe脚本精准触发CAN总线干扰(附避坑点)

VH6501深度实战&#xff1a;CANoe脚本触发干扰的进阶技巧与排错指南 当你第一次用VH6501的CanDisturbanceFrameTrigger类配置触发条件时&#xff0c;是否遇到过这些情况&#xff1a;精心设置的触发位置总是莫名其妙地偏移到下一位&#xff1f;validityMask参数像天书一样难以理…...

【王炸组合】Hermes Agent 官方 UI 发布:本地白嫖 Google Gemma 4,零成本打造最强微信 AI 助手

前言如果说 2025 年是 AI 大模型的爆发年&#xff0c;那么 2026 年 4 月就是“个人 AI 智能体”的普及元年。随着 Gemma 4&#xff08;Google 4月2日刚刚发布&#xff0c;31B 性能直逼 GPT-4o&#xff09;的开源&#xff0c;以及 Hermes Agent 终于告别了繁琐的命令行、发布了正…...

从零训练一个小模型-nanoGPT 模型训练 (一)数据预处理

最近在学习模型训练&#xff0c;实际上在大模型训练上&#xff0c;我并没有深厚的背景&#xff0c;通过视频课程和b站上的一些分享&#xff0c;开始入门。 由于我非神经网络这些相关的专业&#xff0c;所以想把自己学习的过程和经验总结记录下来&#xff0c;一方面自己可以巩固…...

Paper 深读 | LLM驱动的多智能体分层决策新范式

**&#x1f511; 关键词&#xff1a;**分层决策、LLM规划、Bandit探索、多智能体导航 **&#x1f525; 一句话标签&#xff1a;**首创"LLMBandit分布式RL"三层自治体系&#xff0c;显著提升多智能体复杂任务的规划、探索与协作效率 02 一句话核心思想 针对多智能体…...

因果表征学习:从数据中挖掘“为什么”的AI新范式

因果表征学习&#xff1a;从数据中挖掘“为什么”的AI新范式 当你的模型在训练集上表现完美&#xff0c;却在现实世界中频频“翻车”时&#xff0c;或许问题不在于数据不够&#xff0c;而在于模型只学会了“相关”&#xff0c;却不懂“因果”。 引言&#xff1a;超越相关&#…...

ERP系统与医疗器械生产管理规范的契合点

ERP系统与医疗器械生产管理规范的契合点 医疗器械生产管理规范&#xff08;GMP&#xff09;对数据完整性、过程追溯性、质量管理体系有严格要求。ERP系统通过以下模块实现合规&#xff1a; 主数据管理 建立医疗器械唯一标识&#xff08;UDI&#xff09;数据库&#xff0c;确保产…...

golang如何实现错误预算Error Budget计算_golang错误预算Error Budget计算实现实战

错误预算是SLO允许的失败请求占比上限&#xff0c;需绑定固定时间窗口、用累计值而非rate计算、避免float64实时减法&#xff0c;推荐Prometheus聚合异步校准。什么是错误预算&#xff0c;Go 里为什么不能直接用 float64 算错误预算是 SLO&#xff08;Service Level Objective&…...

从4G到Wi-Fi 6:OFDM自适应技术是如何让你刷视频不卡顿的?

从4G到Wi-Fi 6&#xff1a;OFDM自适应技术如何重塑你的无线体验 每次在地铁里刷短视频&#xff0c;或是用咖啡厅Wi-Fi开视频会议时&#xff0c;你是否好奇过&#xff1a;为什么同样的网络环境下&#xff0c;有些人的画面流畅如丝&#xff0c;而你的却卡成PPT&#xff1f;这背后…...

别再傻傻分不清了!GCC、Glibc、Libstdc++ 在 Linux 下到底是啥关系?

别再傻傻分不清了&#xff01;GCC、Glibc、Libstdc 在 Linux 下到底是啥关系&#xff1f; 刚接触 Linux C/C 开发时&#xff0c;最让人头疼的莫过于那些晦涩难懂的编译错误。比如 undefined reference to std::cout 或者 glibc version not found&#xff0c;新手往往一脸茫然&…...