OpenGL(八)使用 subroutine 切换可编程管线
Subroutine 功能是在OpenGL 4.0 版本号里才添加的。因此对于各种Android手机。这个功能基本跪了。假设你发现你的程序报错:ARB_shader_subroutine。那就说明当前显卡不支持。只是大体思路能够了解一下。由于思路相似的功能有其它的实现方式。
原理
在shader中声明一个函数变量,然后定义它的指针,并将其作为一个uniform变量公开出去。最后定义非常多复写函数就可以。
实现
由于版本号限制。使用 subroutine 要注意在shader中添加版本号的编译宏:
#version 400 core
在shader中编写:
subroutine vec4 SurfaceColor();
subroutine uniform SurfaceColor U_SurfaceColor; subroutine (SurfaceColor) vec4 Ambient()
{
//...
} subroutine (SurfaceColor) vec4 Diffuse()
{
//...
} subroutine (SurfaceColor) vec4 Specular()
{
//...
} void main()
{
gl_FragColor = U_SurfaceColor();
}
在shader中,每个函数中的代码段代表一种处理函数。
还有一方面在GL指令中,绑定这个函数指针,并为其指定实现函数的索引值,就可以实现效果的控制。
surfaceColorLocation = glGetSubroutineUniformLocation(program,GL_FRAGMENT_SHADER,"U_SurfaceColor"); GLuint ambientLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Ambient");
GLuint diffuseLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Diffuse");
GLuint specularLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Specular"); //draw
glUniformMatrix4fv(MLocation, 1, GL_FALSE, glm::value_ptr(model));
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&ambientLightIndex);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
glDrawElements(GL_TRIANGLES,indexCount,GL_UNSIGNED_INT,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
总结
本文介绍了OpenGL中的 subroutine 机制,通过它能够切换shader的内容。在Unity3d中使用Shader.maximumLOD
技术能够达到相似的效果,相关内容能够參考官方文档
关注我的微信公众号,获取很多其它优质内容
OpenGL(八)使用 subroutine 切换可编程管线的更多相关文章
- GPU的历史:从固定管线到可编程管线再到通用计算平台
开始的时候GPU不能编程,也叫固定管线的,就是把数据按照固定的通路走完. 和CPU同样作为计算处理器,顺理成章就出来了可编程的GPU,但是那时候想在GPU上编程可不是容易的事,你只能使用GPU汇编来写 ...
- QT_OPENGL-------- 4.可编程管线绘制三角形
一.环境:qt下qmake编译首先在qt .pro文件中添加glew和glfw的链接 LIBS+= -L/usr/lib64 -lGLEW LIBS +=-L/usr/local/lib -lglfw ...
- MFC+OpenGL可编程管线
[github链接] 网上的代码大都是固定管线渲染的,今天下午整理了下,把setPixelFormat.初始化glew.创建GL 4,2 context等操作封装到一个MFC类OpenGLWidget ...
- Android学习指南之三十八:Android手势操作编程[转]
手势操作在我们使用智能设备的过程中奉献了不一样的体验.Android开发中必然会进行手势操作方面的编程.那么它的原理是怎样的呢?我们如何进行手势操作编程呢? 手势操作原理 首先,在Android系统中 ...
- 图解Python 【第八篇】:网络编程-进程、线程和协程
本节内容一览图: 本章内容: 同步和异步 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 一.同步和异步 你叫我去吃饭 ...
- Python开发【第八篇】:网络编程 Socket
Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- python【第八篇】socket网络编程
内容大纲 1.socke基础 两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建 立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API ...
- JavaScript八张思维导图—编程风格
JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...
随机推荐
- socket编程的网络协议
"我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容" TCP/IP只是一个协议栈,就像程序运行一样,必须要实现运行,同时还要 ...
- 将对象转换为JSON字符串
将对象转换为JSON串: 方案一: 可以通过json-lib工具jar包进行转化:在www.json.org官网下载jar包. 方案二: 通过ObjectMapper对象进行转换 需要引入相应的jar ...
- div的border & width
长时间不用css,发现有些基础知识竟有些遗忘,由于项目中的一些css样式,进行了以下相关测试. div的width及height均设置为0后,div的border会怎样显示.经过测试后,发现borde ...
- js for循环的陷阱
☞问题概述 一页面有三个按钮,点击提示相应内容.相应内容已从后台获取,并转化成json数组. var content = ["提示1", "提示2", &quo ...
- SCU - 4441 Necklace(树状数组求最长上升子数列)
Necklace frog has \(n\) gems arranged in a cycle, whose beautifulness are \(a_1, a_2, \dots, a_n\). ...
- linux的bash和shell关系
shell通俗理解:把用户输入的命令翻译给操作系统. shell 是一个交互性命令解释器.shell独立于操作系统,这种设计让用户可以灵活选择适合自己的shell.shell让你在命令行键入命令,经过 ...
- BZOJ 2212 [Poi2011]Tree Rotations(线段树合并)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2212 [题目大意] 给出一棵二叉树,每个叶节点上有一个权值,现在可以任意交换左右儿子, ...
- 【动态规划】POJ3616-Milking Time
[题目大意] 奶牛Bessie在0~N时间段产奶.农夫约翰有M个时间段可以挤奶,时间段[a,b]Bessie能挤到的牛奶量v.奶牛产奶后需要休息R小时才能继续下一次产奶,求Bessie最大的挤奶量. ...
- JDK源码学习笔记——Object
一.源码解析 public class Object { /** * 一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用 */ private static native void ...
- mybatis批量插入oracle时报错:unique constraint (table name) violated
mybatis批量插入oracle时报错:unique constraint (table name) violated,是因为插入的集合中有两条相同唯一约束的数据.