我需要帮助,在我的游戏中组织着色器。HLSL - 组织着色器和技术,不会迷路
游戏使用顶点和像素着色器进行纹理和照明。一些物体纹理,其他只是有色,然后有几个照明算法 - 光照贴图,漫反射和镜面光照,一些只有一些物体得到的影子等。
我的第一个想法是有一个大的,漂亮的着色技术它可以根据参数处理所有事情。这是伟大的,以保持(伪代码给想法):
float4 PixelShaderFunction(input)
{
if (UseTexture)
objectColor = tex2D(...)
else
objectColor = ObjectColor;
if (UseAmbient)
...
if (UseDiffuseLight)
...
// etc...
}
但是表现得很差。
然后我创建了多种技术来避免if
分支,所以每种技术只使用特定对象所需的东西。所以如果对象不接受阴影,那里没有代码。如果它没有使镜面光线,没有代码。另外我将通用功能分组到功能中。像这样(真实代码现在):
float4 Textured_PixelShader(Textured_VsOut input) : COLOR0
{
float4 lightLevel = 0;
float4 objectColor = GetObjColorTex(input.TexUV);
// calculate main table lighting
PsAddTableLight(input.WorldPosition, input.Normal, lightLevel);
// calculate cloth lighting
PsAddClothLight(input.WorldPosition, input.Normal, lightLevel);
// calculate fill light - do we need it?
PsAddFillLight(input.Normal, lightLevel);
// add ambient light
PsAddAmbientLight(lightLevel);
// apply light
PsApplyDiffuseLight(lightLevel, objectColor);
// add speculars
PsAddSpecularBlurred(input.WorldPosition, input.Normal, objectColor);
// final work
return PsFinalize(objectColor);
}
性能的提高是巨大的。
但是我在维护着色器时迷路了。每隔一天我需要添加一项新技术,因为还没有组合texture + lightmap + this_kind_of_shadow + specular
或任何我需要的。他们中的一些人得到这样的名字,另一些人则以他们所使用的对象命名,因为只有一个具有这种组合的对象。它变得一团糟。
我有那么两个问题:
- 为什么我不能有那些
if
报表?我读了很多关于条件执行如何伤害GPU的内容,但是我的ifs只依赖于所有渲染像素(或vert)具有相同值的着色器参数。为什么他们不能很快?我真的很想念他们。 - 将此代码分成不同的着色器/技术/文件的最佳方式是什么?有没有好的标准或规则?
不幸的是,我似乎无法按照自己的方式(动态编译),因为monogame不支持它,即使它只会限于某些平台。但这是我认可的伟大而有价值的答案 - 谢谢。 – Arek
至于为什么'如果'很慢 - 我仍然不确定,但很快就会做一些复验来验证性能放缓。根据所有来源,它应该是快速的,因为对于所有呈现的东西,“if”条件是相同的。 – Arek