我正在使用GLSL着色器编写一个小型渲染引擎:
每个网格(井,子网格)都有一些顶点流(例如位置,法线,纹理,切线等)到一个大的VBO和一个MaterialID中.
每个材质都有一组纹理和属性(例如镜面反射颜色,漫反射颜色,颜色纹理,法线贴图等)
然后我有一个GLSL着色器,它的制服和属性.让我们说:
uniform vec3 DiffuseColor;
uniform sampler2D NormalMapTexture;
attribute vec3 Position;
attribute vec2 TexCoord;
Run Code Online (Sandbox Code Playgroud)
我试图为GLSL着色器设计一种方法来定义属性和制服的流映射(语义),然后将顶点流绑定到适当的属性.
对网格说法的内容:"将您的位置流放在属性"位置"中,将您的tex坐标放在"TexCoord"中.还将材质的漫反射颜色放在"DiffuseColor"中,将材质的第二个纹理放在"NormalMapTexture"中
目前我正在使用硬编码的名称作为属性(即顶点pos始终是"位置"等)并检查每个统一和属性名称以了解着色器使用它的内容.
我想我正在寻找一种创建"顶点声明"的方法,但也包括制服和纹理.
所以我只是想知道人们如何在大型渲染引擎中做到这一点.
编辑:
回顾建议的方法:
1.属性/统一语义由变量名称给出 (我现在正在做什么)为每个可能的属性使用预定义的名称.GLSL绑定器将查询每个属性的名称并基于该属性链接顶点数组.变量名称:
//global static variable
semantics (name,normalize,offset) = {"Position",false,0} {"Normal",true,1},{"TextureUV,false,2}
...when linking
for (int index=0;index<allAttribs;index++)
{
glGetActiveAttrib(program,index,bufSize,length,size[index],type[index],name);
semantics[index]= GetSemanticsFromGlobalHardCodedList(name);
}
... when binding vertex arrays for render
for (int index=0;index<allAttribs;index++)
{
glVertexAttribPointer(index,size[index],type[index],semantics[index]->normalized,bufferStride,semantics[index]->offset);
}
Run Code Online (Sandbox Code Playgroud)
2.每个语义的预定义位置
GLSL绑定器将始终将顶点数组绑定到相同的位置.着色器可以使用相应的名称进行匹配.(这看起来非常类似于方法1,但除非我误解,否则这意味着绑定所有可用的顶点数据,即使着色器不使用它)
.. when linking the program...
glBindAttribLocation(prog, 0, "mg_Position");
glBindAttribLocation(prog, 1, "mg_Color");
glBindAttribLocation(prog, 2, "mg_Normal");
Run Code Online (Sandbox Code Playgroud)
3.来自Material,Engine globals,Renderer和Mesh的可用属性的字典
维护活动材质,引擎全局,当前渲染器和当前场景节点发布的可用属性列表.
例如:
Material has (uniformName,value) = …Run Code Online (Sandbox Code Playgroud) 在C中,我可以调试代码:
fprintf(stderr, "blah: %f", some_var);
Run Code Online (Sandbox Code Playgroud)
在GLSL中......无论如何我只是在Vertex或Fragment着色器中转储一个值?我不在乎它是否缓慢; 我只想转出价值.理想情况下,我想要一个如下设置:
这可行吗?(我不关心性能;我只是想为一帧做这个).
谢谢!
哪个更好 ?
到具有一个着色器程序有很多制服指定灯使用,或映射做(例如,我需要一个网格被视差映射,并且映射另一个视差/镜面).我会制作一个缓存转移制服的缓存列表,如果需要的话,只需为每个下一个网格更换一些制服.
要 为每个需要的案例设置很多着色器程序,每个案例都有少量制服,如果需要的话,每个网格都使用glUseProgram进行惰性绑定.在这里,我假设网格已正确批处理,以避免冗余切换.
我正在编写一个iPhone应用程序,它使用GLSL着色器对纹理进行转换,但有一点,我有点困难的是将变量传递给我的GLSL着色器.
我已经读过,可以让着色器读取OpenGL状态的一部分(我只需要对此变量进行只读访问),但我不确定该交换是如何发生的.
简而言之,我试图获得在片段着色器之外创建的浮点值,以便片段着色器可以访问(无论是传入还是从着色器内部读取).
感谢您提供的任何帮助/指示,非常感谢!
在WebGL中使用GLSL着色器的流行方式似乎是将它们嵌入到主html文件中.顶点和片段着色器嵌入在以下标记中:
<script id="shader-fs" type="x-shader/x-fragment">
Run Code Online (Sandbox Code Playgroud)
这与我在Mozilla Developer Network页面中的WebGL示例中看到的相同.
这适用于简单的应用程序,但是当你有一个带有许多着色器的复杂应用程序时,html文件会变得混乱.(我一直在编辑错误的着色器!)另外,如果你想重复使用着色器,这个方案很不方便.
所以我考虑将这些着色器放在一个单独的XML文件中,并使用XMLHttpRequest()加载它们.然后我看到其他人有同样的想法:
http://webreflection.blogspot.com/2010/09/fragment-and-vertex-shaders-my-way-to.html
我喜欢使用.c文件的建议,因为这为GLSL提供了语法高亮和其他编辑器便利.
但是上述方法的问题是(据我所知)XMLHttpRequest()在开发和测试WebGL应用程序时无法加载本地.c文件 - 即在客户端.但是在此过程中继续将其上传到服务器是很麻烦的.
因此,如果我想将着色器保留在html文件之外,那么将它们作为字符串嵌入代码中是唯一的选择吗?但这会使编写和调试变得困难......
我很感激有关在WebGL应用程序中管理多个GLSL着色器的任何建议.
问候
编辑(2011年5月5日)
由于我使用Mac进行开发,我决定启用Apache服务器,并将我的webgl代码放在http:// localhost/~username /下.这避免了在开发期间禁用文件:协议的问题.现在javascript文件加载代码在本地工作,因为使用了http:而不是file:.我以为我会把它放在这里以防万一有人发现它有用.
我试图在GLSL中围绕着色器,我已经找到了一些有用的资源和教程,但是我一直在为一些应该是根本和微不足道的东西碰壁:我的片段着色器如何检索颜色目前的片段?
你可以通过说明来设置最终颜色gl_FragColor = whatever,但显然这是一个仅输出值.如何获得输入的原始颜色,以便对其进行计算?这必须在某个地方变量,但如果有人知道它的名字,他们似乎没有在我到目前为止遇到的任何教程或文档中记录它,它正在推动我的问题.
我有一些参数从CPU传递到GPU,这些参数对于所有片段都是常量但在每一帧都有变化(我使用的是GLSL ES 1.1).我应该为这些价值观使用制服或属性吗?属性可以在顶点到顶点之间变化,因此我的直觉是使用在整个帧中保持不变的值的属性将是低效的.然而,我已经读过,制服是针对"相对不频繁"变化的价值,这表明在每一帧上更换制服可能效率低下.
在硬件方面,我最感兴趣的是优化iPhone 4S.
我有一个理想情况下需要28位尾数的着色器,尽管我可以使用更少并降低性能.如何确定OpenGL ES中'highp'的精度?它可能是一个FP24,有16位尾数,但我无法确定或如何询问OpenGL.有任何想法吗?
两个问题真的......
我正在为针对Windows,Mac和iPad的应用程序编写着色器,我宁愿不必添加每个着色器的更多版本 - 无论如何更简单的着色器.