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 ...
随机推荐
- nodejs调试基础【转载】
nodejs调试基础[转载] 看到了一片不错的文章: 作者:前端求生之路 链接:nodejs调试基础[转载]
- echarts官网上的动态加载数据bug被我解决。咳咳/。
又是昨天,为什么昨天发生了这么多事.没办法,谁让我今天没事可做呢. 昨天需求是动态加载数据,画一个实时监控的折线图.大概长这样. 我屁颠屁颠的把代码copy过来,一运行,caocaocao~bug出现 ...
- vue-music 关于Player (播放器组件)--播放和进度条
迷你播放器 1.播放器组件会在各个页面的情况下会打开. 首先在vuex state.js 中定义全局的播放器状态 import {playMode} from 'common/js/config.js ...
- SSM整合所需jar包
MySql驱动包 mysql-connector-java-5.1.7-bin.jar MyBatis的核心包和依赖包 mybatis-3.2.7.jar(核心包)asm-3.3.1.jar(依赖包) ...
- 批量更新带有命名空间的XML文件的多个节点值
/// <summary> /// 批量修改节点值 /// </summary> /// <param name="filePath">路径&l ...
- eclipse汉化 adt汉化
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha
- BZOJ 2818 Gcd(莫比乌斯反演)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2818 [题目大意] 给定整数N,求1<=x,y<=N且Gcd(x,y)为素 ...
- 【模拟】 Codeforces Round #434 (Div. 1, based on Technocup 2018 Elimination Round 1) C. Tests Renumeration
题意:有一堆数据,某些是样例数据(假设X个),某些是大数据(假设Y个),但这些数据文件的命名非常混乱.要你给它们一个一个地重命名,保证任意时刻没有重名文件的前提之下,使得样例数据命名为1~X,大数据命 ...
- 【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
我们要统计的答案是sigma([L/K]),L为路径的长度,中括号表示上取整. [L/K]化简一下就是(L+f(L,K))/K,f(L,K)表示长度为L的路径要想达到K的整数倍,还要加上多少. 于是, ...
- 在Linux系统环境下修改MySQL的root密码
root用户登录系统 /usr/local/mysql/bin/mysqladmin -u root -p password 新密码 enter password 旧密码 第二种方法: root用户登 ...