- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
更新:因为我马上需要一些东西,所以我创建了一个简单的着色器包装器来完成我需要的事情。您可以在这里找到它: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/
我试图理解这两个概念。我正在阅读的手册对它们非常简短,像多 channel 算法这样的东西对我来说是新的。我想要一些示例(不是代码),说明我需要在哪里使用不变变量或精确变量,只是为了获得一个大致的想法
您好,我正在尝试获得一个快速的圆角矩形 glsl 着色器,但我只设法使用此函数( https://github.com/marklundin/glsl-sdf-primitives/blob/mast
这可能是一个简单的问题。作为 GLSL 的新手,我宁愿在这里问。 现在,在顶点着色器中,我可以通过以下方式获取世界坐标系中的位置: gl_Position = ftransform();
我想知道是否有人拥有完整、有效且高效的代码来在 glsl 中进行双三次纹理过滤。有这个: http://www.codeproject.com/Articles/236394/Bi-Cubic-and
真的有两个问题... GLSL ES 2 是完全独立的语言,还是 GLSL 的特殊版本? 在“标准库”函数、语法和功能方面,它们之间有什么区别? 我正在为一个针对 Windows、Mac 和 iPad
从GLSL文档(https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/length.xhtml)中,长度函数“计算 vector 的长度”
我想在 GLSL 着色器中实现颜色矩阵滤镜,但找不到与此相关的任何文档。我是着色器世界的新手(我自己从未编写过代码)所以如果我的解释/词汇没有意义,请原谅我。 到目前为止我可以收集到的信息: 一个颜色
我刚刚开始使用 openframeworks 中的着色器,并且正在尝试编写一个片段着色器,它根据片段的观看角度来更改片段的颜色。例如,给定一个矩形,如果从正面看(相机与法线平行)它会是红色,但如果从侧
似乎某些在 case 中具有输出的函数可能使用 if 语句作为底层实现,从而导致分支。我不认为它,但我想知道。 对于 sign(x),如果数字是正数、负数或零,则分别重新运行 1、-1 和 0。 那么
如何在 glsl 中执行位操作? 使用常规 C 风格的按位运算符 | , & , ^ , 或 !不起作用。 最佳答案 它们是在 GLSL 1.30 (OGL 3.0) 中引入的。 根据您想要做什么,您
最近我一直在玩 webGl,我偶然发现了一个很酷的小演示 here (来源 here )我想稍微改变一下以获得一些很酷的结果。 我对改变地形的生成方式很感兴趣。而不是分层 10 个 Octave
这是每个设备的事情吗?还是基于浏览器?抱歉问了这样一个基本问题,但我似乎找不到直接的答案。 最佳答案 它基于 OpenGL ES 2.0,并根据 the spec , 它必须支持 GLSL ES 版本
你如何在 GLSL 着色器中通过引用传递? 最佳答案 您可以将属性标记为 inout在函数签名中,这将使属性有效地“通过引用传递” 例如, void doSomething( vec3 trans,
我有一个浮点 RGBA 缓冲区,我想将其作为统一 Texel 缓冲区传递到我的计算着色器(用于只读访问,没有采样)。谁能告诉我如何在 GLSL 中执行此操作? 我能找到的所有示例似乎都在跳过该主题,或
我有一些参数从 CPU 传递到 GPU,这些参数对于所有片段都是恒定的,但在每一帧上都会发生变化(我使用的是 GLSL ES 1.1)。对于这些值,我应该使用制服还是属性?属性可能因顶点而异,所以我的
我已经看到这个伪随机数生成器在着色器中使用,引用here and there around the web : float rand(vec2 co){ return fract(sin(dot(
我尝试在结构内初始化数组,如下所示: struct myStruct { vec3 data[20] = vec3[20] (vec3(1, 1, 1), vec3( 1, -1, 1), v
我尝试在结构内初始化数组,如下所示: struct myStruct { vec3 data[20] = vec3[20] (vec3(1, 1, 1), vec3( 1, -1, 1), v
在 GLSL 着色器中,出于各种原因,我经常需要几个函数来修改单个值(例如,片段着色器使用四个函数来应用照明、纹理、镜面反射和雾化)。我可以想到至少三种方法来传递这些值进行修改: 使用 inout每个
我在 SL 引用中搜索了“copy”,但找不到任何相关内容。 如果我有: float a[3] = float[3] (1.0,2.0,3.0); float b[3] = a; 是 b现在指向 a
我是一名优秀的程序员,十分优秀!