gpt4 book ai didi

ios - 如何为着色器设计一个简单的 GLSL 包装器

转载 作者:技术小花猫 更新时间:2023-10-29 11:02:28 24 4
gpt4 key购买 nike

更新:因为我马上需要一些东西,所以我创建了一个简单的着色器包装器来完成我需要的事情。您可以在这里找到它:ShaderManager on GitHub .请注意,它是为 Objective-C/iOS 设计的,因此可能并非对所有人都有用。如果您对设计改进有任何建议,请告诉我!

原始问题:

我刚开始使用 GLSL 着色器。我对 GLSL 语言和 OpenGL 接口(interface)非常熟悉,但是我在设计一个简单的 API 来使用着色器时遇到了问题。

OpenGL 与着色器交互的 C 接口(interface)看起来很麻烦。我似乎无法在网上找到任何涵盖此类 API 设计的教程。

我的问题是:是否有人有好的、简单的 API 设计或模式来包装 OpenGL 着色器程序 API?

举个简单的例子。假设我有一个仅模拟固定功能的顶点着色器和两个片段着色器 - 一个用于绘制平滑的矩形,一个用于绘制平滑的圆。我有以下文件:

Shader.vsh : Simple vertex shader, with the following inputs/outputs:
-- Uniforms: mat4 Model, mat4 View, mat4 Projection
-- Attributes: vec4 Vertex, vec2 TexCoord, vec4 Color
-- Varying: vec4 vColor, vec2 vTexCoord

Square.fsh : Fragment shader for drawing squares based on tex coord / color
Circle.fsh : Fragment shader for drawing circles based on tex coord / color

基本链接

现在使用这些的标准方法是什么?我是否将上述着色器链接到两个 OpenGL 着色器程序中?即:

Shader.vsh + Square.fsh = SquareProgram
Shader.vsh + Circle.fsh = CircleProgram

或者我是否改为创建一个大程序,在其中片段着色器检查一些条件统一变量并调用着色器函数来生成它们的结果。例如:

Shader.vsh + Square.fsh + Circle.fsh + Main.fsh = ShaderProgram
//Main.fsh here would simply check whether to call out to square or circle

对于两个单独的程序,我大概需要调用

glUseProgram(CircleProgram); or glUseProgram(SquareProgram);

在我要绘制的每种元素之前。然后我需要在使用之前设置每个程序的制服(模型/ View /投影)和属性。这看起来很笨拙。

使用单个 ShaderProgram 选项时,我仍然需要在片段着色器中设置某种 bool 开关(圆形或方形),以便在绘制每个像素之前进行检查。这看起来也很复杂。

附带说明一下,我是否可以将两个片段着色器(每个都有一个 main() 函数)链接到一个着色器程序中? OpenGL 如何知道调用哪一个?

设置变量

电话:

glUniform*
glVertexAttribPointer

用于在当前程序上设置制服和属性指针位置。

不同的类和结构可能需要从代码中的不同位置访问和设置当前着色器上的变量(或更改当前着色器)。我想不出一个很好的方法来将着色器代码与想要使用它的代码分离。

也就是说,我要绘制的每个形状都需要设置顶点和纹理坐标属性 - 需要 OpenGL 生成的这些属性的句柄。

相机需要在顶点着色器中将其投影矩阵设置为统一,而管理模型矩阵堆栈的类需要在顶点着色器中设置自己的统一。

在绘制场景的过程中更改着色器意味着所有这些类都需要重新设置它们的制服和属性。

大多数人如何围绕这个进行设计?

通过句柄或名称访问的全局着色器字典,以及用于参数的 getter 和 setter?

一个 OO 设计,每个着色器对象都有参数?

我查看了以下包装器:

Jon's Teapot: GLSL Shader Manager - 这将着色器包装在 C++ 类中。它看起来只不过是一个在 C API 上强制执行 OO 原则的包装器,导致 C++ API 非常相似。

我追求任何一种简化着色器程序使用的设计,而不关心所使用的特定范例(面向对象、过程等)

最佳答案

我看到这是用 iOS 标记的,所以如果你偏爱 Objective-C,我会好好看看 Jeff LaMarche 的 GLProgram 包装类,他描述了 here并且有可用的源here .我在自己的应用程序中使用它来简化一些着色器程序设置,并使代码更简洁。

例如,您可以使用如下代码设置着色器及其属性和制服:

sphereDepthProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"SphereDepth" fragmentShaderFilename:@"SphereDepth"];
[sphereDepthProgram addAttribute:@"position"];
[sphereDepthProgram addAttribute:@"inputImpostorSpaceCoordinate"];
if (![sphereDepthProgram link])
{
NSLog(@"Depth shader link failed");
NSString *progLog = [sphereDepthProgram programLog];
NSLog(@"Program Log: %@", progLog);
NSString *fragLog = [sphereDepthProgram fragmentShaderLog];
NSLog(@"Frag Log: %@", fragLog);
NSString *vertLog = [sphereDepthProgram vertexShaderLog];
NSLog(@"Vert Log: %@", vertLog);
[sphereDepthProgram release];
sphereDepthProgram = nil;
}

sphereDepthPositionAttribute = [sphereDepthProgram attributeIndex:@"position"];
sphereDepthImpostorSpaceAttribute = [sphereDepthProgram attributeIndex:@"inputImpostorSpaceCoordinate"];
sphereDepthModelViewMatrix = [sphereDepthProgram uniformIndex:@"modelViewProjMatrix"];
sphereDepthRadius = [sphereDepthProgram uniformIndex:@"sphereRadius"];

当您需要使用着色器程序时,您可以执行如下操作:

[sphereDepthProgram use];

这没有解决您在上面提出的分支与独立着色器的问题,但 Jeff 的实现确实提供了一些 OpenGL ES 样板着色器设置代码的良好封装。

关于ios - 如何为着色器设计一个简单的 GLSL 包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6166202/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com