使用着色器LibGDX

时间:2014-06-02 02:38:40

标签: java libgdx glsl shader

我非常需要帮助。我正在libgdx上进行2D游戏。一切都运作良好,今天我决定制作一个小型的二维粒子系统来制作烟花。我记得我最近在 OpenGL ES 2.0 for Android:快速入门指南一书中使用3d中的着色器完成了这项任务。所以我复制了大部分代码并开始修改一些内容,以便它可以与Libgdx和2d一起使用。这个粒子编辑器的工作原理是有一个大浮点数组,每个粒子可以容纳8个东西:2个位置,x和y; 3种颜色,rgb; 2个方向,x和y; 1开始时间。现在重复阵列中允许的每个粒子。我将最大粒子设置为10,000,因此该阵列中有80,000个浮点数,意味着320,000个字节。无论如何,现在我拥有所有这些属性。现在我将这些属性放入着色器程序中。着色器程序使用它们按方向移动粒子,按时间淡化颜色,并应用重力。所以无论如何,它使用纯OpenGL,但我想使用LibGDX框架。我试图保留尽可能多的旧代码。我认为我所做的会起作用,但它不会显示任何东西。这是代码......

ParticleFirework.java:

public class ParticleFirework {

    private final Vector2 position;
    private final Vector2 direction;
    private final int color;

    private final float angleVariance;
    private final float speedVariance;

    private final Random random = new Random();
    private float[] rotationMatrix = new float[16];
    private float[] directionVector = new float[4];
    private float[] resultVector = new float[4];

    public ParticleFirework(Vector2 position, Vector2 direction, int color,
            float angleVarianceInDegrees, float speedVariance) {
        this.position = position;
        this.direction = direction;
        this.color = color;
        this.angleVariance = angleVarianceInDegrees;
        this.speedVariance = speedVariance;

        directionVector[0] = direction.x;
        directionVector[1] = direction.y;
        directionVector[2] = 0;
    }

    public void addParticles(ParticleSystem particleSystem, float currentTime,
            int count) {
        for (int i = 0; i < count; i++) {
            setRotateEulerM(rotationMatrix, 0, (random.nextFloat() - 0.5f)
                    * angleVariance, (random.nextFloat() - 0.5f)
                    * angleVariance, (random.nextFloat() - 0.5f)
                    * angleVariance);

            multiplyMV(resultVector, 0, rotationMatrix, 0, directionVector, 0);

            float speedAdjustment = 1f + random.nextFloat() * speedVariance;

            Vector2 thisDirection = new Vector2(resultVector[0]
                    * speedAdjustment, resultVector[1] * speedAdjustment);

            particleSystem.addParticle(position, color, thisDirection,
                    currentTime);
        }
    }

}

ParticleSystem.java:

public class ParticleSystem {
    private static final int PARTICLE_POSITION_COUNT = 2;
    private static final int PARTICLE_COLOR_COUNT = 3;
    private static final int PARTICLE_DIRECTION_COUNT = 2;
    private static final int PARTICLE_START_TIME_COUNT = 1;
    private static final int BYTES_IN_A_FLOAT = 4;

    private static final int TOTAL_COUNT = PARTICLE_POSITION_COUNT
            + PARTICLE_COLOR_COUNT + PARTICLE_DIRECTION_COUNT
            + PARTICLE_START_TIME_COUNT;

    private static final int STRIDE = TOTAL_COUNT * BYTES_IN_A_FLOAT;

    private final float[] particles;
    private final int maxParticleCount;

    private int currentParticleCount;
    private int nextParticle;
    private FloatBuffer particleFloatBuffer;

    public ParticleSystem(int maxParticleCount) {
        particles = new float[maxParticleCount * TOTAL_COUNT];
        this.maxParticleCount = maxParticleCount;
        particleFloatBuffer = ByteBuffer
                .allocateDirect(particles.length * BYTES_IN_A_FLOAT)
                .order(ByteOrder.nativeOrder()).asFloatBuffer().put(particles);
    }

    public void addParticle(Vector2 position, int color, Vector2 direction,
            float particleStartTime) {
        final int particleOffset = nextParticle * TOTAL_COUNT;

        int currentOffset = particleOffset;
        nextParticle++;

        if (currentParticleCount < maxParticleCount) {
            currentParticleCount++;
        }

        if (nextParticle == maxParticleCount) {
            nextParticle = 0;
        }

        particles[currentOffset++] = position.x;
        particles[currentOffset++] = position.y;

        particles[currentOffset++] = Color.red(color) / 255f;
        particles[currentOffset++] = Color.green(color) / 255f;
        particles[currentOffset++] = Color.blue(color) / 255f;

        particles[currentOffset++] = direction.x;
        particles[currentOffset++] = direction.y;

        particles[currentOffset++] = particleStartTime;

        particleFloatBuffer.position(particleOffset);
        particleFloatBuffer.put(particles, particleOffset, TOTAL_COUNT);
        particleFloatBuffer.position(0);
    }

    public void bindData(ShaderProgram particleProgram) {
        int dataOffset = 0;
        particleProgram.setVertexAttribute("a_Position",
                PARTICLE_POSITION_COUNT, GL20.GL_FLOAT, false, STRIDE,
                dataOffset);
        dataOffset += PARTICLE_POSITION_COUNT;

        particleProgram.setVertexAttribute("a_Color",
                PARTICLE_COLOR_COUNT, GL20.GL_FLOAT, false, STRIDE,
                dataOffset);
        dataOffset += PARTICLE_COLOR_COUNT;

        particleProgram.setVertexAttribute("a_DirectionVector",
                PARTICLE_DIRECTION_COUNT, GL20.GL_FLOAT, false, STRIDE,
                dataOffset);
        dataOffset += PARTICLE_DIRECTION_COUNT;

        particleProgram.setVertexAttribute("a_ParticleStartTime",
                PARTICLE_START_TIME_COUNT, GL20.GL_FLOAT, false, STRIDE,
                dataOffset);
    }

    public void draw() {
        glDrawArrays(GL_POINTS, 0, currentParticleCount);
    }
}

ParticleGame.java:

public class ParticlesGame extends ApplicationAdapter {
    SpriteBatch batch;
    ShaderProgram particleProgram;
    OrthographicCamera camera;
    Texture img;

    private ParticleSystem particleSystem;
    private ParticleFirework firework;

    private long globalStartTime;

    @Override
    public void create() {
        batch = new SpriteBatch();
        img = new Texture("badlogic.jpg");
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        globalStartTime = System.nanoTime();

        final Vector2 particleDirection = new Vector2(0f, 0.5f);
        final float angleVarianceInDegrees = 5f;
        final float speedVariance = 1f;

        particleProgram = new ShaderProgram("shaders/particle_shader.vs",
                "shaders/particle_shader.fs");

        particleSystem = new ParticleSystem(10000);

        firework = new ParticleFirework(new Vector2(0f, 0f), particleDirection,
                Color.rgb(255, 50, 5), angleVarianceInDegrees, speedVariance);
    }

    @Override
    public void render() {
        float currentTime = (System.nanoTime() - globalStartTime) / 1000000000f;

        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        firework.addParticles(particleSystem, currentTime, 5);

        particleProgram.begin();
        FloatBuffer matrixBuffer = ByteBuffer
                .allocateDirect(camera.combined.getValues().length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(camera.combined.getValues());

        /** Set the uniforms **/
        particleProgram.setUniformMatrix4fv("u_matrix", matrixBuffer, 1, false);
        particleProgram.setUniform1fv("u_Time", new float[] {currentTime}, 0, 1);

        /** Bind data **/
        particleSystem.bindData(particleProgram);

        particleSystem.draw();
    }
}

particle_shader.vs

uniform mat4 u_Matrix;
uniform float u_Time;

attribute vec3 a_Position;  
attribute vec3 a_Color;
attribute vec3 a_DirectionVector;
attribute float a_ParticleStartTime;

varying vec3 v_Color;
varying float v_ElapsedTime;

void main()                    
{                                         
    v_Color = a_Color;       
    v_ElapsedTime = u_Time - a_ParticleStartTime;    

    float gravityFactor = v_ElapsedTime * v_ElapsedTime / 8.0;

    vec3 currentPosition = a_Position + (a_DirectionVector * v_ElapsedTime);    
    currentPosition.y -= gravityFactor;    

    gl_Position = u_Matrix * vec4(currentPosition, 1.0);    
    gl_PointSize = 25.0;    
}       

0 个答案:

没有答案