首页 > 解决方案 > 如何允许用户为 openGL 软件自定义着色器

问题描述

例如,在 Unity 或 Unreal 等软件中,它们如何允许用户将自己的自定义着色器添加到对象中?这个自定义着色器只是普通的片段着色器还是另一种着色器?如果它只是一个片段着色器,它们如何处理灯光?

我不会在这里发布代码,因为它很大并且会污染页面,但我开始在这里学习:https ://github.com/opentk/LearnOpenTK/blob/master/Chapter2/6-MultipleLights/ Shaders/lighting.frag(这是一系列教程,这是上一篇的着色器),他们说我们应该将光照类型放在片段着色器内部的函数中,以计算每个片段的颜色。

例如,这个计算定向光的函数,从我上面发送的代码中提取:

vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
    vec3 lightDir = normalize(-light.direction);
    //diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    //specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    //combine results
    vec3 ambient  = light.ambient  * vec3(texture(material.diffuse, TexCoords));
    vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, TexCoords));
    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    return (ambient + diffuse + specular);
}

但是我从未见过有人在 Unity 的着色器中添加灯光,例如,人们只是添加纹理并弄乱颜色,除非他们真的想专门弄乱灯光。

有没有办法只制作一个片段着色器来计算所有类型的光,然后用户可以在此之上应用另一个着色器,仅用于对象材质?

如果您不知道如何回答但有一些很好的阅读材料,或者我可以了解更多关于 openGL 和 GLSL 的地方,那么它也将非常有价值。

标签: openglglslshaderfragment-shaderopentk

解决方案


有几种不同的方式来构建着色器文件,每种方式都有不同的优缺点。

  • 作为个人节目。您将每个文件都设为自己的着色器程序。添加新程序很简单,并且允许您的用户只用 GLSL、HLSL 或引擎自定义着色器语言编写程序。您必须为用户提供某种方式来表达程序期望的数据类型,除非您从引擎中查询它,但是制作足够通用的东西可能会变得复杂。

  • 超级着色器!将所有需要的功能放在一个着色器中,并让行为由控制流或预处理器宏控制,例如#ifdef. 所以用户只需要编写 main 函数(应用程序将其添加到着色器的其余部分)。这允许您让用户使用所有预定义的变量和函数。明显的缺点是它可能很大且难以处理,并且小的更改可能会破坏许多着色器。

  • 微着色器。每个程序都包含一个小而通用的功能,应用程序将它们全部连接到一个正常工作的着色器。用户只需编写主函数并告诉程序要添加哪些功能。问题是名称很容易发生冲突,除非你很小心,而且比über shader更难实现。

  • 效果文件。Microsoft 的效果框架NVIDIA 的 CgFX 框架提供(已弃用)。

  • 抽象树荫。实际上不知道这是什么,但它应该是一个解决方案

您还可以结合其中一些技术或尝试根据您的需要发明自己的解决方案。以下是讨论的解决方案(在2.3.3 现有解决方案部分)。


推荐阅读