如何允许用户为 openGL 软件自定义着色器
How to allow user's custom shader for an openGL software
例如,在 Unity 或 Unreal 等软件中,它们如何允许用户将自己的自定义着色器添加到对象?
这个自定义着色器只是一个普通的片段着色器还是另一种着色器?如果它只是一个片段着色器,它们如何处理灯光?
我不会post这里的代码,因为它很大并且会污染页面,但我从这里开始学习: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 的着色器中添加灯光,例如,人们只是添加纹理并弄乱颜色,除非他们真的想专门弄乱灯光。
有没有办法只制作一个片段着色器来计算所有类型的光,然后用户可以在其上应用另一个着色器,仅用于对象 material?
如果你不知道如何回答但有一些好的阅读material,或者我可以了解更多关于 openGL 和 GLSL 的地方,那也会很有价值。
有几种不同的方式来构造着色器文件,每种方式各有优缺点。
作为单独的程序。你让每个文件都有自己的着色器程序。添加新程序很简单,并且允许您的用户只用 GLSL、HLSL 或引擎自定义着色器语言编写程序。您将必须为用户提供某种方式来表达程序期望的数据类型,除非您从引擎中查询它,但制作足够通用的东西可能会变得复杂。
Über Shader! 将所有需要的功能放在一个着色器中,让行为由控制流或预处理器宏,例如 #ifdef
。因此,用户只需编写主要功能(应用程序将其添加到着色器的其余部分)。这允许您让用户使用所有预定义的变量和函数。明显的缺点是它可能很大且难以处理,小的变化可能会破坏许多着色器。
微着色器。每个程序都包含一个小的通用功能,应用程序将它们全部连接到一个功能着色器。用户只需编写主要功能并告诉程序要添加哪些功能。问题是除非你小心并且比 über shader.
更难实现名称冲突
效果文件。 由 Microsoft’s effect framework or NVIDIA’s CgFX framework 提供(已弃用)。
抽象遮荫树。实际上不知道这是什么,但它是suppose to be a solution。
您也可以结合其中的一些技术,或尝试根据您的需要发明您自己的解决方案。 Here's 讨论的解决方案(在部门 2.3.3 现有解决方案)。
例如,在 Unity 或 Unreal 等软件中,它们如何允许用户将自己的自定义着色器添加到对象? 这个自定义着色器只是一个普通的片段着色器还是另一种着色器?如果它只是一个片段着色器,它们如何处理灯光?
我不会post这里的代码,因为它很大并且会污染页面,但我从这里开始学习: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 的着色器中添加灯光,例如,人们只是添加纹理并弄乱颜色,除非他们真的想专门弄乱灯光。
有没有办法只制作一个片段着色器来计算所有类型的光,然后用户可以在其上应用另一个着色器,仅用于对象 material?
如果你不知道如何回答但有一些好的阅读material,或者我可以了解更多关于 openGL 和 GLSL 的地方,那也会很有价值。
有几种不同的方式来构造着色器文件,每种方式各有优缺点。
作为单独的程序。你让每个文件都有自己的着色器程序。添加新程序很简单,并且允许您的用户只用 GLSL、HLSL 或引擎自定义着色器语言编写程序。您将必须为用户提供某种方式来表达程序期望的数据类型,除非您从引擎中查询它,但制作足够通用的东西可能会变得复杂。
Über Shader! 将所有需要的功能放在一个着色器中,让行为由控制流或预处理器宏,例如
#ifdef
。因此,用户只需编写主要功能(应用程序将其添加到着色器的其余部分)。这允许您让用户使用所有预定义的变量和函数。明显的缺点是它可能很大且难以处理,小的变化可能会破坏许多着色器。微着色器。每个程序都包含一个小的通用功能,应用程序将它们全部连接到一个功能着色器。用户只需编写主要功能并告诉程序要添加哪些功能。问题是除非你小心并且比 über shader.
更难实现名称冲突效果文件。 由 Microsoft’s effect framework or NVIDIA’s CgFX framework 提供(已弃用)。
抽象遮荫树。实际上不知道这是什么,但它是suppose to be a solution。
您也可以结合其中的一些技术,或尝试根据您的需要发明您自己的解决方案。 Here's 讨论的解决方案(在部门 2.3.3 现有解决方案)。