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 实践篇(二)—— 屏幕坐标与裁剪坐标,片段着色器中的颜色定义 的相关文章

  • jQuery.getJSON:如何避免在每次刷新时请求 json 文件? (缓存)

    在此示例中 您可以看到生成的 HTML 列表 每次刷新时 脚本都会请求数据文件 ajax test json 并再次构建列表 生成的文件 ajax test json 被静态缓存 但是如何避免在每次刷新时请求此文件 source jquer
  • 使用 WMI 查找服务的依赖关系,然后区分依赖的服务和依赖的驱动程序

    MSDN 上有一个代码示例 它使用 WMI 枚举特定服务的所有依赖项 http msdn microsoft com en us library aa393673 v vs 85 aspx http msdn microsoft com e
  • 检查用户是否连接到 Facebook,然后检查他是否喜欢某个页面

    有没有什么方法可以检查用户是否在我的外部页面上连接到 Facebook 而不让他们允许我的应用程序之一 同样的问题也适用于 检查用户是否喜欢某个页面 我检查了大约 20 个问题和 3 4 个教程 似乎所有问题都在讨论内部脚本 粉丝页面 应用
  • AngularJS 使用 $apply 而不使用 $scope

    我开始使用 AngularJS 并且接受了用它来编写控制器的约定 而不是用 scope 所以我的控制器看起来像这样 myApp controller SomeController function this myModel id 1 nam
  • JavaScript 对象引用缓存

    我们的代码库中有很多对象 它们的名称空间是为了避免冲突 Example App local view MyView 在我在代码库中看到的大多数地方 我们使用完整路径来获取对对象的引用 并且这在同一函数中重复多次 Example functi
  • 如何在光标下的所有元素上调用 mouseover?

    我有一个网络应用程序 每次单击时都会创建一个点 见下文 当我将鼠标悬停在一堆点上时 我希望光标下的每个点都会触发 mouseover 或 mouseenter 事件 然而 只有一个事件被触发 即堆栈 顶部 的点的事件 当鼠标移动到一堆多个点
  • 如何根据按钮单击折叠和展开 Kendo UI 树视图中的所有树节点?

    这是行不通的 您可以使用此代码 1 崩溃 折叠kendoTree查看文档 http docs kendoui com api web treeview methods collapse treeview kendoTreeView var
  • 来自 DataURL 的 Blob?

    Using FileReader s readAsDataURL 我可以将任意数据转换为数据 URL 有没有办法将数据 URL 转换回Blob使用内置浏览器 API 的实例 用户 Matt 一年前提出了以下代码 如何在javascript中
  • HTML5 服务器端事件:EventSource 与包装的 WebSocket

    HTML5 服务器发送事件 SSE API 是否只是 HTML5 WebSocket 之上的受限制的 基于事件的 API 在我看来 一个EventSource只是一个WebSocket that Cannot send data 使用tex
  • Chrome SuppressDifferentOriginSubframeJSDialogs 使用 JS 设置覆盖?

    Chrome 开发团队显然刚刚推出了一项名为 SuppressDifferentOriginSubframeJSDialogs 的新 功能 这使得默认情况下不会显示来自与父级不同域上的 iFrame 的警报 确认框 https www ch
  • JQuery 动画文本

    找到简单 简单的动画文本是非常困难的 喜欢这个网站上的 内爆 http codecanyon net item jquery text animation full screen preview 233445 http codecanyon
  • 在 JavaScript 中比较表单中的两个数字

    当我尝试比较不同的数字时 数字发生变化 但文本部分保持不变 这只发生在较大 较小的情况下 而不会发生在 NaN 或相等的情况下 这是我的代码 function check var a document getElementById a va
  • 点击问题:动态生成的链接不触发点击功能

    下面是两个代码片段 由于某种原因什么也没有发生 但来自同一个 JS 文件的其他 jQuery 函数在带有 UL 的页面上执行得很好 这是在盯着我看吗 ul class paganation li 1 li li a href 2 a li
  • Chrome Javascript 调试器暂停时不会重新加载页面

    有时 当我在 Chrome 中调试某些 javascript 并且暂停了 javascript 时 如果我尝试重新加载页面 chrome 只会 继续 调试器 单步执行到下一个断点 似乎没有任何方法可以强制 javascript 完全停止运行
  • 将 NPM 包客户端与 nuxt 结合使用

    我对 nuxt 和 javascript 非常陌生 我正在尝试弄清楚如何在客户端使用我的应用程序的依赖项 我将它们列在我的 nuxt config js 中并使用 npm 安装 我也有一个文件 plugins导入它们的目录 不确定这是否好
  • 将 JavaScript 引擎嵌入到 .NET 中 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 只是想知道是否有人尝试过将任何 js 引擎嵌入并实际集成到 net 环境中 我可以找到并实际使用 经过L
  • Javascript 选择 onchange='this.form.submit()'

    我有一个带有选择和一些文本输入的表单 我希望在更改选择时提交表单 使用以下方法可以正常工作 onchange this form submit 但是 如果表单还包含提交按钮 则当选择更改时 表单不会提交 我猜有某种冲突 我在这里有什么选择
  • 在声明组件选择器时添加指令 - Angular 7

    我正在学习 Angular 并通过单击按钮动态创建组件 我正在尝试使用 Angular Material 的拖放功能来拖动这些创建的组件以对它们进行排序 我的基本组件 html 中有以下代码 div style margin 20px di
  • 如何根据所需表单输入的值更改 CSS 样式

    我想知道如何编写 javascript 来改变所需的表单元素的样式 如果它们有价值的话就改变它们 我想要做的是当所需的文本字段为空时 在它们周围有一个彩色边框 并在它们有值时删除边框样式 我想做的是编写一个 javascript 函数来检查
  • 使用 jquery 提供附加功能时菜单未正确对齐

    I need to make a mega menu similar to one as show in image below 到目前为止 我已经能够在某种程度上使其发挥作用 例如jsFiddle 在这里 http jsfiddle ne

随机推荐

  • 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正值