I have a renderer which is an attempt to draw points as a textured square. Nothing is crashing and I have other items being drawn fine, but these squares are not being rendered, I believe it has something to do with data passed to the shader program in my drawTexturedPoint() function.
I have a FloatBuffer geometryBuffer which holds the vertice positions. 6 vertices with exactly the same vertices coordinates, one for each corner of the two triangles. There are multiple points within this buffer.
The shader program takes these vertices and manipulates them into the correct position based on the point (or square) size passed to the shader.
protected String getPointVertexShader()
{
// Define a simple shader program for our points.
final String pointVertexShader =
"uniform vec2 u_pointSize;
+ "uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "attribute vec2 a_TexCoordinate; \n"
+ "varying vec2 v_TexCoordinate; \n" // Passed into the fragment shader.
+ "void main() \n"
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate; \n" // Pass through the texture coordinate.
+ " gl_Position = u_MVPMatrix * a_Position; \n" // gl_Position is a special variable used to store the final position.
+ " gl_Position += vec4(gl_Position.w * u_pointSize * (a_TexCoordinate - vec2(0.5,0.5)), 0, 0);\n"
+ "} \n";
return pointVertexShader;
}
protected String getPointFragmentShader()
{
final String pointFragmentShader =
"precision mediump float; \n"
+ "uniform sampler2D u_Texture; \n" // The input texture.
+ "varying vec2 v_TexCoordinate;\n" // Interpolated texture coordinate per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = (texture2D(u_Texture, v_TexCoordinate));\n" // Pass the color directly through the pipeline.
+ "} \n";
return pointFragmentShader;
}
Note that u_pointSize is a vec2 in normalised device coordinates; the value should be the size in pixels divided by the viewport size in pixels.
Below is the function where it passes the data to the shader and does the draw.
private void drawTexturedPoint(final FloatBuffer geometryBuffer)
{
//GeometryBuffer holds all the points in one buffer.
GLES20.glUseProgram(mPointsProgramHandle);
mPointSizeHandle = GLES20.glGetAttribLocation(mPointsProgramHandle, "u_pointSize");
mPointMVPMatrixHandle = GLES20.glGetUniformLocation(mPointsProgramHandle, "u_MVPMatrix");
mTextureUniformHandle = GLES20.glGetUniformLocation(mPointsProgramHandle, "u_Texture");
mPointPositionHandle = GLES20.glGetAttribLocation(mPointsProgramHandle, "a_Position");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mPointsProgramHandle, "a_TexCoordinate");
// Pass in the texture coordinate information
mPointSize.position(0);
GLES20.glVertexAttribPointer(mPointSizeHandle, mVec2DataSize, GLES20.GL_FLOAT, false, 0, mPointSize);
GLES20.glEnableVertexAttribArray(mPointSizeHandle);
// Pass in the position information
geometryBuffer.position(0);
GLES20.glVertexAttribPointer(mPointPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, mPositionFloatStrideBytes, geometryBuffer);
GLES20.glEnableVertexAttribArray(mPointPositionHandle);
// Pass in the texture coordinate information
mSquareTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mVec2DataSize, GLES20.GL_FLOAT, false, 0, mSquareTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glUniformMatrix4fv(mPointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the cube.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, geometryBuffer.capacity()/mPositionDataSize);
}
Here are a few other relevant variables used in the draw function
private final int mBytesPerFloat = 4;
private final int mPositionOffset = 0;
private final int mPositionDataSize = 3;
private final int mPositionFloatStrideBytes = mPositionDataSize * mBytesPerFloat;
private FloatBuffer mPointSize;
private final int mVec2DataSize = 2;
// Texture coordinate data.
final float[] squareTextureCoordinateData =
{
// 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
};
This is the way I set the square size (hard-coded for now).
float psize = 25f/480f;
mPointSize.position(0);
mPointSize.put(psize);
mPointSize.put(psize);
mPointSize.flip();
Be most greatful for some assistance!
[EDIT] @user2359247 ok I see what you mean, I'll keep it as uniform, so I have altered: mPointSizeHandle = GLES20.glGetUniformLocation(mPointsProgramHandle, "u_pointSize");
Not quite sure how to pass the buffer through however, I haven't come across this before.
The other friendly question is, do you understand what I am trying to accomplish, I only ask as I am wondering if my mPointSize buffer has the correct data in it?
This solution for rendering points as textured squares came from someone else, so I am trying to piece this together.
So I don't really understand how to set the point size variable values or what type of function should be used to pass it into the shader:
u_pointSize is a vec2 in normalised device coordinates; the value should be the size in pixels divided by the viewport size in pixels.
Tried swapping:
mPointSize.position(0);
GLES20.glVertexAttribPointer(mPointSizeHandle, mVec2DataSize, GLES20.GL_FLOAT, false, 0, mPointSize); //Error code gets sent back after this line.
GLES20.glEnableVertexAttribArray(mPointSizeHandle);
with
GLES20.glUniform2fv(mPointSizeHandle, 1, mPointSize);
this is the surface at the moment:
should be more like this mock-up: