I'm trying to make a program with triangle and circle where triangle should be transparent, and circle needs to move on y axis. I can make circle and triangle, but don't know how to move circle. So I made a square and set it move on the y axis. My question is what is the best way to make a circle with movement, I thought about adding texture to square to look like a circle, but it will apply texture to the triangle as well. Any help would mean so much. Thanks!
Here's my code:
public class MyGLRender implements GLSurfaceView.Renderer{
Context con;
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] projectionMatrix = new float[16];
private float[] mVPMatrix = new float[16];
private final FloatBuffer squareVert;
private final FloatBuffer mColor;
private FloatBuffer triangleVert;
private final FloatBuffer tColor;
private int mvpMatrixHandle;
private int positionHandle;
private int colorHandle;
ShortBuffer indexBuffer = null;
short[] indeces={
0,1,2,
0,3,2
};
float i;
public int smer;
public MyGLRender(Context con)
{
this.con=con;
i=0;
smer=1;
final float[] square={
0.0f, 1.0f, 0.0f,
0.0f,0.0f,0.0f,
1.0f,0.0f,0.0f,
1.0f,1.0f,0.0f,
};
final float[] triangle={
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
final float[] colors = {1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1
};
final float[] colorsTr = {1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1,
1,1,1
};
squareVert = ByteBuffer.allocateDirect(square.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
squareVert.put(square).position(0);
indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indeces).position(0);
mColor = ByteBuffer.allocateDirect(colors.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mColor.put(colors).position(0);
triangleVert = ByteBuffer.allocateDirect(square.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
triangleVert.put(triangle).position(0);
indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indeces).position(0);
tColor = ByteBuffer.allocateDirect(colors.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
tColor.put(colorsTr).position(0);
}
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5, 0, 0, 0, 0, 1, 0);
final String vertexShader =
"uniform mat4 un_MVPMatrix; \n"
+ "attribute vec4 attribute_Position; \n"
+ "attribute vec4 attribute_Color; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " var_Color = attribute_Color; \n"
+ " gl_Position = un_MVPMatrix \n"
+ " * attribute_Position; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+
" gl_FragColor = (length(gl_FragCoord.xy) < 0.5 ) \n" +
" ? vec4(1.0, 1.0, 1.0, 1.0)\n" +
" : vec4(0.5, 0.5, 0.5, 0.5); \n"
+ "} \n";
int vertexS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexS != 0)
{
GLES20.glShaderSource(vertexS, vertexShader);
GLES20.glCompileShader(vertexS);
final int[] compile_Status = new int[1];
GLES20.glGetShaderiv(vertexS, GLES20.GL_COMPILE_STATUS, compile_Status, 0);
}
if (vertexS == 0)
{
try {
throw new Exception("Vertex shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int fragmentS = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentS != 0)
{
GLES20.glShaderSource(fragmentS, fragmentShader);
GLES20.glCompileShader(fragmentS);
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentS, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
}
if (fragmentS == 0)
{
try {
throw new Exception("Fragment shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int program = GLES20.glCreateProgram();
if (program != 0)
{
GLES20.glAttachShader(program, vertexS);
GLES20.glAttachShader(program, fragmentS);
GLES20.glBindAttribLocation(program, 0, "attribute_Position");
GLES20.glBindAttribLocation(program, 1, "attribute_Color");
GLES20.glLinkProgram(program);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
}
if (program == 0)
{
try {
throw new Exception("Program error");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "un_MVPMatrix");
positionHandle = GLES20.glGetAttribLocation(program, "attribute_Position");
colorHandle = GLES20.glGetAttribLocation(program, "attribute_Color");
GLES20.glUseProgram(program);
}
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
GLES20.glViewport(0, 0, width, height);
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
if (i > 1) {
smer = -1;
}
if (i < -1) {
smer = 1;
}
i += 0.05 * smer;
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0, i, 0.0f);
drawSqare(squareVert, indexBuffer);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix,0, -1.5f, 0.0f, 0.0f);
drawSTriangle(triangleVert, indexBuffer);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, -1.0f, 0.0f, -0.0f);
drawSTriangle(triangleVert, indexBuffer);
GLES20.glDisable(GLES20.GL_BLEND);
}
private void drawSqare(final FloatBuffer aTriangleBuffer,ShortBuffer sb)
{
aTriangleBuffer.position(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
mColor.position(0);
GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT, false, 0, mColor);
GLES20.glEnableVertexAttribArray(colorHandle);
Matrix.multiplyMM(mVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, mVPMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indeces.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
private void drawSTriangle(final FloatBuffer fbb,ShortBuffer sbb)
{
fbb.position(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, fbb);
GLES20.glEnableVertexAttribArray(positionHandle);
tColor.position(0);
GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT, false,
0, tColor);
GLES20.glEnableVertexAttribArray(colorHandle);
Matrix.multiplyMM(mVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, mVPMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indeces.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
}
You can follow the Documentation provided by Android for OpenGL
Check this for adding Rotation or motion to view.
here is the sample from Android http://developer.android.com/shareables/training/OpenGLES.zip
Related
If i change the background of GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f) and then try to draw a texture, colors of this last changes unexpectedly. This is the png file:
The result of the application when i try simply to display it is this one:
Im using this code:
public class GLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "MyGLRenderer";
private float[] vertices = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
private float[] textureVertices = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
private final String vertexShaderCode =
"attribute vec4 aPosition;" +
"attribute vec2 aTexPosition;" +
"varying vec2 vTexPosition;" +
"void main() {" +
" gl_Position = aPosition;" +
" vTexPosition = aTexPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"varying vec2 vTexPosition;" +
"void main() {\n" +
"vec4 color = texture2D(uTexture, vTexPosition);\n"+
//"if(color.r == 0.0 && color.g == 0.0 && color.b == 0.0)\n"+
// "color = vec4(1.0,0.5,0.5,1.0);"+
// "discard;"+
" gl_FragColor = color;" +
"}";
private FloatBuffer verticesBuffer;
private FloatBuffer textureBuffer;
private int vertexShader;
private int fragmentShader;
private int program;
private Bitmap bmp;
private int textures[] = new int[2];
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
public GLRenderer() {
bmp=Bitmap.createBitmap(513,912, Bitmap.Config.ARGB_8888);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
checkGlError("glClearColor");
setup();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
#Override
public void onDrawFrame(GL10 gl) {
Log.d("Drawing_Frame","Working");
float[] scratch = new float[16];
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw Bitmap
drawBinaryImage(bmp,textures[0]);
Matrix.setRotateM(mRotationMatrix, 0, 0, 0, 0, 1.0f);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
}
private void setup(){
GLES20.glGenTextures(2, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
//GLES20.glBindTexture(GL);
initializeBuffers();
initializeProgram();
}
private void initializeBuffers() {
ByteBuffer buff = ByteBuffer.allocateDirect(vertices.length * 4);
buff.order(ByteOrder.nativeOrder());
verticesBuffer = buff.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
buff = ByteBuffer.allocateDirect(textureVertices.length * 4);
buff.order(ByteOrder.nativeOrder());
textureBuffer = buff.asFloatBuffer();
textureBuffer.put(textureVertices);
textureBuffer.position(0);
}
private void initializeProgram() {
vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glGetShaderInfoLog(vertexShader);
checkGlError("glCreateShader");
GLES20.glShaderSource(vertexShader, vertexShaderCode);
GLES20.glCompileShader(vertexShader);
fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
checkGlError("glLinkProgram");
}
public void updateTexture(Bitmap bmp){
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
}
private void drawBinaryImage(Bitmap bmp,int texture){
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(program);
//Changes Here original Line GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
int positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
int textureHandle = GLES20.glGetUniformLocation(program, "uTexture");
int texturePositionHandle = GLES20.glGetAttribLocation(program, "aTexPosition");
//Log.d("GL_SETUP",positionHandle+" , "+textureHandle);
GLES20.glVertexAttribPointer(texturePositionHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(texturePositionHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
Log.d("FILTER_APPLY","Applying");
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glUniform1i(textureHandle, 0);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, verticesBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
}
public void setBitmap(Bitmap bitmap){
updateTexture(bitmap);
this.bmp = bitmap;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
The framebuffer is cleared by GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);.
RGBA(1, 1, 0, 1) is yellow. This causes that before rendering the texture, the entire framebuffer is filled in yellow.
The texture contains a blue color RGBA(0, 0, 1, 1) and a black color RGBA(0, 0, 0, 1).
When the quad with the texture is drawn, then blending is enabled with the following function:
(see Blending and glBlendFunc)
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
At blending the current color of the framebuffer is mixed by the actually drawn color. With the above setup this done by the following function:
destinationColor = sourceColor * 1 + destinationColor * 1
In the regions where the texture is blue, the final color becomes white:
(1, 1, 0) * 1 + (0, 0, 1) * 1 = (1, 1, 1)
In the regions where the texture is black, the color in the framebuffer stays yellow:
(1, 1, 0) * 1 + (0, 0, 0) * 1 = (1, 1, 0)
I need to draw a shape in OpenGL from a binary image. For example, I have this image binary
and I need to draw this shape in OpenGL. The fact is that I need to do this "dynamically" so I will have for example a different binary image every second and I need to draw the shapes from every one of those images. Shapes will not be the only triangles like in the example image. I will use this in Android Studio.
Convert this image to Bitmap object and draw it on the GLSurfaceView. you can check condition in shader code like this.
vec4 color = texture2D(uTexture, vTexPosition);
if(color.r == 0.0 && color.g == 0.0 && color.b == 0.0)
color = vec4(1.0,0.5,0.5,1.0);
gl_FragColor = color;
This is the full GLRenderer
public class GLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "MyGLRenderer";
private float[] vertices = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
private float[] textureVertices = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
private final String vertexShaderCode =
"attribute vec4 aPosition;" +
"attribute vec2 aTexPosition;" +
"varying vec2 vTexPosition;" +
"void main() {" +
" gl_Position = aPosition;" +
" vTexPosition = aTexPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D uTexture;" +
"varying vec2 vTexPosition;" +
"void main() {\n" +
"vec4 color = texture2D(uTexture, vTexPosition);\n"+
"if(color.r == 0.0 && color.g == 0.0 && color.b == 0.0)\n"+
"color = vec4(1.0,0.5,0.5,1.0);"+
" gl_FragColor = color;" +
"}";
private FloatBuffer verticesBuffer;
private FloatBuffer textureBuffer;
private int vertexShader;
private int fragmentShader;
private int program;
private Bitmap bmp;
private int textures[] = new int[2];
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
public GLRenderer() {
bmp=Bitmap.createBitmap(513,912, Bitmap.Config.ARGB_8888);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
checkGlError("glClearColor");
setup();
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
#Override
public void onDrawFrame(GL10 gl) {
Log.d("Drawing_Frame","Working");
float[] scratch = new float[16];
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw Bitmap
drawBinaryImage(bmp,textures[0]);
Matrix.setRotateM(mRotationMatrix, 0, 0, 0, 0, 1.0f);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
}
private void setup(){
GLES20.glGenTextures(2, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
//GLES20.glBindTexture(GL);
initializeBuffers();
initializeProgram();
}
private void initializeBuffers() {
ByteBuffer buff = ByteBuffer.allocateDirect(vertices.length * 4);
buff.order(ByteOrder.nativeOrder());
verticesBuffer = buff.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
buff = ByteBuffer.allocateDirect(textureVertices.length * 4);
buff.order(ByteOrder.nativeOrder());
textureBuffer = buff.asFloatBuffer();
textureBuffer.put(textureVertices);
textureBuffer.position(0);
}
private void initializeProgram() {
vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glGetShaderInfoLog(vertexShader);
checkGlError("glCreateShader");
GLES20.glShaderSource(vertexShader, vertexShaderCode);
GLES20.glCompileShader(vertexShader);
fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
checkGlError("glLinkProgram");
}
public void updateTexture(Bitmap bmp){
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
}
private void drawBinaryImage(Bitmap bmp,int texture){
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(program);
//Changes Here original Line GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
int positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
int textureHandle = GLES20.glGetUniformLocation(program, "uTexture");
int texturePositionHandle = GLES20.glGetAttribLocation(program, "aTexPosition");
//Log.d("GL_SETUP",positionHandle+" , "+textureHandle);
GLES20.glVertexAttribPointer(texturePositionHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(texturePositionHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
Log.d("FILTER_APPLY","Applying");
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glUniform1i(textureHandle, 0);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, verticesBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
}
public void setBitmap(Bitmap bitmap){
updateTexture(bitmap);
this.bmp = bitmap;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
}
Use this renderer with GlSurfaceView
Here is main Activity class
public class MainActivity extends AppCompatActivity {
FrameLayout glView;
private GLRenderer renderer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
glView = findViewById(R.id.glview);
setupGL();
}
private void setupGL(){
renderer = new GLRenderer();
//MyGlSurfaceView glSurfaceView = new MyGlSurfaceView(this,renderer);
GLSurfaceView glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setEGLContextClientVersion(2);
glSurfaceView.setRenderer(renderer);
glView.addView(glSurfaceView);
produceFrame();
}
private void produceFrame(){
Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.sample);
renderer.setBitmap(bmp);
}
You can check this for complete project.
I'm quite new to Android OpenGL so I'm trying to write a simple animation app using a tutorial that I've found in a course.
I think it's a quite simple code but the app crashes with a "Unfortunately MovingSquare1 app has crashed".
I could not find any crash in the Logcat, at least to a normal crash sequence of lines in red.
After some debugging, I've found out that the application crashes when the line "int vertexS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);" is executed. I've thought about a Context issue, but I've seen that the "con" variable at the beginning of OGLRenderer is unused.
Can anybody give me a hint?
Thanks for your time, guys.
This is the main activity:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView glsv = new GLSurfaceView(this);
glsv.setRenderer(new OGLRenderer());
setContentView(glsv);
}
}
This is the OGLRenderer class:
public class OGLRenderer implements GLSurfaceView.Renderer {
// Context con;
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] projectionMatrix = new float[16];
private float[] mVPMatrix = new float[16];
private final FloatBuffer squareVert;
private final FloatBuffer mColor;
private int mvpMatrixHandle;
private int positionHandle;
private int colorHandle;
private final int mBytesPerFloat = 4;
ShortBuffer indexBuffer = null;
short[] indeces = {
0, 1, 2,
0, 3, 2
};
float i;
public int sens;
public OGLRenderer() {
i = 0;
sens = 1;
final float[] square = {
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
final float[] colors = {1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0,
1, 0, 0
};
// Initialize the buffers.
squareVert = ByteBuffer.allocateDirect(square.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
squareVert.put(square).position(0);
indexBuffer = ByteBuffer.allocateDirect(indeces.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indeces).position(0);
mColor = ByteBuffer.allocateDirect(colors.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mColor.put(colors).position(0);
}
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -5, 0, 0, 0, 0, 1, 0);
final String vertexShader =
"uniform mat4 un_MVPMatrix; \n"
+ "attribute vec4 attribute_Position; \n"
+ "attribute vec4 attribute_Color; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " var_Color = attribute_Color; \n"
+ " gl_Position = un_MVPMatrix \n"
+ " * attribute_Position; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "varying vec4 var_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = var_Color; \n"
+ "} \n";
int vertexS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexS != 0) {
GLES20.glShaderSource(vertexS, vertexShader);
GLES20.glCompileShader(vertexS);
final int[] compile_Status = new int[1];
GLES20.glGetShaderiv(vertexS, GLES20.GL_COMPILE_STATUS, compile_Status, 0);
}
{
try {
throw new Exception("Vertex shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int fragmentS = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentS != 0) {
GLES20.glShaderSource(fragmentS, fragmentShader);
GLES20.glCompileShader(fragmentS);
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentS, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
}
if (fragmentS == 0) {
try {
throw new Exception("Fragment shader is not created.");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexS);
GLES20.glAttachShader(program, fragmentS);
GLES20.glBindAttribLocation(program, 0, "attribute_Position");
GLES20.glBindAttribLocation(program, 1, "attribute_Color");
GLES20.glLinkProgram(program);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
}
if (program == 0) {
try {
throw new Exception("Program error");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "un_MVPMatrix");
positionHandle = GLES20.glGetAttribLocation(program, "attribute_Position");
colorHandle = GLES20.glGetAttribLocation(program, "attribute_Color");
GLES20.glUseProgram(program);
}
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
if (i > 1) {
sens = -1;
}
if (i < -1) {
sens = 1;
}
i += 0.05 * sens;
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, i, 0.0f, 0.0f);
drawTriangle(squareVert, indexBuffer);
}
private void drawTriangle(final FloatBuffer aTriangleBuffer, ShortBuffer sb) {
int a = Float.SIZE;
aTriangleBuffer.position(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
mColor.position(0);
GLES20.glVertexAttribPointer(colorHandle, 3, GLES20.GL_FLOAT, false, 0, mColor);
GLES20.glEnableVertexAttribArray(colorHandle);
Matrix.multiplyMM(mVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, mVPMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indeces.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
}
Thanks to all the people who took a look at this.
As I suspected, it was a context issue, the solution is to create a class that extends GLSurfaceView and put into the constructor this line:
setEGLContextClientVersion(2);
Thanks.
Simply trying to decode frames from videos.
While working with Android 4+ (<5), it worked just fine.
I'm using parts of the example that can be found here:
http://bigflake.com/mediacodec/
"ExtractMpegFramesTest.java (requires 4.1, API 16)"
The problem is - it extracts a frame, but the result Bitmap is as can be seen here (Saved an image right after decoding it):
The real video of course has "real" frames, and not "stretched" 1 column.
I've saved this image right after the code line:
bmp.copyPixelsFromBuffer(mPixelBuf);
// <-- here I saved the above image
Is there some major update (I can't find) to the decoder that solves this ?
On API level 21 and above the decoder applies the rotation when rendering to the surface. Therefore, the transformMatrix you got from SurfaceTexture contains the rotation info, which means the way use to invert the SurfaceTexture in the example doesn't work. To correctly invert the texture, I rotation it by z axis and do x, y axis transform. Following are what I do :
chnage
st.getTransformMatrix(mSTMatrix);
if (invert) {
mSTMatrix[5] = -mSTMatrix[5];
mSTMatrix[13] = 1.0f - mSTMatrix[13];
}
to
st.getTransformMatrix(mMatrix);
if(invert){
Matrix.setIdentityM(identifyMatrix, 0);
Matrix.translateM(identifyMatrix, 0, 1, 1, 0);
Matrix.rotateM(identifyMatrix, 0, 180, 0, 0, 1);
Matrix.multiplyMM(mSTMatrix, 0, identifyMatrix, 0, mMatrix,0);
}
where mMatrix and identifyMatrix are both
new float[16];
yst's answer creates a mirrored image
st.getTransformMatrix(mIntermediateMatrix);
if(invert){
Matrix.setIdentityM(identityMatrix, 0);
Matrix.translateM(identityMatrix, 0, 1, 1, 0);
Matrix.rotateM(identityMatrix, 0, 180, 0, 0, 1);
//fixes mirror image
Matrix.translateM(identityMatrix, 0, 0, 1, 0);
Matrix.rotateM(identityMatrix, 0, 180, 1, 0, 0);
Matrix.multiplyMM(mSTMatrix, 0, identityMatrix, 0,mIntermediateMatrix,0);
} else {
identityMatrix = mIntermediateMatrix;
}
This is my slightly altered STextureRender class from bigflake's ExtractMpegFramesTest.java (requires 4.2, API 17)
/**
* Code for rendering a texture onto a surface using OpenGL ES 2.0.
*/
private static class STextureRender {
private static final int FLOAT_SIZE_BYTES = 4;
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
private final float[] mTriangleVerticesData = {
// X, Y, Z, U, V
-1.0f, -1.0f, 0, 0.f, 0.f,
1.0f, -1.0f, 0, 1.f, 0.f,
-1.0f, 1.0f, 0, 0.f, 1.f,
1.0f, 1.0f, 0, 1.f, 1.f,
};
private FloatBuffer mTriangleVertices;
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
"}\n";
private static final String FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" + // highp here doesn't seem to matter
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
private float[] mMVPMatrix = new float[16];
private float[] mSTMatrix = new float[16];
private float[] identityMatrix = new float[16];
private float[] mIntermediateMatrix = new float[16];
private int mProgram;
private int mTextureID = -12345;
private int muMVPMatrixHandle;
private int muSTMatrixHandle;
private int maPositionHandle;
private int maTextureHandle;
public STextureRender() {
mTriangleVertices = ByteBuffer.allocateDirect(
mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleVertices.put(mTriangleVerticesData).position(0);
Matrix.setIdentityM(mSTMatrix, 0);
}
public int getTextureId() {
return mTextureID;
}
/**
* Draws the external texture in SurfaceTexture onto the current EGL surface.
*/
public void drawFrame(SurfaceTexture st, boolean invert) {
checkGlError("onDrawFrame start");
st.getTransformMatrix(mIntermediateMatrix);
if(invert){
Matrix.setIdentityM(identityMatrix, 0);
Matrix.translateM(identityMatrix, 0, 1, 1, 0);
Matrix.rotateM(identityMatrix, 0, 180, 0, 0, 1);
//fixes mirror image
Matrix.translateM(identityMatrix, 0, 0, 1, 0);
Matrix.rotateM(identityMatrix, 0, 180, 1, 0, 0);
Matrix.multiplyMM(mSTMatrix, 0, identityMatrix, 0, mIntermediateMatrix,0);
} else {
mSTMatrix = mIntermediateMatrix;
}
/*
if (invert) {
mSTMatrix[5] = -mSTMatrix[5];
mSTMatrix[13] = 1.0f - mSTMatrix[13];
}
*/
// (optional) clear to green so we can see if we're failing to set pixels
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
}
/**
* Initializes GL state. Call this after the EGL surface has been created and made current.
*/
public void surfaceCreated() {
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (mProgram == 0) {
throw new RuntimeException("failed creating program");
}
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
checkLocation(maPositionHandle, "aPosition");
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
checkLocation(maTextureHandle, "aTextureCoord");
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
checkLocation(muMVPMatrixHandle, "uMVPMatrix");
muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
checkLocation(muSTMatrixHandle, "uSTMatrix");
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
mTextureID = textures[0];
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
checkGlError("glBindTexture mTextureID");
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
checkGlError("glTexParameter");
}
/**
* Replaces the fragment shader. Pass in null to reset to default.
*/
public void changeFragmentShader(String fragmentShader) {
if (fragmentShader == null) {
fragmentShader = FRAGMENT_SHADER;
}
GLES20.glDeleteProgram(mProgram);
mProgram = createProgram(VERTEX_SHADER, fragmentShader);
if (mProgram == 0) {
throw new RuntimeException("failed creating program");
}
}
private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
checkGlError("glCreateShader type=" + shaderType);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
return shader;
}
private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GLES20.glCreateProgram();
if (program == 0) {
Log.e(TAG, "Could not create program");
}
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
return program;
}
public void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}
public static void checkLocation(int location, String label) {
if (location < 0) {
throw new RuntimeException("Unable to locate '" + label + "' in program");
}
}
}
I am trying to learn OpenGLES 2.0 in android in depth. I am trying to draw a Simple Point at the center of screen but somehow , the point is not showing .
public class MyRenderer implements GLSurfaceView.Renderer {
Context context;
private int mProgram;
private final float[] mViewMatrix=new float[16];
private float[] mProjectionMatrix=new float[16];
private final float[] mPointModelMatrix=new float[16];
private final float[] mMVPMatrix=new float[16];
private final float[] mPointPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
private final float[] mPointPosInWorldSpace = new float[4];
private final float[] mPointPosInEyeSpace = new float[4];
private int pointMVPMatrixHandle;
private int pointPositionHandle;
public MyRenderer(Context context){
this.context=context;
}
public void onDrawFrame(GL10 arg0) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mPointModelMatrix, 0);
Matrix.translateM(mPointModelMatrix, 0, 0.0f, 0.0f, -3.0f);
Matrix.multiplyMV(mPointPosInWorldSpace, 0, mPointModelMatrix, 0, mPointPosInModelSpace, 0);
Matrix.multiplyMV(mPointPosInEyeSpace, 0, mViewMatrix, 0, mPointPosInWorldSpace, 0);
GLES20.glUseProgram(mProgram);
drawPoint();
}
private void drawPoint(){
pointMVPMatrixHandle=GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");
pointPositionHandle=GLES20.glGetAttribLocation(mProgram, "a_position");
GLES20.glVertexAttrib3f(pointPositionHandle, mPointPosInEyeSpace[0], mPointPosInEyeSpace[1], mPointPosInEyeSpace[2]);
GLES20.glDisableVertexAttribArray(pointPositionHandle);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mPointModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the point.
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
GLES20.glViewport(0, 0, width, height);
final float ratio=(float)width/height;
Log.d("Ratio is", " "+ratio);
Log.d("Width is"," "+width+" and "+height);
final float left = -ratio;
final float right = ratio;
final float bottom= -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=-0.5f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader=this.getVertexShader();
final String fragmentShader=this.getFragmentShader();
final int vertexShaderHandle=ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
final int fragmentShaderHandle=ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
mProgram=ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[]{"a_position"});
}
private String getVertexShader(){
final String vertexShader="uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
return vertexShader;
}
private String getFragmentShader(){
final String fragmentShader="precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
return fragmentShader;
}
}
I am pretty much sure that I am pointing the both eye and point in negative Z direction(further from viewer) . The point should show up as in vertex Shader, point size is 10.0 but somehow, no luck.
Note: ShaderHelper is a class with static method compileShader and createAndLinkProgram where code for compiling shaders, checking for errors are written. (No Errors in Program)
Here is a class I built based around your code for displaying the point. Since you will probably use more than one point eventually it is better to push the points into a vertex array as shown.
package point.example.point;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class PointRenderer implements GLSurfaceView.Renderer
{
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
private int mMVPMatrixHandle;
private int mPositionHandle;
float[] vertices = {
0.0f,0.0f,0.0f
};
FloatBuffer vertexBuf;
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
// Set the background clear color to gray.
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
float eyeX=0.0f;
float eyeY=0.0f;
float eyeZ=0.0f;
float centerX=0.0f;
float centerY=0.0f;
float centerZ=-5.0f;
float upX=0.0f;
float upY=1.0f;
float upZ=0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_MVPMatrix \n"
+ " * a_Position; \n"
+ " gl_PointSize = 10.0; \n"
+ "} \n";
final String fragmentShader =
"precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(1.0, \n"
+ " 1.0, 1.0, 1.0); \n"
+ "} \n";
// Load in the vertex shader.
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0)
{
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the fragment shader shader.
int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0)
{
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0)
{
throw new RuntimeException("Error creating fragment shader.");
}
// Create a program object and store the handle to it.
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0)
{
// Bind the vertex shader to the program.
GLES20.glAttachShader(programHandle, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
// Bind attributes
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
// Link the two shaders together into a program.
GLES20.glLinkProgram(programHandle);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0)
{
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0)
{
throw new RuntimeException("Error creating program.");
}
// Set program handles. These will later be used to pass in values to the program.
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(programHandle);
}
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 100.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 glUnused)
{
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setIdentityM(mModelMatrix, 0);
//Push to the distance - note this will have no effect on a point size
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
Matrix.multiplyMV(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMV(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
//Send the vertex
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuf);
GLES20.glEnableVertexAttribArray(mPositionHandle);
//Draw the point
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
}
}