如何在3d模型中制作纹理?

时间:2014-10-22 22:59:20

标签: libgdx textures bytebuffer

我希望在我的LibGDX代码中有一个动画3D纹理,但我很难找到如何做到这一点。

我假设这"应该"要做的是;

a)直接访问和修改模型上的纹理。 (通过pixmap?ByteBuffer?)

b)预渲染包含所有帧(例如20)的大图像,然后移动UV坐标以创建动画的幻觉。 (类似于2d / webdesign中的ImageStrips)。

我确实研究了每次如何完全替换材料,但这似乎是一种更糟糕的方式。因此,如果有人能够显示我需要做的命令a)或b)(或类似的最佳方法),我会很棒。 数学我很好。 OpenGLES或GDX的复杂性我不是:)

(解决方案至少应该使用HTML / Android编译,最好是一切)

2 个答案:

答案 0 :(得分:0)

如果你有内存,我肯定会选择b),它在处理器上更容易。此外,您只会更改统一的值。但是,由于预处理,打开应用程序可能需要一些时间。

获取统一变量,在编译着色器的地方,animationPos应该是全局的。

Gluint animationPos = glGetUniformLocation(shaderProgram, "nameoftheuniform");

您的主循环应将animationPos值传递给着色器:

Gluniform1i ( animationPos, curentAnimationIndex);

添加片段着色器变量:

uniform int animationPos;

Fragment shader main:

float texCoordY = texCoord.y; //texture coordinates should be passed from vertex shader
float texCoordX = texCoord.x/20.0f; //we are dividing it with 20 since it is the amount of textures that we have and if we use it directly it would try to use all the texture. Whereas the texture stores at 20 different textures.

float textureIndex = 1.0f*animationPos/20.0f; //Pointer to the start of the animation texture.
gl_fragColor = texture2D ( yourTexture, vec2( textureIndex + texCoordX, texCoordY));

上面的代码假设您在x方向上扩展了纹理,您也可以尝试像矩阵一样展开它,然后您需要更改texCoord计算部分。此外,我们使用20个纹理。

选项a)在处理器上更加沉重,每次都会改变纹理,因此它会更多地使用pci,但内存更容易。问题更像是一个设计决定,但我想可以处理20个图像,所以选择b)。

编辑:添加了代码。

答案 1 :(得分:0)

从最新版本开始,在3D表面上播放2D动画非常容易。首先要确保熟悉2D动画概念,如下所述:https://github.com/libgdx/libgdx/wiki/2D-Animation。然后,您可以使用TextureRegionAnimation#getKeyFrame返回)来设置曲面的材质,而不是使用spritebatch,如下所示:https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/TextureRegion3DTest.java。所以基本上你会得到你的渲染方法:

attribute.set(animation.getKeyFrame(stateTime, true));

或者,如果您想要更通用的方法:

instance.getMaterial("<name of material>").get(TextureAttribute.class, TextureAttribute.Diffuse).set(animation.getKeyFrame(stateTime, true));

或者,如果ModelInstance中只有一个材料:

instance.materials.get(0).get(TextureAttribute.class, TextureAttribute.Diffuse).set(animation.getKeyFrame(stateTime, true));