Android Open Source - AndroidExperiments Particle Test Renderer






From Project

Back to project page AndroidExperiments.

License

The source code is released under:

MIT License

If you think the Android project AndroidExperiments listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.brandonlight.gles2demos;
//from w  w w  . j ava2s. c  om
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;

public class ParticleTestRenderer implements GLSurfaceView.Renderer {

  static {
        System.loadLibrary("native_test");
    }
  
    String mVsSource;
    String mFsSource;
    
    IntBuffer mIndexBuffer;

    FloatBuffer mPosVB;
    FloatBuffer mTexVB;
    int mPosVbId, mTexVbId, mVsId, mFsId, mProgramId;
   
    // particle data
    int mParticleCount;
    float[] mPositions;
    float[] mVelocities;
    float[] mTexCoords;
    
    public native void testPrint();
    public native void testGLES2();
    
    public ParticleTestRenderer()
    {
        //*
        mVsSource = new String();
        mVsSource = "precision highp float; \n" +
                    "attribute  vec3 in_Position;               \n" +
                    "attribute  vec2 in_TexCoord;               \n" +
                    "varying vec2 v_TexCoord;                   \n" +
                    "void main(void)                            \n" +
                    "{                                          \n" +
                    "   gl_PointSize = 4.0;                       \n" +
                    "   gl_Position = vec4(in_Position, 1.0);   \n" +
                    "   v_TexCoord = in_TexCoord;               \n" +
                    "}                                          \n";

        mFsSource = new String();
        mFsSource = //"#version 100 \n"+
                    "precision mediump float;\n" + 
                    "varying vec2 v_TexCoord;                         \n" +
                    "void main(void)                                  \n" +
                    "{                                                \n" +
                    "   gl_FragColor = vec4((v_TexCoord.x * 2.0), \n" +
                    "                       (v_TexCoord.y * 2.0), \n" +
                    "                       1.0,                      \n" +
                    "                       1.0);                     \n"+
                    "}                                                \n";
                    
    }

    public void onDrawFrame(GL10 gl)
    {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        
        updateParticles(0.01f);
        
        int posAttribLoc = GLES20.glGetAttribLocation(mProgramId, "in_Position");
        int texAttribLoc = GLES20.glGetAttribLocation(mProgramId, "in_TexCoord");
        
        GLES20.glEnableVertexAttribArray(posAttribLoc);
        GLES20.glEnableVertexAttribArray(texAttribLoc);
        checkGlError("vaPointer");
        
        
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mPosVbId);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mParticleCount*3*4, mPosVB, GLES20.GL_STATIC_DRAW);
        GLES20.glVertexAttribPointer(posAttribLoc, 3, GLES20.GL_FLOAT, false, 3*4, 0);
        
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mTexVbId);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mParticleCount*2*4, mTexVB, GLES20.GL_STATIC_DRAW);
        GLES20.glVertexAttribPointer(texAttribLoc, 2, GLES20.GL_FLOAT, false, 2*4, 0);
       
        GLES20.glUseProgram(mProgramId);
        //particleCount
        GLES20.glDrawElements(GLES20.GL_POINTS, mParticleCount, GLES20.GL_UNSIGNED_INT, mIndexBuffer);

    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
     
    public void updateParticles(float timestep)
    {
      //testPrint();
      
      
      float bounds = 1.0f;
      
      timestep *= 3.0f;
      
      // calculate new velocity with x/'friction' or y/'gravity' constants
      float gravityDecel = 4.0f * timestep;
      //float xFriction = 3.0f * timestep;
      
      for (int i = 0; i < mParticleCount; ++i)
      {
        int posIndex = i * 3;
            int velIndex = i * 3;
            
        mVelocities[velIndex+1] -= gravityDecel; // gravity is always negative
        
        float x = mPositions[posIndex+0] + (mVelocities[velIndex+0] * timestep);
        mPositions[posIndex+0] = Math.min(bounds, Math.max(-bounds, x));

        if ((mPositions[posIndex+0] <= -bounds) || (mPositions[posIndex+0] >= bounds))
            {
          mVelocities[velIndex+0] *= -0.5f;
            }
     
        float y = mPositions[posIndex+1] + (mVelocities[velIndex+1] * timestep);
        mPositions[posIndex+1] = Math.min(bounds, Math.max(-bounds, y));
            
            // change direction
            if ((mPositions[posIndex+1] <= -bounds) || (mPositions[posIndex+1] >= bounds))
            {
              mVelocities[velIndex+1] *= -0.5f;
            }
      }
      
        ByteBuffer posVb = ByteBuffer.allocateDirect(mParticleCount*3*4);
        posVb.order(ByteOrder.nativeOrder());
        mPosVB = posVb.asFloatBuffer();
        mPosVB.put(mPositions);
        mPosVB.position(0);
        
        ByteBuffer texVb = ByteBuffer.allocateDirect(mParticleCount*2*4);
        texVb.order(ByteOrder.nativeOrder());
        mTexVB = texVb.asFloatBuffer();
        mTexVB.put(mTexCoords);
        mTexVB.position(0);
    }
    
    public void initParticles(float impulseX, float impulseY)
    {
      // initial layout of particles is in a 2D grid
      int width = 25, height = 25; 
        mParticleCount = width * height;
        
        if (mPositions == null)
        {
          mPositions  = new float[mParticleCount * 3];
        }
        if (mVelocities == null)
        {
          mVelocities = new float[mParticleCount * 3];
        }
        if (mTexCoords == null)
        {
          mTexCoords  = new float[mParticleCount * 2];
        }
        
        
      for (int w = 0; w < width; ++w)
        {
            for (int h = 0; h < height; ++h)
            {
                int posIndex = (h * width * 3) + (w * 3);
                int velIndex = (h * width * 3) + (w * 3);
                int texIndex = (h * width * 2) + (w * 2);

                float posx = -1.0f + ((2.0f / (float)width) * w);
                float posy = -1.0f + ((2.0f / (float)height) * (float) h);

                mPositions[posIndex+0] = posx;
                mPositions[posIndex+1] = posy;
                mPositions[posIndex+2] = 0.5f;

                mTexCoords[texIndex+0] = w / (float)width;
                mTexCoords[texIndex+1] = 1.0f - h / (float)height;

                float magnitude = (float)Math.sqrt((double)(posx + impulseX)*(posx + impulseX) + (double)(posy + impulseY)*(posy + impulseY));

                mVelocities[velIndex+0] = (posx + impulseX) / magnitude;
                mVelocities[velIndex+1] = (posy + impulseY) / magnitude;
                mVelocities[velIndex+2] = 0;
            }
        }
      
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    {
      testGLES2();
      initParticles(0, 0);
        
        IntBuffer bufferIdBuffer = IntBuffer.allocate(2);
        GLES20.glGenBuffers(2, bufferIdBuffer);
        
        mPosVbId = bufferIdBuffer.get(0);   
        mTexVbId = bufferIdBuffer.get(1);

        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        
        
        int[] indices = new int[mParticleCount];
        for (int i = 0; i < mParticleCount; ++i)
        {
            indices[i] = i;
        }
        
        mIndexBuffer = IntBuffer.allocate(mParticleCount);
        mIndexBuffer.put(indices);
        mIndexBuffer.position(0);
        
        mVsId = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(mVsId, mVsSource);
        GLES20.glCompileShader(mVsId);
        checkGlError("compile VS");
        
        String infoLog = GLES20.glGetShaderInfoLog(mVsId);
        Log.d("shaderLog", infoLog);

        mFsId = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(mFsId, mFsSource);
        GLES20.glCompileShader(mFsId);
        checkGlError("compile FS");

        infoLog = GLES20.glGetShaderInfoLog(mFsId);
        Log.d("shaderLog", infoLog);
        
        mProgramId = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgramId, mVsId);
        GLES20.glAttachShader(mProgramId, mFsId);

        GLES20.glLinkProgram(mProgramId);

        String programLog = GLES20.glGetProgramInfoLog(mProgramId);
        Log.d("programLog", programLog);
        checkGlError("link shaders");   
    }
    
    
    
    private void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e("ParticleTestRenderer", op + ": glError " + error);
            throw new RuntimeException(op + ": glError " + error);
        }
    }
}




Java Source Code List

com.brandonlight.gles2demos.GLES2DemosActivitity.java
com.brandonlight.gles2demos.ParticleTestRenderer.java
com.brandonlight.gles2demos.ParticleTestView.java
com.brandonlight.gles2demos.TouchDemoRenderer.java
com.brandonlight.gles2demos.TouchDemoView.java
com.brandonlight.gles2demos.TriColorVertRenderer.java
com.brandonlight.gles2demos.TriColorVertView.java