c语言opengles程序,OpenGL ES _ 着色器_程序

5gUAjZkpscARYRVd.png

演示图

你不知道这个东西,请不要看了,请看我的其他文章先了解一下O!

学习目标

掌握着色器程序的执行过程

简单的例子

``

uniform float t; // 时间

uniform mat4 gl_ModelViewMatrix; // 模型视图矩阵

attribute vec4 vel;

const vec4 g = vec4(0.0,-9.8,0.0) // 重力加速度

void main()

{

vec4 position = vel;

position += t*vel + t*t*g;

gl_Position = gl_ModelViewMatrix * position;

}

稍微解释一下:代码的作用是模拟重力加速度,对一个点的位置进行变换.

OpenGL /GLSL 程序接口

先上图

ofzuFZcW5cdtIu28.png

着色器创建流程

C语言,大家应该很熟悉吧! C 语言的编译过程步骤:

1.编译器检查错误

2.将他转换成目标代码(.o文件)

3.将一组目标文件进行链接,最后成为一个可执行文件

在OpenGL 程序中使用GLSL 着色器也是一个相似的过程,要在应用程序中使用顶点或者片段着色器需要按照**顺序**执行下面的步骤:

1.创建着色器对象

2.把着色器代码编译成源代码

3.验证是否着色器是否编译成功

为了把多个着色器对象链接起来,我们需要创建着色器程序

4.创建一个着色器程序

5.把着色器对象链接到这个着色器程序中

6.链接着色器

7.验证着色器链接阶段已经成功完成.

8.使用着色器进行顶点或者片段处理.

函数讲解 (用到的主要是C语法)

GLUint glCreateShader(GLenum type);

作用:创建着色器对象

type 类型值两个: GL_VERTEX_SHADER(顶点做色器) 和 GL_VERTEX_SHADER(片段着色器) 返回一个非零的值,作为着色器的标记

void glShaderSource(GLuint shader,GLsizei count,const GLchar**string,const Glint* length);

作用:创建着色器对象后,需要把着色器的源代码和着色器对象关联

参数1:shader 就是创建着色器成功返回的那个值

参数2:count 包含多个字符串,一般就1个字符串

参数3:字符串数组地址

参数4:,可以为NULL 代表字符串为NULL 结尾的,否则,length就代表具有就有count个元素,每个元素指定了string中对应字符串的长度,如果length数组中的某个元素对应一个正整数,就代表string数组中对应字符串的长度,如果是负整数,对应的字符串就是以NULL 结尾的.

void glCompileShader(GLuint shader)

作用:编译着色器源代码

参数 : shader 着色器标示

glGetShaderiv (GLuint shader, GLenum pname, GLint* params)

作用: 查询编译结果

参数1:shader 着色器标识

参数2:GL_COMPLE_STATUS

参数3:查询结果返回

void glGetShaderInfoLog(GLuint shader,GLsizei bufsize,GLsizei length ,char infoLog);

作用: 获取编译相关日志,调试情况下使用

参数1: shader 着色器对象标识

参数2: bufsize 最大日志长度

参数3: length 如果为NULL 不返回任何日志

参数4:infoLog 保存在缓冲区中

GLuint glCreateProgram()

作用:创建空的着色器程序

返回:非零,如果是0 则创建失败

void AttachShader(GLuint program,GLuint shader);

作用: 把着色器和程序相关联

参数1:program 着色器程序标识

参数2:shader 着色器对象标识

void glDetachShader(GLuint program,Gluint shader);

作用: 把着色器对象从着色器程序中分离出来,以更改着色器的操作。

参数1:program 着色器程序标识

参数2:shader 着色器对象标识

void glLinkProgram()

作用:在着色器对象都连接到着色器程序之后,就要把这些对象连接成一个可执行程序.

void glGetProgramInfoLog(GLuint program,GLsizei bufsize,GLsize length char infoLog)

作用:连接着色器程序也可能出现错误,我们需要进行查询,获取错误日志信息

参数1: program 着色器程序标识

参数2: bufsize 最大日志长度

参数3: length 如果为NULL 不返回任何日志

参数4:infoLog 保存在缓冲区中

void glGetProgramiv (GLuint program, GLenum pname, GLint* params)

作用:查询程序连接后的结果

参数1:program 着色器程序标识

参数2: GL_LINK_STATUS

参数3:params 返回状态

void glUserProgram(GLuint program)

作用: 程序连接成功后,就可以调用这个函数,启动这个顶点或者片段着色器程序了,为了恢复使用固定功能的管线,可以向这个函数传递 0作为参数.

void glDeleteShader(GLuint shader)

作用:删除着色器对象,如果这个着色器对象被多个程序连接,一旦程序不再使用这个对象,那么它便会实际删除

参数: shader 着色器对象标识

void glDeleteProgram(GLuint program)

作用: 删除着色器程序 ,如果这个着色器未在任何渲染环境中使用,它将立即删除。否则,会标记为删除,一旦它没不被使用了,便立即被删除

void GLboolean glIsShader(GLuint shader)

作用: 如果shader 是一个着色器对象名称,则返回GL_TRUE, 否则返回GL_FALSE

void GLboolean glIsProgram(GLuint program)

作用: 如果program 是一个着色器程序,则返回GL_TRUE ,否则返回GL_FALSE

void glValidateProgram(GLuint program)

作用:用于验证一个着色器程序是否可以在当前OpenGL 环境下使用,验证结果查询,使用glGetProgramiv() 传入参数GL_VALIDATE_STATUS 为参数,查询程序验证结果

IOS 代码上一份方便大家理解

导入shader的步骤

第一步. 创建GLuint 类型的shader 标示

第二步. 获取shader 文件所在的路径

第三步 获取文件的内容 并进行NSUTF8StringEncoding 编码

第四步. 根据类型创建shader 着色器对象

第五步. 关联shader着色器源代码

第六步. 编译shader着色器对象源代码

第七步. 检查着色器源代码编译是否成功

第八步. 创建着色器程序

第九步. 将编译好的着色器目标文件链接到程序中去

第十步. 绑定着色器的属性

第十一步. 将着色器和程序分开,并且释放着色器

步骤就是多,最好封装好,不重复敲代码才是王道

``

- (BOOL)loadShaders

{

// 第一步.创建标示

GLuint vertShader, fragShader;

// 第二步.获取文件路径

NSString *vertShaderPathname, *fragShaderPathname;

vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];

if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {

NSLog(@"编译失败 vertex shader");

return NO;

}

// 创建 编译 片断着色器对象

fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];

if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {

NSLog(@"Failed to compile fragment shader");

return NO;

}

// 第八步 创建一个着色器空程序

_program = glCreateProgram();

// 第九步 将顶点着色器链接到程序中

glAttachShader(_program, vertShader);

// 将片断着色器链接到程序中

glAttachShader(_program, fragShader);

//第十步 绑定着色器的属性

glBindAttribLocation(_program, GLKVertexAttribPosition, "position");

glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");

if (![self linkProgram:_program]) {

NSLog(@"Failed to link program: %d", _program);

if (vertShader) {

glDeleteShader(vertShader);

vertShader = 0;

}

if (fragShader) {

glDeleteShader(fragShader);

fragShader = 0;

}

if (_program) {

glDeleteProgram(_program);

_program = 0;

}

return NO;

}

// Get uniform locations.

uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");

uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");

// 第十三步 . 分离释放顶点着色器对象 和片段着色器对象

if (vertShader) {

glDetachShader(_program, vertShader);

glDeleteShader(vertShader);

}

if (fragShader) {

glDetachShader(_program, fragShader);

glDeleteShader(fragShader);

}

return YES;

}

-(BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file

{

//第三步 获取文件的内容 并进行NSUTF8StringEncoding 编码

const GLchar *source;

source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];

if (!source) {

NSLog(@"Failed to load vertex shader");

return NO;

}

//第四步 根据类型创建着色器对象

*shader = glCreateShader(type);

//第五步. 获取着色器源代码和着色器关联

glShaderSource(*shader, 1, &source, NULL);

//第六步. 开始编译着色器源代码

glCompileShader(*shader);

#if defined(DEBUG)

GLint logLength;

glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0) {

GLchar *log = (GLchar *)malloc(logLength);

glGetShaderInfoLog(*shader, logLength, &logLength, log);

NSLog(@"Shader compile log:\n%s", log);

free(log);

}

#endif

//第七步. 查看是着色器源代码否编译成功

GLint status;

glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);

if (status == 0) {

glDeleteShader(*shader);

return NO;

}

return YES;

}

- (BOOL)linkProgram:(GLuint)prog

{

// 第十一 链接程序

glLinkProgram(prog);

#if defined(DEBUG)

GLint logLength;

glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0) {

GLchar *log = (GLchar *)malloc(logLength);

glGetProgramInfoLog(prog, logLength, &logLength, log);

NSLog(@"Program link log:\n%s", log);

free(log);

}

#endif

// 第十二步 检查着色器程序链接结果

GLint status;

glGetProgramiv(prog, GL_LINK_STATUS, &status);

if (status == 0) {

return NO;

}

代码下载地址

点我下载

参考

OpenGL 编程指南>

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

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

相关文章

spring IOC加载流程

看了网上、书上很多对于spring IOC容器加载过程的分析。大多都只是粗略的讲一下加载流程。其实这样也不错,简单粗暴。清晰记得之前和一个前辈交流时他说的一句话:什么设计模式、设计框架都是扯淡,能实现这个功能就是最好的。其实这样的说法是…

pytorch 模型可视化_【深度学习】高效使用Pytorch的6个技巧:为你的训练Pipeline提供强大动力...

作者:Eugene Khvedchenya 编译:ronghuaiyang导读只报告模型的Top-1准确率往往是不够的。将train.py脚本转换为具有一些附加特性的强大pipeline每一个深度学习项目的最终目标都是为产品带来价值。当然,我们想要最好的模型。什么是“最好的”…

tstringlist怎么查看是否存在该数据_注意!研究生招生信息只公开1个月!应该怎么用?...

请注意!全国硕士研究生招生信息公开平台(以下简称“研招信息公开平台”)已于2019年7月1日开放-2019年7月30日结束。招生信息怎么看?老师在线教你看懂研究生招生信息!本篇目录:1.全国硕士研究生招生信息公开…

delphi读取xml中的内容property name传递参数_Python 进阶知识全篇-XML 解析

什么是 XML?XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。 你可以通过本站学习 XML 教程XML 被设计用来传输和存储数据。XML 是一套定…

c语言编写网页图形界面代码,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼贴吧内经常有人问C语言是不是只能用于字符终端界面开发,不能用于图形界面。大家也都有回答,需要其他的库。MFC,GTK,QT。本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大…

python 读取word_教你怎么使用 Python 对 word文档 进行操作

使用Python对word文档进行操作一、安装Python-docxPython-docx是专门针对于word文档的一个模块,只能读取docx 不能读取doc文件。说白了,python就相当于windows操作系统,QQ就是跑在windows操作系统上的软件,QQ最大的作用是可以去聊…

stm32cubemx adc_STM32CubeMX__Exp5_ADC1_2CH_DMA_TIM3_Trig__简明指导文件__jyb

用定时器TIM3触发DMA方式的双通道ADC定时采样:拷贝STM32CubeMX工程文件LED_Flash_PC12.ioc,修改为:Exp5_ADC1_2CH_DMA_TIM3_Trig.ioc(1)配置ADC1的通道和参数配置ADC通道参数(2)配置ADC1的DMA①通过点"Add"按钮,添加ADC…

JS 实现 jQuery的$(function(){});

1、浏览器渲染引擎的HTML解析流程 何谓“渲染”,其实就是浏览器把请求到的HTML内容显示出来的过程。渲染引擎首先通过网络获得所请求文档的内容,通常以8K分块的方式完成。下面是渲染引擎在取得内容之后的基本流程: 1,解析html以构…

html 分页_MySQL——优化嵌套查询和分页查询

Java识堂,一个高原创,高收藏,有干货的微信公众号,欢迎关注优化嵌套查询嵌套查询(子查询)可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。嵌套查询写起来简单,也…

从原理上搞定编码-- Base64编码

开发者对Base64编码肯定很熟悉,是否对它有很清晰的认识就不一定了。实际 上Base64已经简单到不能再简单了,如果对它的理解还是模棱两可实在不应该。大概介绍一下Base64的相关内容,花几分钟时间就可以彻底理解它。文 章下边贴了一个Base64的编…

docker mysql总是退出_Docker提升测试效率之路

现如今,Docker已经成为了很多公司部署应用、服务的首选方案。依靠容器技术,我们能在不同的体系结构之上轻松部署几乎任何种类的应用。作为测试一方,我们应与时俱进,将Docker容器技术应用到测试工作中。为了让小伙伴们可以快速上手…

32位mysql安装包_软件测试基础——Linux系统搭建MySQL数据库

一、mysql下载1. 下载:官方网址:https://dev.mysql.com/downloads/mysql/2. 选择相应的版本,由于cenos是基于红帽的,所以Select Operating System选择Red Hat...。我所用的镜像为cenos7所以Red Hat....linux7,一定要选相应的版本&…

python gevent模块 下载_Python中的多任务,并行,并发,多线程,多进程,协程区别...

多任务CPU承担了所有的计算任务。一个CPU在一个时间切片里只能运行一个程序。当我们想同时运行多于一个程序的时候,就是多任务,例如同时运行微信,QQ,浏览器等等。多任务的目的是提升程序的执行效率,更充分利用CPU的资源…

vue-router 路由嵌套显示不出来_网络协议|OSI模型第三层网络层中的路由

的IP协议OSI第二层中用以太网协议定义了信息传输单元,简称为帧,它长这个样子。同样的在OSI第三层中,会用 IP 协议去定义信息传输单元,简称为数据包,它长这个样子。实际上,最终在网络上传输的是第二层的帧&a…

asp.net怎么实现按条件查询_【33期】分别谈谈联合索引生效和失效的条件

点击上方“Java面试题精选”,关注公众号面试刷图,查缺补漏>>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅。这道题考查索引生效条件、失效条件。像这类问题才其实很有意义&…

java 二分搜索获得大于目标数的第一位_程序员数据结构算法编程,二分查找搜索算法的原理与应用介绍!...

本文来讲一种搜索算法,即二分搜索算法,通常在面试时也会被问到。我们先来看一个例子,在图书馆通常是根据查到的编号去找书,可以在书架上按顺序一本本地查找,也可以找到一本书不符合预期时,再跳过一大部分书…

2020idea插件怎么同步_VScode 插件整理

1、auto rename tag :HTML 标签自动闭合;避免了在整个页面中费劲查找。你想将一个H2标签更改为H3标签,或者你想将一个div标签更改为span标签,不管要做什么,你都要浪费时间来查找结束标签,这时候就该用这个插…

python 将两幅图拼接_清华王教授典藏的python电子书,整整10个G拿去不谢

终于拿到!清华王教授典藏的电子书,整整10个G!兄弟,毫无套路!无偿获取方式:1.点赞评论2.关注小编,私信“Python”(点开头像就能看到私信按钮啦).Python指南——五行代码实现批量抠图你是否曾经想将某张照片中…

地磅称重软件源码_【漯河衡器】导致地磅称重不准原因及处理措施

地磅是一种新型的大型电子衡器,能够迅速、直观、高准确度地展现工商业、仓储、货站贸易计量的重要工具。做为贸易结算的工具,地磅的可靠性、准确性、科学性有着极为重要的影响。而在货物来往中,地磅是等价交换的桥梁,一旦地磅显现…

寻宝机器人电路板焊接_专业维修淮安市KUKA库卡KRC2机器人回收{机器人调试}

FANUC机器人伺服-023故障排除:FANUCR-2000六轴焊接机器人点焊进程中,J4机械臂显现自动滑动故障,机器人发出伺服故障报警,报警故障码为伺服-023,依据FANUC机器人维修手册,故障代码解释以下:伺服误…