将3d原型用于粒子系统

时间:2016-07-28 02:20:03

标签: android opengl-es opengl-es-2.0

我从这开始作为基础。

https://github.com/danginsburg/opengles-book-samples/tree/master/Android/Ch13_ParticleSystem

所以我一直在读这本书的基础,我正在努力理解如何将另一个对象加载到不是位图的缓冲区中。例如,我创建了一个包含法线,顶点和纹理的立方体类

class Cube
{


    public  final float VERTICES[] = {
            -0.5f, -0.5f, -0.5f, // Back bottom left
            0.5f, -0.5f, -0.5f,  // Back bottom right
            0.5f, 0.5f, -0.5f,   // Back top right
            -0.5f, 0.5f, -0.5f,  // Back top left
            -0.5f, -0.5f, 0.5f,  // Front bottom left
            0.5f, -0.5f, 0.5f,   // Front bottom right
            0.5f, 0.5f, 0.5f,    // Front top right
            -0.5f, 0.5f, 0.5f    // Front top left
    };

    final float[] cubeNormalData =
            {
                    // Front face
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,
                    0.0f, 0.0f, 1.0f,

                    // Right face
                    1.0f, 0.0f, 0.0f,
                    1.0f, 0.0f, 0.0f,
                    1.0f, 0.0f, 0.0f,
                    1.0f, 0.0f, 0.0f,
                    1.0f, 0.0f, 0.0f,
                    1.0f, 0.0f, 0.0f,

                    // Back face
                    0.0f, 0.0f, -1.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 0.0f, -1.0f,

                    // Left face
                    -1.0f, 0.0f, 0.0f,
                    -1.0f, 0.0f, 0.0f,
                    -1.0f, 0.0f, 0.0f,
                    -1.0f, 0.0f, 0.0f,
                    -1.0f, 0.0f, 0.0f,
                    -1.0f, 0.0f, 0.0f,

                    // Top face
                    0.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,
                    0.0f, 1.0f, 0.0f,

                    // Bottom face
                    0.0f, -1.0f, 0.0f,
                    0.0f, -1.0f, 0.0f,
                    0.0f, -1.0f, 0.0f,
                    0.0f, -1.0f, 0.0f,
                    0.0f, -1.0f, 0.0f,
                    0.0f, -1.0f, 0.0f
            };


    final float[] cubeTextureCoordinateData =
            {
                    // Front face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f,

                    // Right face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f,

                    // Back face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f,

                    // Left face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f,

                    // Top face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f,

                    // Bottom face
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 1.0f,
                    1.0f, 0.0f
            };
}

我假设我需要编写一个新函数来加载多维数据集数据,可能需要帮助充实它。

private int loadCube() {
    Cube cube = new Cube();
    float [] cubeData;
    float[] cubeVerts = cube.getVERTICES();
    float[] cubeNorms = cube.getCubeNormalData();
    float[] cubeTexts = cube.getCubeTextureCoordinateData();

    for (int i=0; i<NUM_PARTICLES;i++)
    {
        // add all the parts to the buffer somehow

    }
       //do some kind og GLES20.glBind
    return particleId[0]; // im not sure what this index does just yet but loadTexture has one
}

我认为这就是我必须做的事情,但是如果我错过了一些重要的事情请告诉我。

EDIT **********************************************

好的,我一直在取得进步并意识到我的问题可能太模糊了。我目前正在获取索引超出范围的错误,但我确定我错误地绑定了数据并且使用着色器做错了。如果你能指出我做错了什么将非常感激

我将数据加载到一个大小为32的缓冲区中,其中:             // [0]是终身             // 1-3是结束位置             // 4-6是开始发布的             // 7-31是从立方体

添加的顶点数据

所以我有这些成员变量

private FloatBuffer mParticles;
private Context mContext;

private final int NUM_PARTICLES = 10000;
private final int PARTICLE_SIZE = 32; // was 7

private final float[] mParticleData = new float[NUM_PARTICLES * PARTICLE_SIZE];

然后我有一个onSurfaceCreate函数,当我尝试添加顶点时,我得到一个越界错误

public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
    String vShaderStr =
            "uniform float u_time;                                \n" +
                    "uniform vec3 u_centerPosition;                       \n" +
                    "attribute float a_lifetime;                          \n" +
                    "attribute vec3 a_startPosition;                      \n" +
                    "attribute vec3 a_endPosition;                        \n" +
                    "varying float v_lifetime;                            \n" +
                    "void main()                                          \n" +
                    "{                                                    \n" +
                    "  if ( u_time <= a_lifetime )                        \n" +
                    "  {                                                  \n" +

                    " vec3 rotation = vec3(.1*cos(u_time*10),0,.1*cos(u_time*10));             \n" +
                    "    gl_Position.xyz = a_startPosition + rotation +              \n" +
                    "                      (u_time/10f * a_endPosition);      \n" +
                    "    gl_Position.xyz += u_centerPosition;             \n" +
                    "    gl_Position.w = 1.0;                             \n" +
                    "  }                                                  \n" +

                    "  else                                               \n" +
                    "     gl_Position = vec4( -1000, -1000, -1000, 0 );       \n" +

                    "  v_lifetime = 1.0 - ( u_time / a_lifetime );        \n" +
                    "  v_lifetime = clamp ( v_lifetime, 0.0, 1.0 );       \n" +
                    "  gl_PointSize =  40.0; \n" +
                    "}";


    String fShaderStr =
            "precision mediump float;                             \n" +
                    "uniform vec4 u_color;                                \n" +
                    "varying float v_lifetime;                            \n" +
                    "uniform sampler2D s_texture;                         \n" +
                    "void main()                                          \n" +
                    "{                                                    \n" +
                    "  vec4 texColor;                                     \n" +
                    "  texColor = texture2D( s_texture, gl_PointCoord );  \n" +
                    "  gl_FragColor = vec4( u_color ) * texColor;         \n" +
                    "  gl_FragColor.a *= v_lifetime;                      \n" +
                    "}                                                    \n";

    // Load the shaders and get a linked program object
    mProgramObject = ESShader.loadProgram(vShaderStr, fShaderStr);

    // Get the attribute locations
    mLifetimeLoc = GLES20.glGetAttribLocation(mProgramObject, "a_lifetime");
    mStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_startPosition");
    mEndPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_endPosition");
    mVertStartPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "a_vertStartPosition");

    // Get the uniform locations
    mTimeLoc = GLES20.glGetUniformLocation(mProgramObject, "u_time");
    mCenterPositionLoc = GLES20.glGetUniformLocation(mProgramObject, "u_centerPosition");
    mColorLoc = GLES20.glGetUniformLocation(mProgramObject, "u_color");
    mSamplerLoc = GLES20.glGetUniformLocation(mProgramObject, "s_texture");

    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    Cube cube = new Cube();

    float[] cubeVerts = cube.getVERTICES();

    // Fill in particle data array
    Random generator = new Random();

    for (int i = 0; i < NUM_PARTICLES; i++) {  //num particles =31
        //[0] is lifetime
        //1-3 is end pos
        //4-6 is start post
        //7-31 is vert data which is added from the cube
        // Lifetime of particle
        mParticleData[i * PARTICLE_SIZE + 0] = generator.nextFloat() *10f;

        // End position of particle
        mParticleData[i * PARTICLE_SIZE + 1] = generator.nextFloat() * 2.0f - 1.0f;
        mParticleData[i * PARTICLE_SIZE + 2] = generator.nextFloat() * 5.0f +5f;// - 1.0f;
        mParticleData[i * PARTICLE_SIZE + 3] = generator.nextFloat() * 2.0f - 1.0f;

        // Start position of particle
        mParticleData[i * PARTICLE_SIZE + 4] = generator.nextFloat() * 0.25f - 0.125f;
        mParticleData[i * PARTICLE_SIZE + 5] = generator.nextFloat() * 0.25f - 0.125f;
        mParticleData[i * PARTICLE_SIZE + 6] = generator.nextFloat() * 0.25f - 0.125f;

        for(int x=0; x<cubeVerts.length;x++)
        {
            mParticleData[i *PARTICLE_SIZE + 7 + x] = cubeVerts[x];
        }


    }
    mParticles = ByteBuffer.allocateDirect(mParticleData.length * 4)
            .order(ByteOrder.nativeOrder()).asFloatBuffer();
    mParticles.put(mParticleData).position(0);

    // Initialize time to cause reset on first update
    mTime = 10f;


}

在我的onDrawFrame中我有这个:

public void onDrawFrame(GL10 glUnused) {
    update();

    // Set the viewport
    GLES20.glViewport(0, 0, mWidth, mHeight);

    // Clear the color buffer
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // Use the program object
    GLES20.glUseProgram(mProgramObject);

    // Load the vertex attributes
    mParticles.position(0);
    GLES20.glVertexAttribPointer(mLifetimeLoc, 1, GLES20.GL_FLOAT,
            false, PARTICLE_SIZE * 4,
            mParticles);

    mParticles.position(1);
    GLES20.glVertexAttribPointer(mEndPositionLoc, 3, GLES20.GL_FLOAT,
            false, PARTICLE_SIZE * 4,
            mParticles);

    mParticles.position(4);
    GLES20.glVertexAttribPointer(mStartPositionLoc, 3, GLES20.GL_FLOAT,
            false, PARTICLE_SIZE * 4,
            mParticles);

    mParticles.position(7);
    GLES20.glVertexAttribPointer(mVertStartPositionLoc, 4, GLES20.GL_FLOAT,
            false, PARTICLE_SIZE * 4,
            mParticles);


    GLES20.glEnableVertexAttribArray(mLifetimeLoc);
    GLES20.glEnableVertexAttribArray(mEndPositionLoc);
    GLES20.glEnableVertexAttribArray(mStartPositionLoc);
   GLES20.glEnableVertexAttribArray(mVertStartPositionLoc);

    // Blend particles
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE);



    // Set the sampler texture unit to 0
    GLES20.glUniform1i(mSamplerLoc, 0);

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    //GLES20.glDrawArrays(GLES20.GL_POINTS, 0, NUM_PARTICLES);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,NUM_PARTICLES*36);
}

0 个答案:

没有答案