[RESOLVED] My first shader: A spritesheet animation

Hmm - maybe I can explain where I’m trying to get and we can see if that sheds light on this. Whenver someone in my game dies, a trophy/prize is spawn instead (for someone else to pick up). Every trophy would be a seperate geometry, attached to a trophy-node.

The quad I attach to the geometry is displaying an animation based on a spritesheet. In my shader, I simply use the base TexCoord (as mentioned above) and add an offset to this based on time and animation speed.

Perhaps there are more options here:

  1. Attach the same material to different geometries (and/or attach the same quad to different geometries)
  2. Batch all trophy nodes (dont know anything about that process, so entirely unsure about any pros or cons)

This is my TestCase:

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;

public class MainShaderTest extends SimpleApplication {

public static void main(String[] args) {
    MainShaderTest app = new MainShaderTest();
    app.start();
}
Quad quad;
private Geometry geom;
private Material mat;
@Override
public void simpleInitApp() {
    
    quad = new Quad(0.5f, 0.5f);
    geom = new Geometry("Bounty", quad);
    mat = assetManager.loadMaterial("Materials/AnimateSpriteShader.j3m");
    geom.setMaterial(mat);
    geom.setLocalTranslation(0,0,5);
    rootNode.attachChild(geom);
}
}

This is my material:

Material BountyMaterial : MatDefs/AnimateSpriteShader.j3md {
     MaterialParameters {
        AniTexMap : Textures/Subspace/prizes.png
        numTilesU : 10
        TileWidth : 16  
        TileHeight : 16
        Speed : 20                      
     }
    AdditionalRenderState {
      Blend Alpha
      Wireframe Off
    }
}

My vertex shader:

uniform mat4 g_WorldViewProjectionMatrix;
uniform float g_Tpf;
uniform float g_Time;

uniform int m_numTilesU;
uniform float m_Speed; 
uniform int m_TileWidth;

attribute vec3 inPosition; //The view
attribute vec2 inTexCoord;

varying vec2 texCoordAni; //parameter to calculate the correct texture coordinates and pass it to the frag shader

void main(){
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);

float tileDistance = float(g_Time*m_Speed);
int selectedTile = int(mod(float(tileDistance), m_numTilesU));

texCoordAni.x = (float(float(inTexCoord.x/m_numTilesU) + float(selectedTile)/float(m_numTilesU)));
texCoordAni.y = inTexCoord.y;
}

My fragment shader:

varying vec2 texCoordAni;
uniform sampler2D m_AniTexMap;

void main(){
    vec4 AniTex = texture2D(m_AniTexMap, vec2(texCoordAni));
    gl_FragColor = AniTex;
}

My material definition:

MaterialDef AnimateSpriteShader {
    
    MaterialParameters {
        Int numTilesU
        Float Speed
        Int TileWidth
        Int TileHeight
        Texture2D AniTexMap
    }
    Technique {
        VertexShader GLSL120 :   MatDefs/AnimateSpriteShader.vert
        FragmentShader GLSL120 : MatDefs/AnimateSpriteShader.frag

        WorldParameters {
            WorldViewProjectionMatrix
            Time
        }
    }
}
1 Like