【 OpenGL 教程06 】 关于着色器(01)

一、说明

   着色器是目前做3D图形最流行的方式。而对应的OpenGL操作晦涩难懂,本篇试图参照一些相关解释文档,以及一个代码案例进行分解说明。

二、OpenGL的渲染管线流程

   数据传输到显示环节的数据流程。

  •    OpenGL—>顶点处理器—>细分着色—>几何处理器—>图元装配—>裁剪器—>光栅器(片段处理器)

三、着色器Shader简述

3.1 Shader注意事项

   一些Shader的注意:Shader着色器的使用跟C/C++程序的创建过程类似。

  1.    写一个shader着色器文本并使其在你的程序中有效可用
  2.    Shader着色器文本全为字符串类型 例如 S = “ coding部分” 代码部分为字符串
  3.    将字符串编译为Shader对象
  4.    使用GLSL编译器(编译器的语法见《OpenGL编程指南》 原书第8版 王锐译)

3.2 Shader对象

   对于每一个着色器程序需要进行下面的步骤设置:
   对于着色器对象:
1、   创建Shader对象
2、   编译
3、   验证编译成功?

3.3 Shader连接

   将上述的着色器对象链接为一个着色器程序:

1、   创建程序
2、   将Shader对象关联到着色器程序
3、   链接程序
4、   判断链接是否成功
5、   使用着色器处理数据

四、程序案例

__author__ = "WSX"import numpy as np
from OpenGL.GLUT import *
from OpenGL.GL import *
import ctypes
#顶点着色器部分
VERTEX_SHADER = """
#version 330layout (location = 0) in vec3 Position;void main()
{gl_Position = vec4(0.4 * Position.x, 0.5 * Position.y, Position.z, 1.0);}
"""
#片段着色器部分,字符串类型
FRAGMENT_SHADER = """
#version 330
out vec4 FragColor;
void main()
{FragColor = vec4(1.0, 1.0, 0.0, 1.0);}
"""
def Create_Shader( ShaderProgram, Shader_Type , Source):  #创建并且添加着色器(相当于AddShader)Shader_Type为类型ShaderObj = glCreateShader( Shader_Type )  #创建Shader对象glShaderSource(ShaderObj , Source)glCompileShader(ShaderObj)  #进行编译glAttachShader(ShaderProgram, ShaderObj)  #将着色器对象关联到程序上def Compile_Shader():  #编译着色器Shader_Program = glCreateProgram()  #创建空的着色器程序Create_Shader(Shader_Program , GL_VERTEX_SHADER , VERTEX_SHADER)Create_Shader(Shader_Program , GL_FRAGMENT_SHADER , FRAGMENT_SHADER)glLinkProgram(Shader_Program)glUseProgram(Shader_Program)def Draw():glClear(GL_COLOR_BUFFER_BIT)glEnableVertexAttribArray(0)glBindBuffer(GL_ARRAY_BUFFER, VBO)glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None) #这里的None不能写为0glDrawArrays(GL_TRIANGLES, 0, 3)glDisableVertexAttribArray(0)  #解析数据 例如一个矩阵里含有 位置 、颜色、多种信息glutSwapBuffers()def CreateBuffer():  #创建顶点缓存器global VBO   #设置为全局变量vertex = np.array([[-1.0,-1.0,0.0],[1.0,-1.0,0.0],[0.0,1.0,0.0]],dtype="float32")   #创建顶点数组VBO = glGenBuffers(1)  #创建缓存glBindBuffer(GL_ARRAY_BUFFER , VBO)   #绑定glBufferData(GL_ARRAY_BUFFER , vertex.nbytes , vertex , GL_STATIC_DRAW)   #输入数据def main():glutInit([])glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)  # 显示模式 双缓存glutInitWindowPosition(100, 100)  # 窗口位置glutInitWindowSize(500, 500)  # 窗口大小glutCreateWindow("sanjiao")  # 创建窗口glutInitContextVersion(4,3)   #为了兼容glutInitContextProfile(GLUT_CORE_PROFILE)   #为了兼容glutDisplayFunc(Draw)  # 回调函数glClearColor(0.0, 0.0, 0.0, 0.0)CreateBuffer()Compile_Shader()glutMainLoop()main()

结果:

五、着色器代码解释

(字符串)
#version 330

   这告诉编译器我们的目标是3.3版的GLSL。如果编译器不支持它,它会发出错误。

layout (location = 0) in vec3 Position;

   该语句出现在顶点着色器中。它声明了一个顶点特定属性,它是3个浮点数的向量,在着色器中将被称为’位置’。“特定于顶点”表示对于GPU中每个对着色器的调用,将提供缓冲区中新顶点的值。
layout (location = 0)创建缓冲区中属性名称和属性之间的绑定。

   您可以通过将多个着色器对象链接在一起来创建着色器。但是,每个着色器阶段(VS,GS,FS)只能有一个主要函数,用作着色器的入口点。例如,您可以创建一个具有多个函数的光照库,并将其与着色器链接,前提是这些函数中没有任何一个函数名为“main”。

gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0);

   这里我们对输入的顶点位置进行硬编码转换。我们将X和Y值减半,并保持Z不变。'gl_Position’是一个特殊的内置变量,它应该包含齐次(包含X,Y,Z和W分量)顶点位置。光栅化器将查找该变量并将其用作屏幕空间中的位置(在进行了几次转换之后)。将X和Y值减半意味着我们将看到一个三角形,它是前一教程中三角形大小的四分之一。请注意,我们将W设置为1.0。这对于正确显示三角形非常重要。从3D到2D的投影实际上分两个阶段完成。首先,您需要将所有顶点乘以投影矩阵(我们将在一些教程中开发),然后GPU在位置属性到达光栅化器之前自动执行所谓的“透视分割”。这意味着它将W组件的所有组件分割成W组件。在本教程中,我们尚未在顶点着色器中进行任何投影,但透视分割阶段是我们无法禁用的。无论我们从顶点着色器输出的gl_Position值是用HW分量还是HW分量。我们需要记住,否则我们不会得到我们期望的结果。为了规避视角分割的影响,我们将W设置为1.0。由1除。

   如果一切工作正常,则具有值(-0.5,-0.5),(0.5,-0.5)和(0.0,0.5)的三个顶点到达光栅器。裁剪器不需要做任何事情,因为所有的顶点都在标准化的框内。这些值被映射到屏幕空间坐标,并且光栅化器开始运行三角形内的所有点。对于每个点,执行片段着色器。以下着色器代码是从片段着色器中获取的。

out vec4 FragColor;

   通常片段着色器的工作是确定片段(像素)的颜色。此外,片段着色器可以完全丢弃像素或更改其Z值(这会影响后续Z测试的结果)。通过声明上述变量来输出颜色。四个分量表示R,G,B和A(对于alpha)。您设置到该变量中的值将由光栅化器接收并写入帧缓冲区。

FragColor = vec4(1.0, 0.0, 0.0, 1.0);

   在之前的几个教程中,没有片段着色器,因此所有内容都以白色的默认颜色绘制。在这里,我们将FragColor设置为红色。

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

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

相关文章

C语言:指针(一)

目录 1.内存和地址2. 指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 解引用操作符(*) 2.3 指针变量的大小 3.指针变量的类型和意义3.1 指针的解引用3.2 指针 -指…

[云] vmware: latency的设置

https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vm-administration/GUID-F5DAC793-7B13-418F-949E-0CD80CEC5D1E.html Configure the Virtual Machine Latency Sensitivity 如果虚拟机上的业务,需要敏感的网络延迟,就需要设置这个参数来做调整…

【MogDB】将流行的博客系统Halo后端的数据库设置为MogDB

前言 本人的个人博客站点(https://www.darkathena.top )基于Halo博客系统搭建,该博客系统后端可以配置多种数据库,默认为H2,但是最新版已不建议使用H2,而是建议使用mysql/postgresql等数据库。经验证&…

【PyTorch][chapter 17][李宏毅深度学习]【无监督学习][ Auto-encoder]

前言: 本篇重点介绍AE(Auto-Encoder) 自编码器。这是深度学习的一个核心模型. 自编码网络是一种基于无监督学习方法的生成类模型,自编码最大特征输出等于输入 Yann LeCun&Bengio, Hinton 对无监督学习的看法. 目录: AE 模型原…

FPGA OSERDESE2

Output Parallel-to-Serial Logic Resources (OSERDESE2) OSERDESE2 在Xilinx 7 系列器件是一款专用的并行至串行转换器,具有特定的时钟和逻辑资源,旨在促进高速源同步接口的实现。每个OSERDESE2模块都包括一个专用的数据串行器和 3 状态控制。数据和 3 态串行器都可以在 SD…

Edwards爱德华STP系列-A1603分子泵使用维修保养说明

Edwards爱德华STP系列-A1603分子泵使用维修保养说明

注意pytorch的原地操作

常见的原地操作:nn.ReLu(inplaceTrue) a torch.randn(2) # tensor([-0.3690, 0.0626]) b a.clone() # tensor([-0.3690, 0.0626]) c a # tensor([-0.3690, 0.0626]) relu nn.ReLu(inplaceTrue)情况1 out relu(a) # tensor([0.0000, 0.0626]) a # tensor([…

前端基础自学整理|DOM树

DOM,文档对象模型(Document Object Model),简单的说,DOM是一种理念,一种思想,一个与系统平台和编程语言无关的接口,一种方法, 使 Web开发人员可以访问HTML元素!不是具体方…

Flask数据库操作-Flask-SQLAlchemy

Flask中一般使用flask-sqlalchemy来操作数据库。flask-sqlalchemy的使用介绍如下: 一、SQLAlchemy SQLALchemy 实际上是对数据库的抽象,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销…

NXP实战笔记(四):S32K3xx如何产生中心对称三相六路波形

目录 1、概述 1.1、理论基础 2、RTD实现 2.1、Emios时基配置 2.1.1、EmiosMcl 2.1.2、EmiosCommon 2.2、Emios PWM配置 2.3、TRGMUX 2.4、LCU 2.5、外设信号配置 3、代码实现 4、测试结果 1、概述 电机控制中需要产生三相六路SVPWM进行占空比与周期调制,怎么通过RT…

Nginx----高性能的WEB服务端

一、Nginx介绍 1、什么是Nginx Nginx Nginx是一个高性能的HTTP和反向代理服务器。是一款轻量级的高性能的web服务器/反向代理服务器/电子邮件(IMAP/POP3)代理服务器,单台物理服务器可支持30 000~50 000个并发请求。 一款高性能…

(done) Positive Semidefinite Matrices 什么是半正定矩阵?如何证明一个矩阵是半正定矩阵? 可以使用特征值

参考视频:https://www.bilibili.com/video/BV1Vg41197ew/?vd_source7a1a0bc74158c6993c7355c5490fc600 参考资料(半正定矩阵的定义):https://baike.baidu.com/item/%E5%8D%8A%E6%AD%A3%E5%AE%9A%E7%9F%A9%E9%98%B5/2152711?frge_ala 看看半正定矩阵的…

C#_值类型与引用类型 及 值参数与引用参数

值类型与引用类型 栈帧和对象内部都维护着符号表,依变量的标识符查询符号表可知地址偏移量 对于成员变量而言,可得相对于所属对象地址的地址偏移量 对于局部变量而言,可得相对于帧指针所指地址的地址偏移量(关于栈指针和帧指针:栈…

Java学习笔记2024/2/21

题目1 现有如下字符串元素:["aaa", "bbb", "aaa", "aaa", "ccc", "bbb"],请将所有的元素按顺序存入ArrayList集合中,并遍历集合查看存储结果。 训练目标 ArrayList集合存储字…

Milvus数据库介绍

参考:https://www.xjx100.cn/news/1726910.html?actiononClick Milvus 基于FAISS、Annoy、HNSW 等向量搜索库构建,核心是解决稠密向量相似度检索的问题。在向量检索库的基础上,Milvus 支持数据分区分片、数据持久化、增量数据摄取、标量向量…

基于Java在线宠物店商城系统设计与实现(源码+部署文档)

博主介绍: ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到 Java项目精品实…

Redis的常见面试题

目录 前言 Redis支持哪些数据类型 五种核心类型 Zset为什么用跳表不用红黑树 ? Redis常见的应用场景? 如何检测Redis的连通性? 如何设置key的过期时间? Redis为什么是单线程模型? Redis里的IO多路复用是什…

惠尔顿安全审计系统任意文件读取漏洞

免责声明:文章来源互联网收集整理,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该…

(delphi11最新学习资料) Object Pascal 学习笔记---第5章第3节(运算符重载)

5.3.4 运算符重载 ​ 另一个与记录相关的 Object Pascal 语言特性是运算符重载,即在数据类型上自己定义标准操作(加法、乘法、比较等)的能力。基本思想是你可以实现一个加法运算符(一个特殊的 Add 方法),然…

【VIP专属】Python应用案例——基于TensorFlow 2.3建立RNN搭配Word2Vec Embedding进行文本分类

目录 一、数据准备 二、实验流程 1、加载数据集 ​2、分词处理