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 切换可编程管线的更多相关文章

  1. GPU的历史:从固定管线到可编程管线再到通用计算平台

    开始的时候GPU不能编程,也叫固定管线的,就是把数据按照固定的通路走完. 和CPU同样作为计算处理器,顺理成章就出来了可编程的GPU,但是那时候想在GPU上编程可不是容易的事,你只能使用GPU汇编来写 ...

  2. QT_OPENGL-------- 4.可编程管线绘制三角形

    一.环境:qt下qmake编译首先在qt .pro文件中添加glew和glfw的链接 LIBS+= -L/usr/lib64 -lGLEW LIBS +=-L/usr/local/lib -lglfw ...

  3. MFC+OpenGL可编程管线

    [github链接] 网上的代码大都是固定管线渲染的,今天下午整理了下,把setPixelFormat.初始化glew.创建GL 4,2 context等操作封装到一个MFC类OpenGLWidget ...

  4. Android学习指南之三十八:Android手势操作编程[转]

    手势操作在我们使用智能设备的过程中奉献了不一样的体验.Android开发中必然会进行手势操作方面的编程.那么它的原理是怎样的呢?我们如何进行手势操作编程呢? 手势操作原理 首先,在Android系统中 ...

  5. 图解Python 【第八篇】:网络编程-进程、线程和协程

    本节内容一览图: 本章内容: 同步和异步 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 一.同步和异步 你叫我去吃饭 ...

  6. Python开发【第八篇】:网络编程 Socket

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  7. 读书笔记_Effective_C++_条款四十八:了解模板元编程

    作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...

  8. python【第八篇】socket网络编程

    内容大纲 1.socke基础 两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建 立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API ...

  9. JavaScript八张思维导图—编程风格

    JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...

随机推荐

  1. Java之IO流的关闭

    1.在finally中关闭流: OutputStream out = null; try { out = new FileOutputStream(""); // ...操作流代码 ...

  2. TCP连接复用

    转自网络:看到一陌生名词,记录一下 TCP连接复用技术通过将前端多个客户的HTTP请求复用到后端与服务器建立的一个TCP连接上.这种技术能够大大减小服务器的性能负载,减少与服务器之间新建TCP连接所带 ...

  3. linux 下 php 扩展

    首先查看,php 原来安装的配置 /www/server/php/72/bin/php -i | grep configure (php 位置) 加上你的扩展 '--with-mcrypt' make ...

  4. 转:攻击JavaWeb应用[6]-程序架构与代码审计

    转:http://static.hx99.net/static/drops/tips-429.html 攻击JavaWeb应用[6]-程序架构与代码审计 园长 · 2013/08/12 16:53 注 ...

  5. 洛谷P2168 [NOI2015] 荷马史诗 [哈夫曼树]

    题目传送门 荷马史诗 Description 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马 ...

  6. 【linux入门必备】小白需要掌握的基础知识_不定期更新

    因为博主对linux掌握暂时不需要太精通,遇到一个记录一个. 零碎 知识点: 杂类常用命令: 模糊匹配补齐 TAB 系统相关命令: 查阅手册 man 更新软件 sudo apt-get update ...

  7. Linux命令之sort

    sort [选项] [文件] 对文本文件的行进行排序.常见的字符排序空字符串<数字<a<A<b<B...<z<Z (1).常用选项 -b,--ignore-l ...

  8. webpack2 热加载js 文件

    如果只要普通的热加载 只要如下配置就好了 package.json { "devDependencies": { "webpack": "^2.6.1 ...

  9. 【BZOJ 1115】【POI 2009】石子游戏Kam

    http://www.lydsy.com/JudgeOnline/problem.php?id=1115 差分后变成阶梯博弈. #include<cstdio> #include<c ...

  10. Gauss 消元(模板)

    /* title:Gauss消元整数解/小数解整数矩阵模板 author:lhk time: 2016.9.11 没学vim的菜鸡自己手打了 */ #include<cstdio> #in ...