c++ - 对于 OpenGL 着色器,您将如何在 C++ 中编写接受所有类型的统一函数?

标签 c++ templates opengl glsl shader

假设我有一个 Shader 类,我想要一个 Uniform 函数将我传递的数据发送到加载的 Shader 程序

class Shader{
   unsigned int programid;
   template<typename Type>
   void Uniform(unsigned int location, Type object){
       //Some logic that passes the type data to the uniform using glUniform[?]()
   }
}

我将如何编写 Uniform 函数(使用 C++ 中的模板)来接受任何类型(原始或对象)并将其传递给着色器?

例子:

GLSL:统一 float ; C++:shader.Uniform(somefloat);

GLSL:uniform vec3 Position;

C++:

template<typename Type, size_t Size>
Vector{ Type data[Size]; }

Vector<float, 3> position = {0.0f, 1.0f, 1.0f}
shader.Uniform(position);

GLSL:

struct Light
{
  vec3 position;
  vec4 rotation;
  float luminosity;
  bool status;
};

uniform Light object;

C++:

struct Light {
  Vector<float, 3> position;
  Vector<float, 4> rotation;
  float luminosity;
  bool status;
}
Light object = {{1.0f,0.0f,0.0f},{0.0f,0.0f,0.0f},0.75f,true};
shader.Uniform(object);

最佳答案

首先,C++ 和 GLSL 是静态类型的语言,而不是像 JavaScript 或 Python 那样的动态类型。所以没有实际的方法来编写接受任何类型的 C++ 函数。您的 C++ 模板函数的作用实质上是文本替换。每次 C++ 编译器看到使用的模板(例如“Vector”)时,它都会采用原始​​模板声明并制作一个新拷贝,其中“Type”和“Size”分别替换为“float”和“3”。并且编译器生成一个唯一的错位名称以防止链接器错误,例如 __Vector_TypeFOO_SizeBAR...

(为了完整起见,是的,可以使用 union 和/或指针转换在 C/C++ 中实现您自己的动态类型化。但是由于您不能在 GLSL 中执行其中任何一项,因此它无助于回答问题。)

因此,由于 GLSL 没有模板来进行文本替换,您必须自己实现它。从文件或其他任何地方加载着色器的源代码。在将其传递给 glCompileShader 之前,使用您最喜欢的字符串处理库将实际字符串插入到占位符文本中。

例如,在你的着色器中你可以这样写:

<TYPE><SIZE> position;

你的主程序会做类似的事情

src = loadShaderCode("example.template");
src.replace("<TYPE>", "vec");
src.replace("<SIZE>", "3");
shader = compileShader(src, ...);

希望这对您有所帮助。

关于c++ - 对于 OpenGL 着色器,您将如何在 C++ 中编写接受所有类型的统一函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58864129/

相关文章:

c++ - 使用 bool 变量和值启用功能

c++ - 在 OnOK 中保存对话框数据时出现问题

opengl - OpenGL displayList 大小的限制

OpenGL glColorPointer 重复颜色?

c++ - 日志记录性能和运算符<<

c++ - 创建无重复的随机数序列

c++ - 对带有可变参数模板的 std::ref() 和 std::bind() 有点模糊

c++ - 为什么这段代码可以在 Coliru 上编译,但不能在 Xcode 上编译?

c++ - 迭代模板 int

opengl - 如何使用stencil buffer实现分层裁剪