How to animate textures in JME3

I just started using JME3 and I have not come very far yet. Yes, I am a noob.



You would think that something as simple as rolling a texture across a surface periodically in JME3 would be readily provided by intuitively named functions in the API. I have search the forum, I have searched google, I have looked through the tutorials on the site, I have looked through the and… NOTHING!



The closest I have come is this tutorial for JME2: https://wiki.jmonkeyengine.org/legacy/doku.php/starter:hello_keyinput?



Trying this in JME3 opens a lot of questions?

Where is the display variable?

Where is the setTextureCoordinates() function?

How am I supposed to create a TextureState in JME3?

Where did the TriMesh class go? Should I use Quad instead?



I want to do everything shown in the “hello keyinput”, but using JME3? How do I do it?

You’ll need shaders to do that.

JME3 is based on shaders, i don’t recommend using the fixed pipeline like in the JME2 example.



Read this

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:materials_overview

and this

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:jme3_shaders



Create your own material based on the simple textured material.

In the frag shader, you just have to offset the texCoord based on the g_Tpf variable, which is the time spent on the last frame.

for example :



texCoord.x=texCoord.x+g_Tpf;



will give you an horizontal scrolling texture. (you’ll need to adjust the g_tpf for tweaking the speed)

And…hardware accelerated.

How about a generic animated texture shader for the engine btw?



Aka

uniform texture

uniform int xsplits

unifrom int ysplits

uniform float showsplit



so for example I could:

xsplits = 3

ysplits = 2

→ 0-5 textures



Combined with a controller that can be given a fixed rate this would be perfect for sprites and simple animated textures.



I would like to write that controller, however with shaders I could at max write one without lightening :confused:

heh it’s tricky though EmpirePhoenix. I’ve been working on getting a simple sprite sheet handler working for sprite animations for maybe a month now and there’s sooooo many ways to do it and soooo many pitfalls you gotta watch out for. I’m not sure if you could make a combination of shaders and controllers that would be suitable/generic enough for anyone’s application.



I actually had a shader at one point that did what you’re saying though, I haven’t decided if it’s the best way to go though… *digs around in code for a second… * Yeah, it does something like that but it’s cludgy as all hell. I’m playing around with a method right now that just keeps track of animation frames with durations and x,y coords stored. This way the animations don’t necessarily have to be in any order on the texture/sprite sheet. But again, it’s still in a cludgy phase. I might go back to handling it with rows and columns of animations, but we’ll see. I’m tied up in the controllers that actually control the animations at the moment. Changes to the shader are actually the least of my concerns.



I don’t actually have the shader handling the animation transitions either because I figured that would really turn into a pain in the butt if I needed finer control over the frame switches. Besides, it’s super easy to handle that in a controller.



[Edit: Bad example code removed. Refer to Particle effects]

Guys, the particle system does this already… Its a quad with an animated texture…

If all you need is one quad with one animation, yeah, this is overkill. Though, this was only meant as a stepping stone, not a final product. I knew posting old unfinished code was probably a bad idea. I’ll clean it out until I come up with something that’s actually new.

Thanks guys, but I’m afraid I still do not get it.



Nehon, I read the information in the links but I cannot say that it is obvious how I can use it to have a texture scroll across a surface.



Does anyone have a short code sample, something like this:



public MyGame extends SimpleApplication{



Quad quad = null;

Geometry surface = null;

Material mat = null;

Texture tex = null;



public simpleInitApp(){

quad = new Quad(100f * screenratio, 100f);

surface = new Geometry(“Quad”, quad);

surface.setLocalTranslation(-200, -50, -150);

mat = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);

tex = assetManager.loadTexture(“mygame/surface.jpg”);

tex.setWrap(Texture.WrapMode.Repeat);

mat.setTexture(“m_ColorMap”, tex);

/*

  • And then what ???

    /

    surface.setMaterial(mat);

    rootNode.attachChild(sky);



    }



    @Override

    public void simpleUpdate(float tpf) {

    // make the player rotate

    if (isrunning){

    ttime += tpf;

    int xpos = null;

    /

  • How do I GET the x position of the texture?
  • xpos = mat.getTexture().getX() ???

    /

    xpos -= tpf
    100;

    if (xpos < -200){

    xpos =+ 100;

    }

    /*
  • How do I SET the x position of the texture?
  • xpos = mat.getTexture().setX() ???

    */

    }

    }

    }




    How hard can it possibly be? (sob)

    Do I need to learn OpenGL native commands to get it going?

Sorry nehon for not addressing the rest of your post.



How do I get the frag shader in order to get the coordinates? Is it in the texture or in the material?

Hmm…sorry, i meant the vert shader.



you have to :

  • create your own j3md file (copy the simpleTextured one)
  • in the WorldParameters bloc add Tpf
  • copy the SimpleTextured.vert shader and name it ScrollingTexture.vert
  • in this shader add a uniform : uniform float g_Tpf
  • you can see the line texCoord=inTexCoord, you have to do your modification after that line, change texCoord.x or texCoord.y based on the g_Tpf
  • don’t forget to change the VertexShader GLSL100: Common/MatDefs/Misc/SimpleTextured.vert line in the j3md file to VertexShader GLSL100: Your/Path/To/Your/Shader/ScrollingTexture.vert



    then in your code create a material based on this new J3md file…it should work

Just busted this out since one day I’ll probably need it. It’s far from perfect, and might not be exactly what you need, but it should be enough to get started. For instance, it might be better to have two scroll floats to control the x and the y scroll independently.



You’re going to need to change TWO lines, depending on where you stick this stuff.



In the J3MD:

VertexShader GLSL100: scrollShader/scrollShader.vert - Change this to where you put the vert.



In the test case:

mat = new Material(assetManager, “scrollShader/scrollShader.j3md”); - Change this to where you put the j3md.



Modify the scrollSpeed variable to control how fast it scrolls.



Have fun!

~FlaH



The J3MD:



[java]

MaterialDef Scroll Texture {



MaterialParameters {

Texture2D m_ColorMap

Float m_Scroll

Boolean m_YCoCg

Boolean m_LATC

Boolean m_Normalize

Boolean m_ShowAlpha

}



Technique {

VertexShader GLSL100: scrollShader/scrollShader.vert

FragmentShader GLSL100: Common/MatDefs/Misc/SimpleTextured.frag



WorldParameters {

WorldViewProjectionMatrix

}



Defines {

DXT_YCOCG : m_YCoCg

NORMAL_LATC : m_LATC

NORMALIZE : m_Normalize

SHOW_ALPHA : m_ShowAlpha

}

}



Technique FixedFunc {

}



}

[/java]



The Vert:



[java]

uniform mat4 g_WorldViewProjectionMatrix;

uniform float m_Scroll;



attribute vec3 inPosition;

attribute vec2 inTexCoord;



varying vec2 texCoord;



void main(){

gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);



texCoord = vec2(inTexCoord[0] + m_Scroll,

inTexCoord[1] + m_Scroll);

}

[/java]



A Test case:



[java]

public class TestScrollShader extends SimpleApplication {



Geometry surface;

Material mat;



float scrollAmt = 0;

float scrollSpeed = 1;



public static void main(String[] args) {

TestScrollShader app = new TestScrollShader();

app.start();

}



@Override

public void simpleInitApp() {

Quad quad = new Quad(5, 5);

surface = new Geometry(“Quad”, quad);

mat = new Material(assetManager, “scrollShader/scrollShader.j3md”);

Texture tex = assetManager.loadTexture(“Textures/ColoredTex/Monkey.png”);

tex.setWrap(Texture.WrapMode.Repeat);

mat.setTexture(“m_ColorMap”, tex);

mat.setFloat(“m_Scroll”, 0.01f);

surface.setMaterial(mat);

rootNode.attachChild(surface);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



scrollAmt += scrollSpeed * tpf;

if(scrollAmt > 1) {

scrollAmt = scrollAmt - 1;

}

mat.setFloat(“m_Scroll”, scrollAmt);

}

}

[/java]

nehon and teflah,



thank you for the responses.



Teflah, thanks for the details. I could not have done that without the explanation cause frankly the two first files I don’t know what I am looking at? Is this the language used by OpenGL? Is this parsed real time or is it translated before the program starts?



Anyhow, I get the error…



Error while copying native libraries

java.io.FileNotFoundException: C:UsersAdminDevelopmentJavaProjectstestscrollshaderlwjgl.dll (Process cannot access the file. Another process is currently using it.)

at java.io.FileOutputStream.open(Native Method)

at java.io.FileOutputStream.(FileOutputStream.java:179)

at java.io.FileOutputStream.(FileOutputStream.java:131)

at com.jme3.system.Natives.extractNativeLib(Natives.java:72)

at com.jme3.system.Natives.extractNativeLibs(Natives.java:167)

at com.jme3.system.JmeSystem.initialize(JmeSystem.java:347)

at com.jme3.system.JmeSystem.newContext(JmeSystem.java:267)

at com.jme3.app.Application.start(Application.java:316)

at com.jme3.app.Application.start(Application.java:299)

at com.jme3.app.SimpleApplication.start(SimpleApplication.java:122)

at testscrollshader.TestScrollShader.main(TestScrollShader.java:28)



I haven’t gotten any further than that :frowning:

Ok, I got it to work.



I put it in a folder called testscrollshader like you did in the example.

My bad.



Thanks a lot for all the help.

Hi guys!



First of all I would like to thank you for this topic. It was very helpful for me. I did a shader according to your explanation.



http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/forum/topic/fakeparticleblow-shader/



I’ve got one question:

Is it possible to make texture animation without simpleUpdate(float tpf)?

I mean to make the animation in a shader…

Is it possible to make texture animation without simpleUpdate(float tpf)?



No not possible, since shaders have no understanding of anything not being themself or a parameter passed.

Actually you can in JME3.

there is a g_Tpf ot g_Time uniform passed to the shader if you declare it in the worldParameters section of the j3md file

2 Likes
nehon said:
Actually you can in JME3.
there is a g_Tpf ot g_Time uniform passed to the shader if you declare it in the worldParameters section of the j3md file


Really? 0o I went with the simpleUpdate pass-on method too for my shaders, didn't know that one yet. Is it in the wiki somewhere? Must have overlooked it :/

Yep, it’s written in the wiki, in the shader doc https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:jme3_shaders

The complete list of global uniforms that can be used in JME3 can be found here.

also, half of the topic could’ve been done by, by using the forum’s search function:



http://hub.jmonkeyengine.org/groups/general-2/forum/topic/animated-2d-sprites/ :wink:

Nehon, thank you for your answering. Now, we can use GPU animation. It’s really cool.



I tried g_Tpf, but it did not work for me. But g_Time works fine!!! Thanks a lot!



I uploaded my shader with GPU animation to: http://code.google.com/p/jme-glsl-shaders/

Mhh maybe there is a bug with g_Tpf, i’ll look into it