我从这开始作为基础。
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);
}