mardi 25 décembre 2018

Is libgdx ModelBatch suitable for Ashley?

In other words, what's the best practice to render modelparts in ashley's rendering subsystem?

  • The Question in Details:

The initial thought is put any visual effects handling into shader as much as possible. Performance of this is better because they are handled in GPU. There are lots of example like this at three.js and shadertoy.

To do this in Ashley, I can use a component with all the parameters sent to GPU before rendering any mesh. So the render sub system would look like:

public class SysDynamicRender extends IteratingSystem {
    ShaderProgram program;
    private void initShader() {
        program = new ShaderProgram("vert", "frag");

        // variables only about the shader program, not about meshes
        u_projTrans = program.getUniformLocation("u_projTrans");
        u_worldTrans = program.getUniformLocation("u_worldTrans");
        u_colorLoc = program.getUniformLocation("u_color");
        texBase = new Texture("data/modlib/color-blocks.jpg");
    }

    @Override
    protected void processEntity(Entity entity, float deltaTime) {
        // in Ashley, we only get meshparts from entity
        renderQueue.add(entity);
    }

    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
        // render
        for (Entity e : renderQueue) {
            // way 1: use the help of ModelBatch
            CmpModelInst cmpModelInst = e.getComponent(CmpModelInst.class)
            modelBatch.render(cmpModelInst.inst(), shader);

            // way 2: rendering meshpart directly (not work)
            // 2.1 get the Renderable (out)
            DynaAttr attr = e.getComponent(CmpVisuals.class).attr;
            ModelInstance inst = cmpModelInst.class).inst();
            Node n = inst.getNode("cube1_cube1_auv");
            out = inst.getRenderable(out, n);
            // 2.2 rendert meshpart with shader program
            program.setUniformMatrix(u_worldTrans, out.worldTransform);
            program.setUniformf(u_colorLoc, attr.effects());
            program.setUniformf(u_factorLoc, attr.u_factorF());
            out.meshPart.render(program);
        }

    renderQueue.clear();
    }
}

I think there must be a better way to implement update().

The question is what's that?

  • Further Consideration

The visual effects parameters like color, reflecting angles (for different color) are attributes of the shaders, they shouldn't been updated at each rendering call iterating over meshparts. It's a performance cost because CPU needing send data to GPU - if I understand correctly.

Ashley provided a schema for solving this. Just implement a dynamic shader and put the referencing component into entity, let Ashley call the correct sub system.

In this way, ModelBatch must not suitable? The ModelBatch.flush() is simply iterating over it's parts.

Reference:

ModelBatch.java: https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g3d/ModelBatch.java

wiki: https://github.com/libgdx/libgdx/wiki/ModelBatch

Something I don't understand?

Aucun commentaire:

Enregistrer un commentaire