WebGL 实践篇(二)—— 屏幕坐标与裁剪坐标,片段着色器中的颜色定义

2023-11-15

一 裁剪坐标系、canvas坐标系以及屏幕坐标系

裁剪坐标(WebGL坐标系)的范围:(-1,1),原点在中间,x正值向右,y正值向上

屏幕坐标:原点在左上角,x正值向右,y正值向下

canvas坐标:与屏幕坐标相比,原点向右向下偏移,x,y正值方向不变

参考:

(26条消息) WebGL屏幕坐标系、canvas坐标系和WebGL坐标系转换——学习笔记_ponGISer的博客-CSDN博客icon-default.png?t=M276https://blog.csdn.net/u011332271/article/details/110477155二 顶点着色器的修改

在前一例绘制三角形的过程当中,我们传入的顶点是裁剪空间坐标,而一般情况下,我们更希望传入屏幕像素坐标,因此需要将传入的像素坐标转换成裁剪坐标。

  <script id="vertex-shader" type="nojs">
    attribute vec2 a_position;

    uniform vec2 u_resolution;

    void main(){
      //将像素坐标转换为0~1,u_resolution是画布的分辨率
      vec2 zeroToOne = a_position / u_resolution;
      //再转换为0~2
      vec2 zeroToTwo = zeroToOne * 2.0;
      //再转换为-1~1(即裁剪空间坐标)
      vec2 clipSpace = zeroToTwo - 1.0;

      gl_Position = vec4(clipSpace,0,1);
    }
  </script>

三 封装编译着色器、连接着色器程序的函数(有专门的webUtils工具库对这两个操作进行封装,webgl-utils.js)

    //创建着色器并编译
    function createShaders(webgl, type, source) {
      var shader = webgl.createShader(type);
      webgl.shaderSource(shader, source);
      webgl.compileShader(shader);

      var success = webgl.getShaderParameter(shader, webgl.COMPILE_STATUS);
      if (!success) {
        console.log("error:", webgl.getShaderInfoLog(shader));
        return;
      }
      return shader;
    }

    //创建着色程序并链接
    function createPrograms(webgl, vertexShader, fragmentShader) {
      var program = webgl.createProgram();
      webgl.attachShader(program, vertexShader);
      webgl.attachShader(program, fragmentShader);
      webgl.linkProgram(program);

      var success = webgl.getProgramParameter(program, webgl.LINK_STATUS);
      if (!success) {
        console.log("error:", webgl.getProgramInfoLog(program));
        return;
      }
      return program;
    }

四 绘制矩形(需要绘制两个三角形)

    var positionAttributeLocation = webgl.getAttribLocation(programs, "a_position");

    var resolutionUniformLocation = webgl.getUniformLocation(programs, "u_resolution");

    var positionBuffer = webgl.createBuffer();

    webgl.bindBuffer(webgl.ARRAY_BUFFER, positionBuffer);

    //矩形由两个三角形构成
    var positions = [
      10, 20,
      80, 20,
      10, 30,
      10, 30,
      80, 20,
      80, 30
    ]
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(positions), webgl.STATIC_DRAW);

    webgl.viewport(0, 0, webgl.canvas.width, webgl.canvas.height);

    webgl.clearColor(0, 0, 0, 1);

    webgl.clear(webgl.COLOR_BUFFER_BIT);

    webgl.useProgram(programs);

    //attribute
    webgl.enableVertexAttribArray(positionAttributeLocation);
    webgl.bindBuffer(webgl.ARRAY_BUFFER, positionBuffer);
    webgl.vertexAttribPointer(positionAttributeLocation, 2, webgl.FLOAT, false, 0, 0);

    //uniform
    webgl.uniform2f(resolutionUniformLocation, webgl.canvas.width, webgl.canvas.height);

    webgl.drawArrays(webgl.TRIANGLES, 0, 6);

结果如下:

 可以看到矩形在右下角,而不是我们所认为的在左上角,从屏幕坐标与webgl坐标我们可以看出它们y轴的正方向不同,因此在转换成裁剪坐标之后我们需要对y轴进行一次翻转即可,顶点着色器程序就变成了这样:

  <script id="vertex-shader" type="nojs">
    attribute vec2 a_position;

    uniform vec2 u_resolution;

    void main(){
      //将像素坐标转换为0~1,u_resolution是画布的分辨率
      vec2 zeroToOne = a_position / u_resolution;
      //再转换为0~2
      vec2 zeroToTwo = zeroToOne * 2.0;
      //再转换为-1~1(即裁剪空间坐标)
      vec2 clipSpace = zeroToTwo - 1.0;
      //翻转y轴
      gl_Position = vec4(clipSpace * vec2(1,-1),0,1);
    }
  </script>

结果如下:

六 自定义颜色

颜色是在片段着色器进行修改的,想要自定义颜色的话就需要利用uniform变量进行自定义传值。片段着色器代码如下:

  <script id="fragment-shader" type="nojs">
    precision mediump float;

    uniform vec4 u_color;

    void main(){
      gl_FragColor = u_color;
    }
  </script>

 定义uniform变量主要包括两个步骤:

1. 获取uniform变量的位置:

    var colorUniformLocation = webgl.getUniformLocation(programs, "u_color");

2.为它定义一个值(由于颜色值我们在着色器中定义的是vec4,因此也就需要4个参数即rbga):

    webgl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1);

结果如下(每次刷新都会得到一个颜色不一样的矩形):

七 一点点不一样的小拓展:绘制50个颜色不一大小不一的随机矩形:

注意在渲染前一定要做好准备工作噢(比如创建缓冲区、绑定缓冲、存放数据、启用缓冲区以及说明绘制方式等)

    for (var ii = 0; ii < 50; ii++) {
      setRectangle(webgl, randomInt(300), randomInt(300), randomInt(300), randomInt(300));

      webgl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1);

      webgl.drawArrays(webgl.TRIANGLES, 0, 6);
    }

    function randomInt(range) {
      return Math.floor(Math.random() * range);
    }


    function setRectangle(gl, x, y, width, height) {
      var x1 = x;
      var x2 = x + width;
      var y1 = y;
      var y2 = y + height;
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        x1, y1,
        x2, y1,
        x1, y2,
        x1, y2,
        x2, y1,
        x2, y2
      ]), gl.STATIC_DRAW);
    }

结果如下:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebGL 实践篇(二)—— 屏幕坐标与裁剪坐标,片段着色器中的颜色定义 的相关文章

  • 为什么 setInterval 会无限循环

    我正在尝试设置一个计时器 以便它显示用户的秒数和分钟剩余时间 并且我正在使用setInterval获取秒数 如果有 60 秒 则会从用户处减少 1 分钟 问题是我变得无限for每次我尝试这样做时都会循环 就像是 var userObj na
  • 如何将函数处理程序从控制器传递到 AngularJs 中的指令隔离范围?

    我在控制器中有以下功能 angular module app controller BodyController function this click function message alert message 我想将此函数传递到指令的
  • 嵌套 .ajax() 调用的 JavaScript/jQuery 变量作用域问题

    我很难传递变量postData这是一个嵌套子级的序列化 jQuery 数组对象 ajax call postData成功传递给第一个 ajax 打电话 但是当我尝试在第二次使用它时 ajax 调用时 它不会发布任何表单元素 因为变量在该级别
  • 如何在 contenteditable 中跟踪插入符/光标?

    我想在 contenteditable 中跟踪插入符 光标的移动 不过 我不确定最好的方法是什么 我目前正在监听点击 按下键盘 按下键盘的声音 当然 像箭头键或 ctrl x 这样的按键甚至不会触发 虽然 click 工作正常 但 keyd
  • Web Worker 中的 RequireJS

    我正在尝试在网络工作者中使用 RequireJS 问题是我在使用它时不断收到以下错误 Uncaught Error importScripts failed for underscore at lib underscore js 我已经测试
  • 该脚本在 IE 中不起作用。我该如何修复它?

    有一个脚本可以根据用户的显示器屏幕分辨率更改页面模板 但是 它在 IE 中不起作用 请告知如何修复它 table align center tr td head td tr tr td nbsp td td nbsp td td nbsp
  • 最小有效 JSON 是多少?

    我仔细阅读了 JSON 描述http json org http json org 但我不确定我是否知道这个简单问题的答案 最小可能的有效 JSON 字符串是什么 string 该字符串是有效的 JSON 吗 42简单的数字是有效的 JSO
  • Angular JS未知提供者错误

    删除 Bower components 并清理缓存后 我使用 Bower install 重新安装了依赖项 该应用程序无法加载并出现以下错误 未捕获的错误 injector unpr 未知提供程序 forceReflowProvider 这
  • 使用express记录所有GraphQL响应

    我成功地设置了记录 graphQL 错误 app use graphql graphqlHTTP request gt return schema rootValue request formatError error gt const p
  • 如何将 iLike 运算符与 Sequelize 结合使用来进行不区分大小写的查询

    我使用 Sequelize 和 PostgreSQL 来管理我的数据库 我想执行不区分大小写的搜索查询 当我用谷歌搜索时 有人说我可以使用 iLike 运算符来做到这一点 我尝试以这种方式实现 var getRadiosByGenre fu
  • JavaScript 语法是什么:{Ci, CC}? [复制]

    这个问题在这里已经有答案了 我正在做一些 FF 附加开发 我看到这样的语法 var Cc Ci require chrome 只是好奇这个语法是什么 以及它是否对 FF 开发或其他东西有特殊意义 这称为解构赋值 它的一个特点是JavaScr
  • 对 UPDATE 行的 POST 请求

    我是 javascript 的新手 所以我正在寻找一些帮助来创建一种拖放地理编码标记的方法 以允许交互式更改地址 我相信通过更新 LOCATION 列行可以实现这一点 第一步是 发送 POST 请求 对吧 好吧 所以我想问是否有人可以给我看
  • Vue: vue-i18n: 无法翻译 keypath 的值,使用 keypath 的值作为默认值

    我正在使用 Vue 我想展示三种语言 英语 他加禄语和宿务语 现在我有错误 无法转换键路径 NavbarMobile home 的值 使用 keypath 的值作为默认值 我通过 console log this i18n locale 检
  • Safari 和 Edge 中的 audioContext.copyToChannel() 替代方案

    Safari 和 Edge 都不支持audioContext copyToChannel 函数用自定义内容填充audioBuffer 还有其他方法吗 就我而言 我想创建一个脉冲响应 用该响应填充缓冲区 并将一些声音与该缓冲区进行卷积 对于
  • React Native v0.71.8 React-native-vector-icons 你看不到的图标

    我在用react native版本v0 71 8 我安装了react native vector icons库 但图标未显示 似乎链接在最新版本的 React Native 中不再起作用 所以我按照说明进行操作 但它不再编译 出现以下错误
  • 防止 Firefox Web 通知自动关闭

    我已经在 Firefox 中将 Web 通知与服务器发送的 DOM 事件结合使用 不幸的是 通知在大约两到三秒后消失 我更喜欢 Chrome 的方法 即让消息保持可见 在任何给定时间最多显示三个 直到用户单击通知 这是我所拥有的 windo
  • 无法使用 Excel JavaScript API 设置 NumberFormat

    我正在使用 Excel Javascript API 在搜索文档后 仍然找不到我想要实现的解决方案 因此 我想将所有内容设置为数字格式 文本 这样 Excel 的自动格式设置就不会与任何单元格的内容混淆 不会删除前导零或更改日期格式 文档建
  • 如何在vuetify中设置固定工具栏?

    在 vuetify 中我使用工具栏
  • 谷歌地图的灰度

    有没有什么方法可以在不丢失任何其他功能的情况下以灰度显示 Google 地图 通过 Javascript API 嵌入 是的 他们在 api V3 中引入了StyledMaps http code google com apis maps
  • 如何阻止用户重复单击 jQuery AJAX 调用?

    我有一个包含以下脚本的网页 JavaScript function LinkClicked var stage this id var stop ContentPlaceHolderMenu txtDate val var nDays Co

随机推荐

  • Flex和Bison协同工作(下)

    Flex和Bison协同工作 下 上一篇文章我们写了一个稍微复杂一点点的词法解析器 这篇我们开始搞定语法分析器 文法与语法分析 语法分析器的任务其实就是找出输入记号之间的关系 通常使用语法分析树 parse tree 例如 算术表达式12
  • [4G&5G专题-62]:架构 - 开放的网络自动化平台ONAP(Open Network Automation Platform)

    目录 第1章 什么是开放的网络自动化平台ONAP 1 1 什么是ONAP 1 2 什么是的网络自动化平台 1 3 ONAP的动机与背景 1 4 ONAP的底层支撑技术 1 5 ONAP的前世 1 6 5G与ONAP 第2章 5G RAN的自
  • 你真的会用read()读【普通文件】吗?

    原型如下 include
  • 如何将json字符串写入table表格中

    JSON JavaScript Object Notation 是一种轻量级的数据交换格式 可以方便的将后台复杂的数据带回到前台进行展示 那么如何把json字符串写入到table表格之中呢 json简单说就是javascript中的对象和数
  • 美通企业日报

    今日看点 2019时尚育儿
  • java 常见错误合集

    java lang NullPointerException 这个异常都是因为调用null对象的方法 就是一个对象还没有没有正常初始化 就先调用它的方法比如 Object obj null obj toString 这就会抛出 这个异常
  • java中strictfp么意思_java中的strictfp的作用

    自Java2以来 Java语言增加了一个关键字strictfp 虽然这个关键字在大多数场合比较少用 但是还是有必要了解一下 strictfp 的意思是FP strict 也就是说精确浮点的意思 在Java虚拟机进行浮点运算时 如果没有指定s
  • 基于STM32控制的数字BUCK电路及程序编写

    本文芯片采用STM32G474CBT6 采用STM32cubeMX进行程序生成 BUCK电路拓扑结构 如图所示 BUCK变换器主要由电源VDC 场效应管MOSFET 续流二极管VD 电感L以及滤波电容C和负载RES组成 当MOSFET开通时
  • linux pxe安装视频,Linux利用PXE安装虚拟机的方法

    之前和友人聊天 知道可以利用PXE安装虚拟机 相信很多用户都和小编一样还不是很清楚 在这小编就把学习到的方法分享给大家 方法如下 1 1 dnsmasq apt get install dnsmasq vim etc dnsmasq con
  • elasticsearch sort script实现字段值等于某值排名靠前

    什么是script语言 script语言是es提供的一种支持自定义编程的用于复杂查询的脚本语言 主要类型有painless expressions等 需求描述 实际业务场景需要将某字段等于某值的排在前面 其他数据靠后 比如 雇员属性 nam
  • 阿里跟腾讯又㕛叒打起来了,这次是在东南亚

    腾讯与阿里的先头部队 已经在东南亚开始新的战争 在这之中 电商的争夺尤其激烈 神经浪游者 作者威廉 吉布森说 未来已来 只是分布得不太均匀 互联网的分布尤其如此 先是欧美 之后中国 如今 投资人和从业者纷纷押注 昔日的好时光将在东南亚将重现
  • sqlite3 提示 not found

    在android开发中使用adb shell下的sqlite3命令来查看SQLite数据库时 出现了 sqlite3 not found 错误 在网上搜索了一下问题的原因 原来是模拟器或真机中的 system xbin 目录下少了sqlit
  • 华为OD机试 - 工作安排 - 动态规划(Java 2023Q1 100分)

    目录 一 题目描述 二 输入描述 三 输出描述 四 动态规划 五 解题思路 六 Java算法源码 七 效果展示 1 输入 2 输出 3 说明 华为OD机试 2023B卷题库疯狂收录中 刷题点这里 一 题目描述 小明每周上班都会拿着自己的工作
  • vue设置全局过滤器

    src目录下新建文件夹filters 新建文件index js内容为 const timefilters getdate data console log data getdatetime data console log data exp
  • 十大Web网站漏洞扫描工具

    1 Nikto 这是一个开源的Web服务器扫描程序 它可以对Web服务器的多种项目 包括3500个潜在的危险文件 CGI 以及超过900个服务器版本 还有250 多个服务器上的版本特定问题 进行全面的测试 其扫描项目和插件经常更新并且可以自
  • 信号槽的返回值(QMetaObject::invokeMethod的用法)——Qt

    前言 之前从未想过信号槽是可以有返回值的 因为虽然信号发出去了 但是它在事件循环中 什么时候执行还不一定 这个想法固然是对的 但是这也不是不能实现的 我查了网上的一些资料 发现差不多有一下三种方法 1 信号槽里加指针或引用 这个不推荐 隐患
  • 并发处理

    1 并发活动 进程的引入 操作系统的特性之一是并发与共享 即在系统中 内存 同时存在几个相互独立的程序 这些程序在系统中既交叉地运行 又要共享系统中的资源 这就会引起一系列的问题 包括 对资源的竞争 运行程序之间的通信 程序之间的合作与协同
  • 分布式锁的实现

    目录 分布式锁 分布式锁的引出 单体锁存在的问题 共享数据不安全 超卖现象 锁的理解 拓展 分流 拓展 分流Nginx简单理解 分布式锁的引出 分布式锁的设计思路 分布式锁的常见应用场景 分布式锁方案 数据库的分布式锁如何实现 Redis分
  • 《手把手教你》系列练习篇之4-python+ selenium自动化测试(详细教程)

    1 简介 今天我们继续前边的练习 学习和练习一下 如何使用webdriver方法获取当前测试页面的URL 如何获取当前页面的title 如何打开浏览器的一个新建页面 如何操作单选按钮等等 这些小练习 来巩固基础 2 webdriver方法获
  • WebGL 实践篇(二)—— 屏幕坐标与裁剪坐标,片段着色器中的颜色定义

    一 裁剪坐标系 canvas坐标系以及屏幕坐标系 裁剪坐标 WebGL坐标系 的范围 1 1 原点在中间 x正值向右 y正值向上 屏幕坐标 原点在左上角 x正值向右 y正值向下 canvas坐标 与屏幕坐标相比 原点向右向下偏移 x y正值