【发布时间】:2015-02-18 18:10:46
【问题描述】:
我最近一直在学习如何在 libgdx 中实现我自己的着色器。 到目前为止,我使用自定义着色器提供程序完成了这项工作,它根据对象的 userdata 值在几个着色器之间进行选择;
public class MyShaderProvider extends DefaultShaderProvider {
public final DefaultShader.Config config;
final static String logstag = "ME.MyShaderProvider";
//known shaders
static public enum shadertypes {
prettynoise,
invert,
standardlibgdx,
noise,
distancefield,
conceptbeam
}
public MyShaderProvider (final DefaultShader.Config config) {
this.config = (config == null) ? new DefaultShader.Config() : config;
}
public MyShaderProvider (final String vertexShader, final String fragmentShader) {
this(new DefaultShader.Config(vertexShader, fragmentShader));
}
public MyShaderProvider (final FileHandle vertexShader, final FileHandle fragmentShader) {
this(vertexShader.readString(), fragmentShader.readString());
}
public MyShaderProvider () {
this(null);
}
public void testListShader(Renderable instance){
for (Shader shader : shaders) {
Gdx.app.log(logstag, "shader="+shader.getClass().getName());
Gdx.app.log(logstag, "can render="+shader.canRender(instance));
}
}
@Override
protected Shader createShader (final Renderable renderable) {
//pick shader based on renderables userdata?
shadertypes shaderenum = (shadertypes) renderable.userData;
if (shaderenum==null){
return super.createShader(renderable);
}
Gdx.app.log(logstag, "shaderenum="+shaderenum.toString());
switch (shaderenum) {
case prettynoise:
{
return new PrettyNoiseShader();
}
case invert:
{
String vert = Gdx.files.internal("shaders/invert.vertex.glsl").readString();
String frag = Gdx.files.internal("shaders/invert.fragment.glsl").readString();
return new DefaultShader(renderable, new DefaultShader.Config(vert, frag));
}
case noise:
{
return new NoiseShader();
}
case conceptbeam:
{
Gdx.app.log(logstag, "creating concept gun beam ");
return new ConceptBeamShader();
}
case distancefield:
{
return new DistanceFieldShader();
}
default:
return super.createShader(renderable);
}
//return new DefaultShader(renderable, new DefaultShader.Config());
}
}
这似乎奏效了。
我有一个应用了噪声着色器的对象,动画效果很好。
我有一个带有倒置纹理着色器的对象,看起来又很好。
我有一大堆其他对象正在使用正常的默认着色器进行渲染。
似乎我设置的提供程序正在根据 userData 使用不同的着色器正确渲染不同的对象。
但是,我最近发现我使用新着色器类型 (ConceptBeamShader) 创建的新对象仅使用默认着色器进行渲染。
对象用户数据设置与其他对象相同;
newlazer.userData = MyShaderProvider.shadertypes.conceptbeam;
但是,conceptbeamshader 绝不会被创建或使用。
事实上 createShader() 似乎根本没有运行它...暗示着色器数组中的现有着色器已经足够好。
使用上面的 testListShader() 函数,我看到“DefaultShader”在“着色器”列表中,它可以渲染任何东西,因此它永远不会创建我希望该对象使用的新着色器:-/
我假设其他着色器只是在之前被选中,因为这些对象是在将 DefaultShader 添加到该内部着色器列表之前创建的。
当然,一旦使用 DefaultShader,它就会存储在该提供程序列表中,并将“吞噬”任何其他着色器。 MyShaderProvider 扩展类中的 getShader 函数是;
public Shader getShader (Renderable renderable) {
Shader suggestedShader = renderable.shader;
if (suggestedShader != null && suggestedShader.canRender(renderable)) return suggestedShader;
for (Shader shader : shaders) {
if (shader.canRender(renderable)) return shader;
}
final Shader shader = createShader(renderable);
shader.init();
shaders.add(shader);
return shader;
}
正如您所见,着色器被循环播放,并且使用了第一个为“canRender”返回 true 的着色器。
那么...嗯...您应该如何准确地说“使用此着色器渲染此 ModelInstance”?
我在网上阅读的教程似乎都没有涵盖这一点 - 事实上,官方网站上的教程似乎准确地推荐了我正在做的事情,所以很明显我缺少一些东西。
谢谢,
编辑 它被实例化的地方被要求。不知道这有什么帮助,但在这里;
public static MyShaderProvider myshaderprovider = new MyShaderProvider();
然后在游戏设置时将其分配给模型批次
modelBatch = new ModelBatch(myshaderprovider);
如前所述,我的其他着色器正在工作并且在我分配了匹配用户数据的对象上也是可见的,所以我 99.9% 确定正在调用提供程序,并且至少在某些情况下,为正确选择正确的着色器目的。 我的直觉是,一旦“DefaultShader”被添加到内部着色器列表中,它就会出错。
【问题讨论】:
-
好吧,你永远不会实例化你的提供者,检查stackoverflow.com/help/how-to-ask。您可能还想考虑使用材料而不是 userData,请参阅:github.com/libgdx/libgdx/wiki/ModelBatch#shaderprovider
-
也许我应该提到我已经阅读了很多教程,包括官方网站上的教程。我还没有找到任何涵盖这一点的内容。很多根本不涉及 ModelInstances,而是纯粹处理基于 sprite 的使用。如前所述,我的着色器系统设置适用于许多对象。提供者是从主类实例化和分配的。您提供的第二个链接确切地说明了我已经在做什么。我已经设置了一个自定义着色器提供程序,并且正在使用 userData 来选择要使用的着色器。我不明白为什么使用不同的材料场会改变结果。
-
说您已阅读教程无助于澄清问题。就像说的那样,您永远不会实例化提供程序。也许从一个工作示例 (github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/…) 开始,然后对其进行修改以满足您的需求。至少它会帮助您创建一个 mcve (stackoverflow.com/help/mcve) 以包含在您的问题中。
-
我有一个工作示例。我提到的其他着色器工作。我们必须在这里谈论不同的目的:-/我有 1 个提供者。它目前正在分配一组着色器,如上所述。如果它没有设置肯定没有他们会工作?我的动画噪声着色器?我的反转着色器?如果没有工作提供者,其中任何一个将如何工作:?我确实很困惑,但我的问题很简单; 如何将特定着色器分配给特定的 ModelInstance
-
顺便说一句,该工作示例仅使用 BaseShaderProvider,甚至没有显示正在使用的自定义。显示一个默认提供程序和一个着色器的示例并不能回答某人有多个工作着色器但没有选择一个特定着色器的问题。