【OpenGL的着色器03】内置变量(gl_Position等)

目录

一、说明

二、着色器的变量

2.1 着色器变量

2.2 着色器内置变量

三、最常见内置变量使用范例

3.1 常见着色器变量

3.2 示例1: gl_PointSize 

3.3 示例2:gl_Position 

3.4 gl_FragColor

3.5 渲染点片元坐标gl_PointCoord

3.6 gl_PointCoord应用案例

四、GPU的内置函数

4. 1 内置函数列表

4.2 角度与三角函数

4.3 指数函数

4.4 通用函数

4.5 几何函数

4.6 矩阵函数

4.7 矢量函数

4.8 纹理查询函数


一、说明

        着色器的内置变量和内置函数很有必要说一说,因为,初入门的时候不知道着色器有多深的水准,必须将它所蕴涵的东西统统摆到桌面上,才能有所准备,有所认知,有所实用。本篇就是将着色器默认的变量函数统统摆出,混个脸熟。

二、着色器的变量

2.1 着色器变量

        着色器有两种变量:

  • 普通变量,着色器语言和C语言类似,需要先声明后使用。
  • 内置变量,所谓内置变量就是不用声明可以直接赋值,主要是为了实现特定的功能。    

2.2 着色器内置变量

1) 顶点着色器内置变量

名称类型描述
gl_Colorvec4输入属性-表示顶点的主颜色
gl_SecondaryColorvec4输入属性-表示顶点的辅助颜色
gl_Normalvec3输入属性-表示顶点的法线值
gl_Vertexvec4输入属性-表示物体空间的顶点位置
gl_MultiTexCoordnvec4输入属性-表示顶点的第n个纹理的坐标
gl_FogCoordfloat输入属性-表示顶点的雾坐标
gl_Positionvec4输出属性-变换后的顶点的位置,用于后面的固定的裁剪等操作。所有的顶点着色器都必须写这个值。
gl_ClipVertexvec4输出坐标,用于用户裁剪平面的裁剪
gl_PointSizefloat点的大小
gl_FrontColorvec4正面的主颜色的varying输出
gl_BackColorvec4背面主颜色的varying输出
gl_FrontSecondaryColorvec4正面的辅助颜色的varying输出
gl_BackSecondaryColorvec4背面的辅助颜色的varying输出
gl_TexCoord[]vec4纹理坐标的数组varying输出
gl_FogFragCoordfloat雾坐标的varying输出

2)片段着色器内置变量

名称类型描述
gl_Colorvec4包含主颜色的插值只读输入
gl_SecondaryColorvec4包含辅助颜色的插值只读输入
gl_TexCoord[]vec4包含纹理坐标数组的插值只读输入
gl_FogFragCoordfloat包含雾坐标的插值只读输入
gl_FragCoordvec4只读输入,窗口的x,y,z和1/w
gl_FrontFacingbool只读输入,如果是窗口正面图元的一部分,则这个值为true
gl_PointCoordvec2点精灵的二维空间坐标范围在(0.0, 0.0)到(1.0, 1.0)之间,仅用于点图元和点精灵开启的情况下。
gl_FragData[]vec4使用glDrawBuffers输出的数据数组。不能与gl_FragColor结合使用。
gl_FragColorvec4输出的颜色用于随后的像素操作
gl_FragDepthfloat输出的深度用于随后的像素操作,如果这个值没有被写,则使用固定功能管线的深度值代替

三、最常见内置变量使用范例

3.1 常见着色器变量

内置变量名称含义变量数值类型
gl_PointSize 点渲染模式,方形点区域渲染像素大小 float
gl_Position       顶点位置坐标   vec4
gl_FragColor     片元颜色值    vec4
gl_FragCoord     片元坐标,单位像素   vec2
gl_PointCoord    点渲染模式对应点像素坐标    vec2

        当WebGL执行绘制函数gl.drawArrays()绘制模式是点模式gl.POINTS的时候,顶点着色器语言main函数中才会用到内置变量gl_PointSize,使用内置变量gl_PointSize主要是用来设置顶点渲染出来的方形点像素大小。

3.2 示例1: gl_PointSize 

void main() {//给内置变量gl_PointSize赋值像素大小,注意值是浮点数gl_PointSize=20.0;
}//绘制函数绘制模式:点gl.POINTS
gl.drawArrays(gl.POINTS,0,点数量);

3.3 示例2:gl_Position 

        gl_Position内置变量主要和顶点相关,出现的位置是顶点着色器语言的main函数中。gl_Position内置变量表示最终传入片元着色器片元化要使用的顶点位置坐标。

        如果只有一个顶点,直接在给顶点着色器中设置内置变量gl_Position赋值就可以,内置变量gl_Position的值是四维向量vec4(x,y,z,1.0),前三个参数表示顶点的xyz坐标值,第四个参数是浮点数1.0。

void main() {//顶点位置,位于坐标原点gl_Position = vec4(0.0,0.0,0.0,1.0);
}

        如果你想完全理解内置变量gl_Position,必须建立逐顶点的概念,如果javascript语言中出现一个变量赋值,你可以理解为仅仅执行一次,但是对于着色器中不能直接这么理解,如果有多个顶点,你可以理解为每个顶点都要执行一遍顶点着色器主函数main中的程序。

        多个顶点的时候,内置变量gl_Position对应的值是attribute关键字声明的顶点位置坐标变量apos,顶点位置坐标变量apos变量对应了javascript代码中多个顶点位置数据。

<!-- 顶点着色器源码 -->
<script id="vertexShader" type="x-shader/x-vertex">
  //attribute声明vec4类型变量apos
  attribute vec4 apos;
  void main() {
    //顶点坐标apos赋值给内置变量gl_Position
    //逐顶点处理数据
    gl_Position = apos;
  }
</script>

        逐顶点处理的案例:WebGL的每一个顶点位置坐标都会通过平移矩阵m4进行矩阵变换,相当于批量操作所有的顶点数据,进行了平移,只是平移的计算通过矩阵乘法运算完成的而已。所谓的逐顶点,在这里体现的就是每一个顶点都会执行main函数中的矩阵变换。你可以参照生活的流水线去理解,比如多个同样的设备从我这里经过,我会分别对他们进行同样的操作,比如安装一个零件。

<!-- 顶点着色器源码 -->
<script id="vertexShader" type="x-shader/x-vertex">
  //attribute声明vec4类型变量apos
  attribute vec4 apos;
  void main() {
    //创建平移矩阵(沿x轴平移-0.4)
    //1   0   0  -0.4
    //0   1   0    0
    //0   0   1    0
    //0   0   0    1
    mat4 m4 = mat4(1,0,0,0,  0,1,0,0,  0,0,1,0,  -0.4,0,0,1);
    //平移矩阵m4左乘顶点坐标(vec4类型数据可以理解为线性代数中的nx1矩阵,即列向量)
    // 逐顶点进行矩阵变换
    gl_Position = m4*apos;
  }

</script>


## gl_Position的顶点数据传递
attribute声明的顶点变量数据如何通过javascript的WebGL API批量传递所有顶点数据。

<script>
    //顶点着色器源码
    var vertexShaderSource = document.getElementById( 'vertexShader' ).innerText;
    //片元着色器源码
    var fragShaderSource = document.getElementById( 'fragmentShader' ).innerText;
    //初始化着色器
    var program = initShader(gl,vertexShaderSource,fragShaderSource);
    //获取顶点着色器的位置变量apos,即aposLocation指向apos变量。
    var aposLocation = gl.getAttribLocation(program,'apos');

    //类型数组构造函数Float32Array创建顶点数组
    var data=new Float32Array([0.5,0.5,-0.5,0.5,-0.5,-0.5,0.5,-0.5]);

    //创建缓冲区对象
    var buffer=gl.createBuffer();
    //绑定缓冲区对象,激活buffer
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    //顶点数组data数据传入缓冲区
    gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
    //缓冲区中的数据按照一定的规律传递给位置变量apos
    gl.vertexAttribPointer(aposLocation,2,gl.FLOAT,false,0,0);
    //允许数据传递
    gl.enableVertexAttribArray(aposLocation);
...
</script>


3.4 示例3:gl_FragColor

gl_FragColor内置变量主要用来设置片元像素的颜色,出现的位置是片元着色器语言的main函数中。

内置变量gl_Position的值是四维向量vec4(r,g,b,a),前三个参数表示片元像素颜色值RGB,第四个参数是片元像素透明度A,1.0表示不透明,0.0表示完全透明。

// 片元颜色设置为红色
gl_FragColor = vec4(1.0,0.0,0.0,1.0);

理解内置变量gl_Position需要建立逐顶点的概念,对于内置变量gl_FragColor而言,需要建立逐片元的概念。顶点经过片元着色器片元化以后,得到一个个片元,或者说像素点,然后通过内置变量gl_FragColor给每一个片元设置颜色值,所有片元可以使用同一个颜色值,也可能不是同一个颜色值,可以通过特定算法计算或者纹理像素采样。

根据位置设置渐变色

  void main() {
    // 片元沿着x方向渐变
    gl_FragColor = vec4(gl_FragCoord.x/500.0*1.0,1.0,0.0,1.0);
  }

纹理采样

// 接收插值后的纹理坐标
varying vec2 v_TexCoord;
// 纹理图片像素数据
uniform sampler2D u_Sampler;
void main() {
  // 采集纹素,逐片元赋值像素值
  gl_FragColor = texture2D(u_Sampler,v_TexCoord);
}

片元坐标gl_FragCoord
内置变量gl_FragCoord表示WebGL在canvas画布上渲染的所有片元或者说像素的坐标,坐标原点是canvas画布的左上角,x轴水平向右,y竖直向下,gl_FragCoord坐标的单位是像素,gl_FragCoord的值是vec2(x,y),通过gl_FragCoord.x、gl_FragCoord.y方式可以分别访问片元坐标的纵横坐标。

下面代码是把canvas画布上不同区域片元设置为不同颜色。

<!-- 片元着色器源码 -->
<script id="fragmentShader" type="x-shader/x-fragment">
  void main() {
    // 根据片元的x坐标,来设置片元的像素值
    if(gl_FragCoord.x < 300.0){
      // canvas画布上[0,300)之间片元像素值设置
      gl_FragColor = vec4(1.0,0.0,0.0,1.0);
    }else if (gl_FragCoord.x <= 400.0) {
      // canvas画布上(300,400]之间片元像素值设置
      gl_FragColor = vec4(0.0,1.0,0.0,1.0);
    }else {
      // canvas画布上(400,500]之间片元像素值设置
      gl_FragColor = vec4(0.0,0.0,1.0,1.0);
    }    
    // 所有片元设置为红色
    // gl_FragColor = vec4(1.0,0.0,0.0,1.0);
  }
</script>


片元的颜色随着坐标变化(设置一个渐变色效果)

<!-- 片元着色器源码 -->
<script id="fragmentShader" type="x-shader/x-fragment">
  void main() {
    // 片元沿着x方向渐变
    gl_FragColor = vec4(gl_FragCoord.x/500.0*1.0,1.0,0.0,1.0);
  }
</script>



3.5 渲染点片元坐标gl_PointCoord


        如果你想了解内置变量gl_PointCoord表示的坐标含义,就需要了解 GL绘制函数gl.drawArrays()的绘制模式参数gl.POINTS。

        绘制函数gl.drawArrays()绘制模式参数设置为点渲染模式gl.POINTS,WebGL会把顶点渲染为一个方形区域,在顶点着色器代码中可以通过内置变量gl_PointSize设置顶点渲染的方向区域像素大小。

        一个顶点渲染为一个方形区域,每个方形区域可以以方向区域的左上角建立一个直角坐标系,然后使用内置变量gl_PointCoord描述每个方形区域中像素或者说片元的坐标,比如方形区域的左上角坐标是(0.0,0.0),每个方形区域几何中心坐标是(0.5,0.5),右下角坐标是(1.0,1.0)。

        注意内置变量gl_PointCoord和gl_FragCoord表示的像素坐标含义不同,查看下图表示。


// 点绘制模式渲染10个顶点
gl.drawArrays(gl.POINTS,0,10);

顶点着色器中通过内置变量gl_PointSize设置点渲染的方形区域像素尺寸。

void main() {
  //点渲染的方形区域像素大小
  gl_PointSize = 20.0;
  ...
}


3.6 gl_PointCoord应用案例


        gl.POINTS绘制模式点默认渲染效果是方形区域,通过下面片元着色器代码设置可以把默认渲染效果更改为圆形区域。

<!-- 片元着色器源码 -->
<script id="fragmentShader" type="x-shader/x-fragment">
  precision lowp float;// 所有float类型数据的精度是lowp
  void main() {
    // 计算方形区域每个片元距离方形几何中心的距离
    // gl.POINTS模式点渲染的方形区域,方形中心是0.5,0.5,左上角是坐标原点,右下角是1.0,1.0,
    float r = distance(gl_PointCoord, vec2(0.5, 0.5));
    //根据距离设置片元
    if(r < 0.5){
      // 方形区域片元距离几何中心半径小于0.5,像素颜色设置红色
      gl_FragColor = vec4(1.0,0.0,0.0,1.0);
    }else {
      // 方形区域距离几何中心半径不小于0.5的片元剪裁舍弃掉:
      discard;
    }
  }

</script>

        通过gl_PointCoord返回的是片元纵横坐标vec2(x,y),自然通过xy分量gl_PointCoord.x、gl_PointCoord.y方式可以分别访问片元坐标的横坐标、纵坐标,
                        

四、GPU的内置函数

4. 1 内置函数列表

4.2 角度与三角函数

4.3 指数函数

4.4 通用函数


 

4.5 几何函数

4.6 矩阵函数

4.7 矢量函数

4.8 纹理查询函数

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PyTorch][chapter 20][李宏毅深度学习]【无监督学习][ GAN]【实战】

前言 本篇主要是结合手写数字例子,结合PyTorch 介绍一下Gan 实战 第一轮训练效果 第20轮训练效果,已经可以生成数字了 68 轮 目录&#xff1a; 谷歌云服务器&#xff08;Google Colab&#xff09; 整体训练流程 Python 代码 一 谷歌云服务器&#xff08;Google Colab&…

Open CASCADE学习|曲线曲面连续性

1、曲线的连续性 曲线的连续性是三维建模、动画设计等领域中非常重要的一个概念&#xff0c;它涉及到曲线在不同点之间的连接方式和光滑程度。下面将详细介绍曲线的连续性&#xff0c;包括C连续性和G连续性。 1.1C连续性&#xff08;参数连续性&#xff09; C连续性是指曲线…

使用MyBatisPlus实现向数据库中存储List类型的数据

使用MyBatisPlus实现向数据库中存储List类型的数据 问题描述 建表时&#xff0c;表中的这五个字段为json类型 但是在入库的时候既不能写入数据&#xff0c;也不能查询出数据。 解决方案&#xff1a; 1.首先明确&#xff0c;数据存入的时候是经过了数据类型转化&#xff0c…

数据之光:探索数据库技术的演进之路

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

喜讯!持安科技CEO何艺获评安全419《2023年度十大优秀创业者》

近日&#xff0c;由网络安全产业资讯媒体安全419主办的《年度策划》2023年度十大优秀创业者正式出炉&#xff0c;零信任办公安全技术创新企业持安科技创始人兼CEO何艺&#xff0c;获评十大优秀创业者。 这是安全419第二届推出该项目的评选活动&#xff0c;安全419编辑老师在多年…

抽象类、模板方法模式

抽象类概述 在Java中abstract是抽象的意思&#xff0c;如果一个类中的某个方法的具体实现不能确定&#xff0c;就可以申明成abstract修饰的抽象方法&#xff08;不能写方法体了&#xff09;&#xff0c;这个类必须用abstract修饰&#xff0c;被称为抽象类。 抽象方法定义&…

这些单片机汇编语言的错误,你还在犯错吗?

在单片机开发中&#xff0c;很多工程师会选择汇编语言来作为底层编程&#xff0c;来直接控制硬件和高校执行命令&#xff0c;然而因为汇编语言是直接与硬件交互&#xff0c;所以很容易出现错误&#xff0c;本文将基于Keil C51汇编器的环境总结单片机汇编语言常见的错误&#xf…

人工智能_大模型010_Centos7.9中CPU安装ChatGLM3-6B大模型_安装使用_010---人工智能工作笔记0145

从一个空的虚拟机开始安装: https://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/files 可以看到这里有很多的数据文件,那么这里 这里点击模型文件就可以下载,这个就是chatglm3-6B的文件,需要点击每个文件,然后点击右边的下载,把文件都下载下来 右侧有下载按钮.点击下载可…

使用Fabric创建的canvas画布背景图片,自适应画布宽高

之前的文章写过vue2使用fabric实现简单画图demo&#xff0c;完成批阅功能&#xff1b;但是功能不完善&#xff0c;对于很大的图片就只能显示一部分出来&#xff0c;不符合我们的需求。这就需要改进&#xff0c;对我们设置的背景图进行自适应。 有问题的canvas画布背景 修改后的…

【rust】11、所有权

文章目录 一、背景二、Stack 和 Heap2.1 Stack2.2 Heap2.3 性能区别2.4 所有权和堆栈 三、所有权原则3.1 变量作用域3.2 String 类型示例 四、变量绑定背后的数据交互4.1 所有权转移4.1.1 基本类型: 拷贝, 不转移所有权4.1.2 分配在 Heap 的类型: 转移所有权 4.2 Clone(深拷贝)…

Quartz 任务调度框架源码阅读解析

概念: quartz 是一个基于JAVA的定时任务调度框架 案例: <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.0</version></dependency>JobDetail job JobBuilder.newJob(Sc…

LeetCode 刷题 [C++] 第236题.二叉树的最近公共祖先

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以…

大数据分析案例-基于SVM支持向量机算法构建手机价格分类预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

矩阵爆破逆向之条件断点的妙用

不知道你是否使用过IDA的条件断点呢&#xff1f;在IDA进阶使用中&#xff0c;它的很多功能都有大作用&#xff0c;比如&#xff1a;ida-trace来跟踪调用流程。同时IDA的断点功能也十分强大&#xff0c;配合IDA-python的输出语句能够大杀特杀&#xff01; 那么本文就介绍一下这…

【JAVA】JDK内置工具之appletviewer

下载java 下载java的时候会先下载Java jdk&#xff0c;Java Development Kit Java开发工具包。 然后会下载jre&#xff0c;也就是Java Runtime Environment Java运行环境。什么是JDK、JRE&#xff1f;_java中的jdk,jre代表什么-CSDN博客 下载之后先找到java下的bin文件&#x…

yolov9 tensorRT 的 C++ 部署

yolov9 tensorRT C 部署 本示例中&#xff0c;包含完整的代码、模型、测试图片、测试结果。 完整的代码、模型、测试图片、测试结果【github参考链接】 TensorRT版本&#xff1a;TensorRT-7.1.3.4 导出onnx模型 导出适配本实例的onnx模型参考【yolov9 瑞芯微芯片rknn部署、地平…

网络爬虫的危害,如何有效的防止非法利用

近年来&#xff0c;不法分子利用“爬虫”软件收集公民隐私数据案件屡见不鲜。2023年8月23日&#xff0c;北京市高级人民法院召开北京法院侵犯公民个人信息犯罪案件审判情况新闻通报会&#xff0c;通报侵犯公民个人隐私信息案件审判情况&#xff0c;并发布典型案例。在这些典型案…

获取PDF中的布局信息——如何获取段落

PDF解析是极其复杂的问题。不可能靠一个工具解决全部问题&#xff0c;尤其是五花八门&#xff0c;格式不统一的PDF文件。除非有钞能力。如果没有那就看看可以分为哪些问题。 提取文本内容&#xff0c;提取表格内容&#xff0c;提取图片。我认为这些应该是分开做的事情。python有…

DataSpell 2023:专注于数据,加速您的数据科学之旅 mac/win版

JetBrains DataSpell 2023是一款专为数据科学家和数据分析师设计的集成开发环境&#xff08;IDE&#xff09;。这款IDE提供了强大的数据分析和可视化工具&#xff0c;旨在帮助用户更快速、更高效地进行数据科学工作。 DataSpell 2023软件获取 DataSpell 2023在保持其一贯的数…

【多线程】常见锁策略详解(面试常考题型)

目录 &#x1f334; 乐观锁 vs 悲观锁&#x1f38d;重量级锁 vs 轻量级锁&#x1f340;自旋锁&#xff08;Spin Lock&#xff09;&#x1f38b;公平锁 vs ⾮公平锁&#x1f333;可重⼊锁 vs 不可重⼊锁&#x1f384;读写锁⭕相关面试题 常⻅的锁策略 注意: 接下来讲解的锁策略不…