zoukankan      html  css  js  c++  java
  • 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技术能够达到相似的效果,相关内容能够參考官方文档


    松阳论道

    关注我的微信公众号,获取很多其它优质内容

  • 相关阅读:
    VS Code 编译运行C/C++
    滴水逆向-文件读写&内存分配-PE准备阶段
    技术从业者的未来(三)
    房价预测-California House Prices
    记录一下Linux的文件夹的rwx权限使用。
    对微任务和宏任务的执行顺序的个人理解
    算法1.4 节 ----- 算法分析
    .NetCore中间件实现原理
    谷歌浏览器禁用JS步骤
    管理经验分享
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7286987.html
Copyright © 2011-2022 走看看