OpenGL之Shader编程入门

news2024/12/28 2:36:00

1.shader 编程基础

1.1 Vertex shader与Fragment shader
Vertex shader即顶点着色器,用来改变顶点的属性。Fragment shader即片元着色器,用来改变片元的颜色,在Direct3D中称为Pixel shader,像素着色器。

1.2 编程语言
面向OpenGL的GLSL语言,Cg语言,以及面向Direct3D的HLSL语言。Cg语言与HLSL语言语法基本上相同。

1.3 Vertex shader 功能
vertex shader 可以控制如下方框中的通道对应的属性信息,包括几何变换、投影变换、光照计算等。
在这里插入图片描述

1.4 Fragment shader功能
Fragment shader的功能如下。
在这里插入图片描述
主颜色与辅助颜色(Primary Color、Secondary Color):设置辅助颜色的目的是将Specular颜色与Ambient、Diffuse颜色分开;

  • 在典型的光照计算中,分别计算ambient、diffuse、specular和自发光的值,让后进行叠加;而在这之后进行纹理映射的话,specular可能会被覆盖(弱化)。
  • 为了解决这个问题,OpenGL中提供了glLightModelfv(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)函数,调用函数可以将每个顶点的光照计算分为主颜色和辅助颜色,主颜色包含所有非镜面反射光照的总贡献,而辅助颜色为镜面反射光照的贡献。
  • 纹理映射的时候只将主颜色和辅助颜色混合起来,执行完纹理映射后,再将主颜色和纹理颜色混合的结果与辅助颜色混合起来。

Fragment shader可以做片元测试,但实际中可以交给固定管线来做。在新版本中alpha测试需要在Frgment shader来做,固定管线已经废弃。可以使用discard来做alpha测试。

//alpha 值小于0.1f。该片元将被丢弃
if(vColorValue.a < 0.1f)
{
	discard;
}

1.5 vertex shader 与Fragment shader案例

  • vertex shader
void main(void{
	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_vertex;
}
uniform float time;
void main(void{
	vec4 v = gl_Vertex;
	v.z = sin(5.0 * v.x * time ) * 0.25;
	gl_Position = gl_ModelViewMatrix * v;
}
  • fragment shader
//改变颜色
void main(void)
{
	gl_FragColor = vec4(0.0,1.0,0.0,1.0);
}

2.OpenGL中的shader编程

2.1 OpenGL通过引入扩展库 glew来更方便的进行shader编程。
glew下载地址:http://glew.sourceforge.net/,对下载的源码进行编译生成lib和dll即可引用。

2.2 检测显卡是否支持shader编程

if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
{
	printf("Ready for glsl\n");
{

2.3 将shader代码可以在C++源代码文件中存储在字符串变量中,也可将shader代码编写到独立的文件中,然后将文本文件读取到字符串中即可。

2.4 两个概念

  • 着色器对象(shader):一个着色器对象对应一个shader程序;
  • 着色器程序(program):可以装载多个着色器对象;

shader编程主要过程:

  • 创建着色器对象;
  • 将着色器源代码装载入着色器对象;
  • 将源代码编译为目标代码;
  • 创建着色器程序;
  • 将着色器对象附加到着色器程序中;
  • 链接着色器程序;
    在这里插入图片描述http://www.lighthouse3d.com.tutorials/glsl-tutorial/

2.5 shader编程

glUseProgram(GL_shaderProgram);
//释放
glUseProgram(0);
  • 检测编译是否正确
//获取编译错误,存放到param中
glGetShaderiv(GLuint objec,GLenum type ,int* param);
type : GL_COMPILE_STATUS
  • 检查链接是否正确
glGetProgramiv(GLuint objec,GLenum type ,int* param)
type : GL_LINK_STATUS
  • 获取日志Infolog
glGetSHaderInfoLog(GLuint objec,int maxLen ,int* len,char* log);
glGetProgramInfoLog(GLuint objec,int maxLen ,int* len,char* log);
  • 清除
glDetachShader(GLuint program,GLuint shader);
glDeleteShader(GLuint id);
glDeleteProgram(GLuint id);

3.VS与FS之间的数据流
vertex shader代码只需要编写对单个顶点的操作即可,GPU会自动将其作用到其他顶点上;fragment shader只需要编写对单个片元的操作即可。
在这里插入图片描述

  • VS的输入:针对顶点的属性、一致型变量(uniform)(对所有顶点都一样);
  • VS的输出:针对顶点的数据;
  • FS的输入:针对片元的属性、一致型变量(uniform)(对所有片元都一样);
  • FS的输出:gl_FragColor、gl_FragDepth 、…;

编写shader时,内建的变量以gl开头,可以直接使用。而自定义的变量,从程序中传入。

  • 代码程序,如下进行time以及vertCol变量的传递,与VS中的同名变量绑定。
glUseProgram(GL_shaderProgram);
//取得shader代码中的time变量的location
time_location = glGetUniformLocation(G_shaderProgram,"time");
//将time_location与程序中定义的变量shaderTime进行关联,则shaderTime的值就可以传递到time,即可对shaderTime进行操作即可;
glUniform1f(time_location,shaderTime);

//取得shader中vertCol变量的localtion
vertCol_location = glGetAttributeLocation(G_shaderProgram,"vertCol");

//通过函数将值进行传递
glVertexAttrib4f(vertCol_location ,1.0f,0.0f,0.0f,0.0f);
  • vertex shader程序
uniform float time;
in vec4 vertCol; // 表述输入数据
out vec4 col;	 //输出数据;

void main(void)
{
	vec4 v = gl_Vertex;
	v.y += time * 0.1;
	col = vertCol;
	gl_Position  = gl_ModelViewProjectionMatrix * v;
}
  • fragment shader程序
in vec4 col;	//与vertxe中col对应
void main(void)
{
	gl_FragColor = col;
}

4.VS/FS的输入与输出变量

4.1 可以传输给VS的数据

  • 内建的uniform变量,如gl_ModelViewMatrix;只读类型;
    在这里插入图片描述

  • 内建的顶点属性变量(in 类型),如gl_Vertex;只读。
    在这里插入图片描述

  • 自己定义的uniform 类型变量,需要人为赋值,如下进行赋值操作。
    在这里插入图片描述

  • 自己定义的in类型变量,并进行赋值操作;也可以利用内建的变量来传递,如rgba中的a分量;

in vec4 vertMass;

在这里插入图片描述

  • 纹理数据;

shader编程还是内嵌到固定流水线当中,内建变量的值还是来自固定流水线。

4.2 VS的输出

  • 特定变量(Special Output Variables);可读可写;
    在这里插入图片描述

  • 内建顶点属性变量(加out限定符);可读可写;
    在这里插入图片描述

  • 自定义的顶点属性变量(加out限定符);

4.3 FS输入

  • 内建的uniform变量;
  • 内建的in类型变量;
  • 其他
    在这里插入图片描述

4.4 FS的输出
在这里插入图片描述
可以将缓冲数据绘制到gl_FragData,后面通过gl_FragData获取绘制到缓冲区的数据;

5.VS的out变量与FS的in变量的对应
在这里插入图片描述
6.总结
在这里插入图片描述

附录:图形编程技术,北京林业大学,杨刚

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

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

相关文章

C语言快速互转HEX(16进制)和原始字符串/数组

C语言快速互转HEX&#xff08;16进制&#xff09;和原始字符串/数组缘由这个起因是昨晚群里有人在讨论怎么把字符串转成HEX方法最佳&#xff0c;讨论到最后变成哪种方法效率最优了。毕竟这代码是要在MCU上面跑的&#xff0c;要同时考虑到时间和空间的最优解。当然讨论的是有结果…

Java8流式计算相关

目录 lambda 优点 语法介绍 语法格式一 : 语法格式二 : 语法格式三 : 语法格式四 : 语法格式五 : 语法格式六 : 方法引用 stream Stream流的常用方法&#xff1a; 创建动态list 创建固定长度list map filter groupingBy sum list转map&#xff1a; map转li…

谷粒商城学习笔记

docker 安装docker docker官方centos镜像下载地址&#xff1a;https://docs.docker.com/engine/install/centos/ 步骤&#xff1a; 先卸载&#xff0c;如果不是root用户在前边加上sudo sudo yum remove docker \docker-client \docker-client-latest \docker-common \docke…

C 程序设计教程(05)—— C 语言的数据类型(三):指针类型

C 程序设计教程&#xff08;05&#xff09;—— C 语言的数据类型&#xff08;三&#xff09;&#xff1a;指针类型 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用…

MySql中json类型数据的查询以及在MyBatis-Plus中的使用

表结构和初始数据 新建表结构 CREATE TABLE json_test (id int NOT NULL AUTO_INCREMENT,roles json DEFAULT NULL COMMENT 角色,project json DEFAULT NULL COMMENT 项目,PRIMARY KEY (id) ) ENGINEInnoDB;初始数据 INSERT INTO ctts_dev.json_test(id, roles, project) VALU…

SpringBoot 整合 xxl-job

文章目录部署 xxl-jobSpringBoot 配置maven 配置application.yaml配置 XxlJobConfigXxlJobSpringExecutor新建执行任务配置 xxl-job-admin执行器管理任务管理部署 xxl-job K8S 部署 xxl-job 参考文档&#xff1a;https://blog.csdn.net/weixin_42555971/article/details/12489…

【Web开发】Python实现Web服务器(Docker下部署Flask)

&#x1f37a;基于Python的Web服务器系列相关文章编写如下&#x1f37a;&#xff1a; &#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask快速入门&#xff09;&#x1f388;&#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask案例测试&#xff09;&a…

分享112个PHP源码,总有一款适合您

PHP源码 分享112个PHP源码&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1MaBtjYZk08o0eJT5_E79aQ?pwduldm 提取码&#xff1a;uldm 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载…

实战丨从0到1搭建结算平台

一、概述我们最开始分享了O2O电商支付清结算体系&#xff0c;接着分享了如何从0-1搭建计费体系&#xff0c;接下来我们分享&#xff1a;各方的钱算完之后怎么付出去&#xff0c;也即结算平台建设的实操与设计思路。1.什么是结算&#xff1f;说结算平台之前&#xff0c;先说一下…

22年 | 年前总结 | 主业谋生存,副业谋发展

22年关键词 复盘 | 极简 | 长期主义 | 阅读 | 斜杠青年 | 一事无成 | … 当然了&#xff0c;2023也会继续延续某些关键词。 一壶清酒&#xff0c;敬这红尘也敬我 很多人都在说&#xff0c;疫情存在的时间比任何一段恋情还要长。 而我想说&#xff0c;我失败的次数还超过了做…

Java设计模式中策略模式是怎么回事/怎么替代繁琐if-else语句/如何优化条件选择语句

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.3 策略模式 6.3.1 概述 定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替代&#xff0c;且算法的变化不会影响使用算法的用户属…

【自学Python】Python注释

文章来源嗨客网&#xff08;www.haicoder.net&#xff09; Python注释 Python注释教程 用于注解说明解释程序的文字就是注释&#xff0c;注释提高了代码的阅读性。一旦程序中某部分内容被注释掉&#xff0c;则该内容将会被 Python 解释器忽略&#xff0c;换句话说&#xff0c…

一般颜色直方图

颜色直方图是一种用于图像处理和分析的图表&#xff0c;它可以显示图像中不同颜色的数量。通常&#xff0c;颜色直方图会将颜色分成几个色调区间&#xff0c;每个区间对应一个条形图&#xff0c;其中条形图的高度表示该色调区间中的像素数量。通过颜色直方图&#xff0c;你可以…

Mask RCNN网络源码解读(Ⅰ) --- 语义分割前言与转置卷积

目录 1.什么是语义分割 2.语义分割常见的数据集格式 3.常见的语义分割评价指标 4.转置卷积 1.什么是语义分割 常见分割任务&#xff1a;语义分割、实例分割、全景分割 图一 原始图片图二 语义分割图三 实例分割语义分割&#xff08;例如FCN网络&#xff09;可以理解为一个…

开发与项目经理之间的打情骂俏——数据库篇

&#x1f466;&#x1f466;一个帅气的boy&#xff0c;你可以叫我Love And Program &#x1f5b1; ⌨个人主页&#xff1a;Love And Program的个人主页 &#x1f496;&#x1f496;如果对你有帮助的话希望三连&#x1f4a8;&#x1f4a8;支持一下博主 由数据库引发的一系列探…

小论文写作指南(AI类)

参考b站沃恩智慧课程 论文结构 标题:不要太长或太短,抓住重点,简明扼要。 作者:你的作品一定力争一作,通讯作者是导师/大老板/出资人。 摘要Abstract:点明大背景(如为什么研究微表情识别,对社会有什么价值,拔高立意层次),阐述目标(我们提出模型为了在什么问题上达…

9个时间序列交叉验证方法的介绍和对比

评估性能对预测模型的开发至关重要。交叉验证是一种流行的技术。但是在处理时间序列时&#xff0c;应该确保交叉验证处理了数据的时间依赖性质。在之前的文章中&#xff0c;我们也做过相应的介绍。 在本文中&#xff0c;我们收集了时间序列的常用的9种交叉验证方法。这些包括样…

【博客578】LVS NAT配合MASQUERADE实现FULLNAT的场景,及此场景下net.ipv4.vs.conntrack参数的重要作用

LVS NAT配合MASQUERADE实现FULLNAT的场景&#xff0c;及此场景下net.ipv4.vs.conntrack参数的重要作用 1、LVS基本原理&#xff1a; 流程&#xff1a; 当用户向负载均衡调度器&#xff08;Director Server&#xff09;发起请求&#xff0c;调度器将请求发往至内核空间 PREROU…

第6章 线程通信

6.2.1 管道 管道是一个线性字节数组,类似文件,使用文件读写进行访问&#xff1b;在程序里面,创建管道需要使用popen()或者pipe(); 管道的一个重要特点是使用管道的两个线程之间必须存在某种关系, 例如,使用popen需要提供另一端进程的文件名,使用pipe的两个线程分别隶属于父子进…

Linux常用命令——fgrep命令

在线Linux命令查询工具 fgrep 为文件搜索文字字符串 补充说明 fgrep命令是用来搜索 file 参数指定的输入文件&#xff08;缺省为标准输入&#xff09;中的匹配模式的行。fgrep 命令特别搜索 Pattern 参数&#xff0c;它们是固定的字符串。如果在 File 参数中指定一个以上的…