OpenGL ES Object is Displaying Strangely / Distorted - Android - java
EDIT OK - I grabbed a device and..guess what...it displays correctly ? Does anyone know why this would be happening on the simulator only ? Thank you.
I am trying to draw an object using glDrawElements on Android. I am using the code below to read in my vertice and indice data and then draw the object in my render method. I am testing this on the simulator rather than a real device.
This is my scene object code :
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class SceneObject {
public FloatBuffer mVertexBuffer;
public FloatBuffer mTextureBuffer;
public ShortBuffer indexBuffer;
public FloatBuffer mMatriceBuffer;
public FloatBuffer mPivotBuffer;
public short[] indicesTest = {0,1,2,3,4,5,3,5,6,7,5,8,7,8,9,10,7,9,11,10,9,12,1,0,13,12,14,15,13,14,14,10,11,15,14,11,0,14,12,16,17,18,19,16,18,18,20,19,21,16,19,22,21,19,22,19,23,4,24,25,25,26,27,25,27,28,4,25,28,5,4,28,5,28,8,29,30,31,29,31,19,29,19,20,32,33,31,32,31,30,32,34,33,35,22,23,36,35,23,37,36,23,37,23,38,39,37,38,40,39,38,41,40,38,41,38,1,42,41,1,12,43,1,42,1,43,17,27,26,26,18,17,44,45,46,46,47,44,48,49,50,51,52,53,53,54,51,55,51,54,54,56,55,57,48,50,50,58,57,52,59,60,60,53,52,59,44,47,47,60,59,61,62,63,63,64,61,65,66,67,67,68,65,69,70,71,71,72,69,66,69,72,72,67,66,73,65,68,68,74,73,70,75,76,76,71,70,75,61,64,64,76,75,77,78,79,79,80,77,81,82,62,62,61,81,83,81,61,61,75,83,84,63,62,62,82,84,63,84,85,86,87,88,89,90,91,92,93,87,87,86,92,94,95,96,96,97,94,98,99,100,100,101,98,102,103,104,104,105,102,106,107,108,108,109,106,110,111,112,78,77,113,114,115,78,112,111,116,117,118,115,119,116,120,121,122,123,123,124,121,125,126,127,127,128,125,129,130,131,132,133,5,5,133,6,5,134,135,135,134,136,134,137,136,137,138,136,129,139,130,139,140,141,140,142,141,137,141,138,141,142,138,141,130,139,143,144,145,144,146,145,147,145,146,144,148,146,148,149,146,146,149,150,151,132,152,153,152,154,154,152,155,152,132,155,132,5,155,155,5,135,156,157,158,158,157,146,146,157,147,159,160,158,158,160,156,34,160,159,149,161,150,161,162,150,162,163,150,150,163,164,163,165,164,165,166,164,166,167,164,164,167,129,167,168,129,169,139,129,129,168,169,154,143,153,145,153,143,170,171,172,173,172,171,174,175,176,177,178,179,180,179,178,178,181,180,182,180,181,175,183,176,184,176,183,185,177,186,179,186,177,171,185,173,186,173,185,187,188,189,190,189,188,191,192,193,194,193,192,195,196,197,198,197,196,196,191,198,193,198,191,192,199,194,200,194,199,201,195,202,197,202,195,188,201,190,202,190,201,203,204,205,206,205,204,207,208,187,188,187,208,208,209,188,201,188,209,189,210,187,207,187,210,210,189,211,212,213,214,215,216,217,218,219,220,221,220,219,222,223,224,225,226,227,228,229,230,231,230,229,232,233,234,235,236,237,238,239,240,241,242,243,123,244,124,245,246,203,204,203,246,247,248,203,249,250,251,252,253,247,248,247,253,159,33,34,254,255,256,256,257,254,255,244,123,123,256,255,244,258,121,121,124,244,259,260,125,125,128,259};
public float[] verticeTest = {20360.8f,20679.5f,611.547f,24248.7f,13527f,1074.93f,24207.4f,23005.5f,1503.19f,9819.59f,14845.7f,8.81875f,11126.3f,13982.2f,32.0718f,8379.01f,17678.5f,0.00115749f,8379.01f,15141.6f,0.00111471f,12137.8f,17973.8f,60.0461f,14591.9f,14509.2f,164.113f,15621.5f,15846.6f,223.075f,15136.7f,18549.5f,194.186f,16918.2f,16705.3f,310.215f,21081.8f,15846.6f,687.576f,19789f,16705.3f,554.435f,18467.9f,19868.7f,433.258f,18354.3f,17001.2f,423.539f,14591.9f,7402.34f,164.113f,13930.5f,9087.62f,131.015f,13039.7f,9096.18f,92.3283f,19110.4f,-8011.43f,490.311f,12811.7f,7228.03f,83.5128f,15621.5f,6064.9f,223.074f,16918.2f,5206.21f,310.215f,21807.5f,-426.492f,768.658f,11221.5f,13854f,34.3347f,12150f,12649.6f,60.4329f,12811.7f,10964.3f,83.513f,13702.6f,10955.8f,120.472f,13930.5f,12823.9f,131.015f,12150f,5542.76f,60.4327f,11119f,4205.31f,31.902f,15341.7f,-15792.9f,206.155f,9819.59f,3346.62f,8.81857f,10735.6f,-21752.5f,23.5976f,8379.01f,3050.73f,0.000981022f,18354.3f,4910.32f,423.538f,19789f,5206.21f,554.434f,21081.8f,6064.9f,687.576f,23336.1f,6399.27f,954.364f,22106.6f,7402.34f,803.393f,22764f,9087.62f,882.485f,22990.5f,10955.8f,910.595f,22764f,12823.9f,882.485f,22106.6f,14509.2f,803.393f,24248.7f,8492.36f,-3249.03f,24207.4f,17415.3f,-3297.97f,24207.4f,23005.5f,1503.19f,24248.7f,13527f,1074.93f,12728.3f,-24463.4f,-4243.56f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,19110.4f,-13046f,-3833.65f,21807.5f,-5461.09f,-3555.3f,21807.5f,-426.492f,768.658f,19110.4f,-8011.43f,490.311f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,23336.1f,1364.68f,-3369.59f,23336.1f,6399.27f,954.364f,24883.8f,8123.11f,-2819.08f,24859.5f,16025.8f,-2803.12f,24207.4f,17415.3f,-3297.97f,24248.7f,8492.36f,-3249.03f,13363.4f,-24832.7f,-3813.62f,15976.8f,-21196.8f,-3687.86f,15341.7f,-20827.5f,-4117.81f,12728.3f,-24463.4f,-4243.56f,19745.5f,-13415.3f,-3403.7f,22442.7f,-5830.35f,-3125.36f,21807.5f,-5461.09f,-3555.3f,19110.4f,-13046f,-3833.65f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,23222.6f,-2518.03f,-3057.67f,23336.1f,1364.68f,-3369.59f,10301.8f,-40240.8f,-15469.8f,10482f,-40907.1f,-14694f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,25648.8f,8121.58f,-2817.31f,25624.5f,16024.2f,-2801.34f,24056.1f,-2550.94f,-3019.36f,25678.7f,16560.2f,-2907.29f,25594.2f,17951.2f,-3237.71f,25624.5f,-88046.9f,-92182.7f,25678.7f,-87767f,-92508.6f,25678.7f,16560.2f,-2907.29f,25678.7f,16560.2f,-2907.29f,25624.5f,16024.2f,-2801.34f,25624.5f,-88046.9f,-92182.7f,25624.5f,-88413.1f,-92497.2f,25678.7f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,24820f,-88133.2f,-92823.1f,25678.7f,-88133.2f,-92823.1f,25624.5f,-88413.1f,-92497.2f,24765.7f,-89895.8f,-93770.7f,24820f,-89615.9f,-94096.6f,24820f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,25678.7f,-89596.5f,-94079.9f,25678.7f,-88133.2f,-92823.1f,24820f,-88133.2f,-92823.1f,24820f,-89615.9f,-94096.6f,23222.6f,-93458.9f,-81162.2f,24056.1f,-93491.8f,-81123.9f,24056.1f,-2550.94f,-3019.36f,23222.6f,-2518.03f,-3057.67f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-40907.1f,-14694f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-41291.8f,-14246f,10579f,-102925f,-68042.7f,10489f,-103571f,-67018.6f,10482f,-41713.9f,-13886.7f,10482f,-41291.8f,-14246f,10489f,-103571f,-67018.6f,8379.01f,-102145f,-69021.7f,10579.6f,-102089f,-68973.2f,10301.8f,-40240.8f,-15469.8f,8379.01f,-68082.6f,-39554.7f,8379.01f,-101057f,-70411.1f,10735.6f,-101057f,-70411.1f,10579.6f,-102089f,-68973.2f,8379.01f,-102145f,-69021.7f,-7490.7f,13527f,1074.93f,-3602.79f,20679.5f,611.547f,-7449.35f,23005.5f,1503.19f,5631.77f,13982.2f,32.0718f,6938.43f,14845.7f,8.81875f,4620.19f,17973.8f,60.0461f,2166.16f,14509.2f,164.113f,1136.48f,15846.6f,223.075f,1621.29f,18549.5f,194.186f,-160.178f,16705.3f,310.215f,-4323.73f,15846.6f,687.576f,-3030.97f,16705.3f,554.435f,-1709.92f,19868.7f,433.258f,-1596.32f,17001.2f,423.539f,2827.51f,9087.62f,131.015f,2166.16f,7402.34f,164.113f,3718.3f,9096.18f,92.3283f,-2352.36f,-8011.43f,490.311f,3946.3f,7228.03f,83.5128f,1136.48f,6064.9f,223.074f,-160.182f,5206.21f,310.215f,-5049.53f,-426.492f,768.658f,5536.51f,13854f,34.3347f,4608.07f,12649.6f,60.4329f,3946.3f,10964.3f,83.513f,3055.44f,10955.8f,120.472f,2827.51f,12823.9f,131.015f,5639.04f,4205.31f,31.902f,4608.07f,5542.76f,60.4327f,1416.3f,-15792.9f,206.155f,6022.45f,-21752.5f,23.5976f,6938.43f,3346.62f,8.81857f,-1596.32f,4910.32f,423.538f,-3030.97f,5206.21f,554.434f,-4323.73f,6064.9f,687.576f,-6578.08f,6399.27f,954.364f,-5348.56f,7402.34f,803.393f,-6006f,9087.62f,882.485f,-6232.44f,10955.8f,910.595f,-6006f,12823.9f,882.485f,-5348.57f,14509.2f,803.393f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,-7449.35f,23005.5f,1503.19f,-7490.7f,13527f,1074.93f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,1416.3f,-15792.9f,206.155f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,-5049.53f,-426.492f,768.658f,-2352.36f,-8011.43f,490.311f,1416.3f,-20827.5f,-4117.81f,1416.3f,-15792.9f,206.155f,6022.45f,-26787.1f,-4300.36f,6022.45f,-21752.5f,23.5976f,-6578.08f,1364.68f,-3369.59f,-6578.08f,6399.27f,954.364f,-8101.47f,16025.8f,-2803.12f,-8125.81f,8123.11f,-2819.08f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,781.19f,-21196.8f,-3687.86f,3394.66f,-24832.7f,-3813.62f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,-5684.64f,-5830.35f,-3125.36f,-2987.47f,-13415.3f,-3403.7f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-6464.54f,-2518.03f,-3057.67f,-6578.08f,1364.68f,-3369.59f,6276.06f,-40907.1f,-14694f,6456.25f,-40240.8f,-15469.8f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-8866.45f,16024.2f,-2801.34f,-8890.79f,8121.58f,-2817.31f,-7298.12f,-2550.94f,-3019.36f,-8920.72f,16560.2f,-2907.29f,-8836.13f,17951.2f,-3237.71f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,16560.2f,-2907.29f,-8866.45f,16024.2f,-2801.34f,-8920.72f,16560.2f,-2907.29f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8061.98f,-89615.9f,-94096.6f,-8007.72f,-89895.8f,-93770.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-8061.98f,-88133.2f,-92823.1f,-8061.98f,-89615.9f,-94096.6f,-8061.98f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-7298.12f,-93491.8f,-81123.9f,-6464.54f,-93458.9f,-81162.2f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-2518.03f,-3057.67f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-93458.9f,-81162.2f,6456.25f,-40240.8f,-15469.8f,6179.01f,-102925f,-68042.7f,6178.41f,-102089f,-68973.2f,6276.06f,-41291.8f,-14246f,6179.01f,-102925f,-68042.7f,6179.01f,-102925f,-68042.7f,6276.06f,-40907.1f,-14694f,6179.01f,-102925f,-68042.7f,6276.06f,-41713.9f,-13886.7f,6269.01f,-103571f,-67018.6f,6022.45f,-21752.5f,23.5976f,6022.45f,-26787.1f,-4300.36f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,6178.41f,-102089f,-68973.2f,6178.41f,-102089f,-68973.2f,6022.45f,-101057f,-70411.1f
};
public String objectName;
public int triangleCount;
public int verticeCount;
public float[] vertices;
public float[] normals;
public float[] textures;
public short[] indices;
public float[] matrices;
public float[] pivots;
public float[] animations;
public void awake() {
ByteBuffer vbb = ByteBuffer.allocateDirect(verticeTest.length * 4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(verticeTest);
mVertexBuffer.position(0);
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length * 4);
tbb.order(ByteOrder.nativeOrder());
mTextureBuffer = tbb.asFloatBuffer();
mTextureBuffer.put(textures);
mTextureBuffer.position(0);
//short has 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(indicesTest.length*2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indicesTest);
indexBuffer.position(0);
verticeCount = (triangleCount*3);
}
public void draw(GL10 gl) {
System.out.println("Draw Method Called in Object");
gl.glEnable(GL10.GL_TEXTURE_2D); //workaround bug 3623
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
System.out.println("Triangle Vertice Count is "+verticeCount);
int x = vertices.length;
System.out.println("Rendering following number of vertices "+x);
int y = indices.length;
System.out.println("Rendering following number of indices "+y);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
}
}
And here is the code where I call the draw method :
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
class GLRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "GLRenderer";
private final Context context;
private final GLCube cube = new GLCube();
private long startTime;
private long fpsStartTime;
private long numFrames;
SceneObject drawObject;
SceneObject object;
//Used for object position and rotation.
float zRotation;
float xRotation;
float yRotation;
float kxRotation = 0.0f;
float kyRotation = 0.0f;
ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>();
boolean SEE_THRU = false;
GLRenderer(Context context) {
this.context = context;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Setup any OpenGL Options that are required.
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D);
if (SEE_THRU) {
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
}
//Optional - disable dither to boost peformance.
//gl.glDisable(GL10.GL_DITHER); //Dithering enabled by default.
//Turn on the lights.
float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1};
float lightDiffuse[] = new float[] {1, 1, 1, 1};
float[] lightPos = new float[] {1 ,1 ,1 , 1};
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);
//Specify which materials we should use.
float matAmbient[] = new float[] {1, 1, 1, 1};
float matDiffuse[] = new float[] {1, 1, 1, 1};
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
//Define the view frustrum
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
float ratio = (float)width/height;
gl.glLoadIdentity();
//gl.glOrthof(0, 480f, 800f, 0, 0, 1);
GLU.gluPerspective(gl, 45.0f, ratio, 1.0f, 100f);
}
public void onDrawFrame (GL10 gl) {
//Defs for rotation of object.
float kzRotation = 0.0f;
kyRotation +=1.0f;
kxRotation =280.0f;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
SceneObject object = sceneObjects.get(13); //Get the object
//Position the model.
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -30.0f);
gl.glScalef(0.0001f, 0.0001f, 0.0001f);
zRotation = kzRotation;
xRotation = kxRotation;
yRotation = kyRotation;
gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f);
gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f);
gl.glRotatef(zRotation, 0.0f, 0.0f, 1.0f);
object.draw(gl);
}
}
}
The problem is that the object is not displaying as it should, but instead looks warped and squashed. Can anyone spot what might be wrong ?
EDIT - Changed the onSufaceChanged method as per Tim's answer below, however no improvement.
I've added an image of how the object is rendering on Android and the same object rendering correct on the iPhone. The most noticeable problem is that the "legs" should be straight and not bend and overall the object should be much longer. I'm sure the vertices and indices in the code above are correct (they are exactly the same as the iPhone ones).
In case it is relevant here is how I am setting up the surfaceview / view:
public class SaxParserActivity extends Activity {
/** Called when the activity is first created. */
ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
GLView view;
view = new GLView(this, sceneObjects);
//Pass down our sceneObjects into the view class.
//view.sceneObjects = sceneObjects;
setContentView(view);
}
}
class GLView extends GLSurfaceView {
private final GLRenderer renderer;
ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>();
GLView(Context context, ArrayList<SceneObject> sceneObjects) {
super (context);
//Uncomment this to turn on error-checking and logging.
//setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
renderer = new GLRenderer(context);
//Pass down our sceneObjects.
renderer.sceneObjects = sceneObjects;
setRenderer(renderer);
}
}
I'm a bit confused by what you're doing. Why do you wipe on the projection matrix in onDrawFrame, after setting it in onSurfaceChanged?
You should set projection in onSurfaceChanged like so:
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity(); //make sure to reset before glOrthof
gl.glOrthof(0, 320f, 480f, 0, 0, 1);
}
And then change back to modelview and don't disturb the projection matrix during onDrawFrame.
You'll probably need to recalibrate your scale and translate in onDrawFrame as well after doing this.
Related
GP/GPU : ping pong technique with JOGL
I've tried to implement an reaction-diffusion model on GPU with JOGL and GLSL. I use a ping pong technique with 2 FramebufferObject ( I've tried too with one FBO and 2 Colors attachements without success). Shader seems correct since I've tried it in unity (with some adaptations) and it works. After one week of trying many things, i'm completely out of idea to make this code works. I'm really not specialist of JOGL, so maybe i miss something evident. The result is an image which becomes white with time : no reaction-diffusion behaviors and I don't understand why ! Thanks in advance for helps. Here is my code : package gpu2; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.nio.IntBuffer; import java.nio.FloatBuffer; import java.io.File; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.GLFBODrawable; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Colorbuffer; import com.jogamp.opengl.FBObject.ColorAttachment; import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderUtil; import com.jogamp.opengl.util.GLBuffers; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLOffscreenAutoDrawable; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.GLDrawableFactory; import static com.jogamp.opengl.GL.*; // GL constants import static com.jogamp.opengl.GL2.*; // GL2 constants import gpu2.ModelParam; /** * JOGL 2.0 Program Template (GLCanvas) * This is a "Component" which can be added into a top-level "Container". * It also handles the OpenGL events to render graphics. */ #SuppressWarnings("serial") public class JOGL2Setup_GLCanvas extends GLCanvas implements GLEventListener { // Define constants for the top-level container private static String TITLE = "JOGL 2.0 Setup (GLCanvas)"; // window's title private static final int CANVAS_WIDTH = 512; // width of the drawable private static final int CANVAS_HEIGHT = 512; // height of the drawable private static final int FPS = 30; // animator's target frames per second private final float[] canvasVertices = { -1f, -1f, 0.0f, -1f, 1f, 0.0f, 1f, -1f, 0.0f, 1f, 1f, 0.0f, }; private final float[] canvasTexCoords = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; /** The entry main() method to setup the top-level container and animator */ public static void main(String[] args) { // Run the GUI codes in the event-dispatching thread for thread safety SwingUtilities.invokeLater(new Runnable() { #Override public void run() { // Create the OpenGL rendering canvas GLCanvas canvas = new JOGL2Setup_GLCanvas(); canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT)); // Create a animator that drives canvas' display() at the specified FPS. final FPSAnimator animator = new FPSAnimator(canvas, FPS, true); // Create the top-level container final JFrame frame = new JFrame(); // Swing's JFrame or AWT's Frame frame.getContentPane().add(canvas); frame.addWindowListener(new WindowAdapter() { #Override public void windowClosing(WindowEvent e) { // Use a dedicate thread to run the stop() to ensure that the // animator stops before program exits. new Thread() { #Override public void run() { if (animator.isStarted()) animator.stop(); System.exit(0); } }.start(); } }); frame.setTitle(TITLE); frame.pack(); frame.setVisible(true); animator.start(); // start the animation loop } }); } // Setup OpenGL Graphics Renderer private GLU glu; // for the GL Utility private GL2 gl; //OpenGl data private int vboVertices; private int vboTextCoord; private Texture textureFile; private FBObject fbo[]; private ShaderProgram shaderCompute; private ShaderProgram shaderVisu; private ShaderProgram shaderComputeInit; private int currentSourceBuffer = 0; private int currentDestBuffer = 1; private int currentFrame = 0; private int maxFrameCount = 5000000; private float clearUniform = 0; ModelParam params = new ModelParam(); public JOGL2Setup_GLCanvas() { this.addGLEventListener(this); } #Override public void init(GLAutoDrawable drawable) { gl = drawable.getGL().getGL2(); // get the OpenGL graphics context glu = new GLU(); // get GL Utilities gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color gl.glEnable(GL_TEXTURE_2D); gl.glEnable( GL_COLOR_MATERIAL ); gl.glEnable( GL_FRAMEBUFFER ); gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NEAREST); // best perspective correction viewOrtho(gl); gl.glViewport(0,0,CANVAS_WIDTH,CANVAS_HEIGHT); int[] buffers = new int[2]; gl.glGenBuffers(2, buffers, 0); vboVertices = buffers[0]; vboTextCoord = buffers[1]; gl.glBindBuffer(GL_ARRAY_BUFFER, vboVertices); gl.glBufferData(GL_ARRAY_BUFFER, canvasVertices.length*(Float.SIZE/Byte.SIZE)*3, FloatBuffer.wrap(canvasVertices), GL_STATIC_DRAW); gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glBufferData(GL_ARRAY_BUFFER, canvasTexCoords.length*(Float.SIZE/Byte.SIZE)*2, FloatBuffer.wrap(canvasTexCoords), GL_STATIC_DRAW); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); // ------------ create Texture Source------------------------ textureFile = initializeTexture(); if (textureFile==null) { System.out.println("cannot load texture from disk"); } // ------------ load shaders ------------------------ shaderCompute = loadShader(gl, "compute.vsh", "compute.fsh"); shaderComputeInit = loadShader(gl, "compute.vsh", "computeInit.fsh"); shaderVisu = loadShader(gl, "visu.vsh", "visu.fsh"); // ------------ create FBO ------------------------ initFBO(); } /** * Called back by the animator to perform rendering. */ #Override public void display(GLAutoDrawable drawable) { if (currentFrame < maxFrameCount) { prepareNextStep(); renderToFBO(); currentFrame++; } renderFBOToScreen(); } private void prepareNextStep() { currentSourceBuffer = 1 - currentSourceBuffer; currentDestBuffer = 1 - currentDestBuffer; } private void renderToFBO() { fbo[currentDestBuffer].bind(gl); //gl.glClear(GL_COLOR_BUFFER_BIT); viewOrtho(gl); shaderCompute.useProgram(gl, true); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseU", 0.211f); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseV", 0.088f); setShaderUniformFloat(gl, shaderCompute.program(), "feed", 0.007f); setShaderUniformFloat(gl, shaderCompute.program(), "kill", 0.08f); setShaderUniformFloat(gl, shaderCompute.program(), "Tech", 1f); setShaderUniformFloat(gl, shaderCompute.program(), "currentFrame", currentFrame); setShaderUniformFloat2(gl, shaderCompute.program(), "resolution", CANVAS_WIDTH, CANVAS_HEIGHT); drawDataBuffer(shaderCompute, true); shaderCompute.useProgram(gl, false); fbo[currentDestBuffer].unbind(gl); } void drawDataBuffer(ShaderProgram currentShader, boolean sencondImage) { // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER,vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //activate texture data from last fbo final FBObject.Colorbuffer texSource = (FBObject.Colorbuffer) fbo[currentSourceBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, texSource.getName()); setShaderUniform1i(gl, currentShader.program(), "textureData", 0); if (sencondImage) { //activate texture with image from file gl.glActiveTexture(GL_TEXTURE1); gl.glBindTexture(GL_TEXTURE_2D, textureFile.getTextureObject()); textureFile.bind(gl); setShaderUniform1i(gl, currentShader.program(), "textureImage", 1); } //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); //disable texture image if (sencondImage) { gl.glActiveTexture(GL_TEXTURE1); textureFile.disable(gl); } //disable texture data gl.glActiveTexture(GL_TEXTURE0); gl.glDisable(texSource.getName()); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); } public void renderFBOToScreen() { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers gl.glLoadIdentity(); // reset the model-view matrix viewOrtho(gl); gl.glEnable(GL_TEXTURE_2D); final FBObject.Colorbuffer tex0 = (FBObject.Colorbuffer) fbo[currentDestBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, tex0.getName()); //activate shader shaderVisu.useProgram(gl, true); // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); //desactivate shader shaderVisu.useProgram(gl, false); } private void initFBO() { try { gl.glEnable(GL_TEXTURE_2D); fbo = new FBObject[2]; //first fbo fbo[currentSourceBuffer] = new FBObject(); // Create FrameBuffer fbo[currentSourceBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentSourceBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentSourceBuffer].bind(gl); int tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentSourceBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); int DrawBuffers[] = {GL_COLOR_ATTACHMENT0}; gl.glDrawBuffers(1, DrawBuffers, 0); // "1" is the size of DrawBuffers fbo[currentSourceBuffer].unbind(gl); //second fbo fbo[currentDestBuffer] = new FBObject(); // Create FrameBuffer fbo[currentDestBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentDestBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentDestBuffer].bind(gl); tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentDestBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //ogl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); gl.glDrawBuffers(1, DrawBuffers, 1); // "1" is the size of DrawBuffers fbo[currentDestBuffer].unbind(gl); } catch (Exception e) { System.out.println("Problem with fbo init " + e); e.printStackTrace(); } } private Texture initializeTexture() { Texture t = null; try { t = TextureIO.newTexture(new File("e:/shaders/wiki.jpg"), false); t.setTexParameteri(gl, GL_TEXTURE_MIN_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_MAG_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); t.setTexParameteri(gl, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } catch (Exception e) { System.out.println("Unable to read texture file: " + e); e.printStackTrace(); } return t; } private ShaderProgram loadShader(GL2 gl, String vertexShader, String fragmentShader) { ShaderCode vertShader = ShaderCode.create(gl, GL2.GL_VERTEX_SHADER, 1, getClass(), new String[]{"e:/shaders/"+vertexShader},false); vertShader.compile(gl); ShaderCode fragShader = ShaderCode.create(gl, GL2.GL_FRAGMENT_SHADER, 1, getClass(), new String[]{"e:/shaders/"+fragmentShader},false); fragShader.compile(gl); ShaderProgram newShader = new ShaderProgram(); newShader.init(gl); newShader.add(vertShader); newShader.add(fragShader); newShader.link(gl, System.out); vertShader.destroy(gl); fragShader.destroy(gl); return newShader; } public static void setShaderUniform1i(GL2 inGL,int inProgramID,String inName,int inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1i(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat(GL2 inGL,int inProgramID,String inName,float inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1f(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat2(GL2 inGL,int inProgramID,String inName,float inValue1 ,float inValue2) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform2f(tUniformLocation, inValue1, inValue2); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } private void viewOrtho(GL2 gl) // Set Up An Ortho View { gl.glMatrixMode(GL_PROJECTION); // Select Projection gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); gl.glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix } private int genTexture(GL2 gl) { final int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); return tmp[0]; } /** * Called back before the OpenGL context is destroyed. Release resource such as buffers. */ #Override public void dispose(GLAutoDrawable drawable) { } } And the corresponding GLSL Shader : #version 120 uniform sampler2D textureData; uniform sampler2D textureImage; uniform vec2 resolution; uniform float diffuseU; uniform float diffuseV; uniform float feed; uniform float kill; uniform float Tech = 1.0; uniform float currentFrame = 0.0; void main() { //coords vec2 position = ( gl_FragCoord.xy / resolution.xy ); vec2 pixel = 1./resolution; //get data from texture vec4 imgSource = texture2D(textureImage, gl_TexCoord[0].st); vec2 oldUV = texture2D(textureData, gl_TexCoord[0].st).rg; if(currentFrame<10){ if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.2f) oldUV = vec2(0.0,0.2); else if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.3f) oldUV = vec2(0.5,0.1); else oldUV = vec2(0.1,0.0); gl_FragColor = vec4(oldUV.rg, 0.0, 1.0); return; } //get neightboors vec2 dataUp = texture2D(textureData, position + pixel * vec2(0., 1.)).rg; vec2 dataDown = texture2D(textureData, position + pixel * vec2(0., -1.)).rg; vec2 dataLeft = texture2D(textureData, position + pixel * vec2(-1., 0.)).rg; vec2 dataRight = texture2D(textureData, position + pixel * vec2(1., 0.)).rg; //adapt parameters vec2 imgParam = imgSource.rg; float dU = diffuseU ;//+ 0.01 * (imgParam - 0.5); float dV = diffuseV ;//+ 0.01 * (imgParam - 0.5); float F = feed ;//+ 0.01 * (imgParam - 0.5); float K = kill ;//+ 0.01 * (imgParam - 0.5); //compute new values vec2 laplace = (dataUp+dataDown+dataLeft+dataRight) - 4.0 * oldUV; float uvv = oldUV.r * oldUV.g * oldUV.g; // calculate delta quantities float du = dU * laplace.r - uvv + F*(1.0 - oldUV.r); float dv = dV * laplace.g + uvv - (F+K)*oldUV.g; vec2 newUV = oldUV + vec2(du, dv)* Tech; gl_FragColor = vec4(newUV.rg, 0.0, 1.0); }
Few considerations: avoid deprecated OpenGL (and GLU), use GL4 (or GL3) unless you need awt/swt/swing, prefer newt, more here prefer Animator instead of FPSAnimator, more here prefer direct buffers instead of arrays, since otherwise jogl has to create them underneath and you can't keep trace (= deallocate when done) of those native allocations GL4 will allow you also to avoid all those uniform overhead (and also potential bugs) you have to deal with (especially during runtime), thanks to explicit locations prefer direct buffer management instead of FBObject for the moment unless you really know what FBObject is doing. Once you get it working, you can move on using that class. This may be (one of the) cause your code is not working, because something is not getting setup up as you need. Moreover, the lines of codes needed to replace FBObject are essentially the same (if you can't use explicit location for any reason) prefer some literal way to define the texture uniform location, it is usually another tricky part causing bugs, something like this prefer also a sampler for the textures, gives you more flexibility don't wait one week next time, let us know earlier! :) Frustation can be a nasty thing that put you down easily. Together we can help you getting it working ;)
Is it possible to draw more than one object using OpenGL ES 2.0
This is an update to a question I recently asked, but with new problems after I tried some stuff. What I want is to draw multiple circles on the screen. I created a class for the circle object. In my renderer class, I created an array list of these circles each with a different position. When called to draw, it only draws one of them. I logged what was going on and each object is being called to get drawn, but it seems only one appears on the screen. It's not just my circles. It appears throughout personal testing OpenGL ES 2.0 will only draw one object on the screen. I have no idea how to fix this. Is there something special I have to do in OpenGL ES 2.0? Here is my code. Ignore the incredibly sloppy and inefficient code right now. I am aware of it and will fix it later. Here is my circle object class: GLCircle: package com.background.gl.objects; import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.glDrawArrays; import static android.opengl.Matrix.multiplyMM; import static android.opengl.Matrix.setIdentityM; import static android.opengl.Matrix.translateM; import static com.background.gl.glcirclebackgroundanimation.Constants.BYTES_PER_FLOAT; import java.util.Random; import android.opengl.Matrix; import android.util.Log; import com.background.gl.data.VertexArray; import com.background.gl.helper.TextureShaderProgram; public class GLCircle { private static final int POSITION_COMPONENT_COUNT = 2; private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2; private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT; public float x; public float y; protected float[] wallBounds; protected boolean positiveX, positiveY; public boolean nullify; protected float xCounter = 0f; protected float yCounter = 0f; public float[] bounds; protected Random ran; private float[] VERTEX_DATA = { // Order of coordinates: X, Y, S, T // Triangle Fan 0f, 0f, 0.5f, 0.5f, -0.25f, -0.25f, 0f, 0.9f, 0.25f, -0.25f, 1f, 0.9f, 0.25f, 0.25f, 1f, 0.1f, -0.25f, 0.25f, 0f, 0.1f, -0.25f, -0.25f, 0f, 0.9f }; private final VertexArray vertexArray; public GLCircle(float x, float y) { vertexArray = new VertexArray(VERTEX_DATA); ran = new Random(); wallBounds = new float[4]; nullify = false; this.x = x; this.y = y; } public void bindData(TextureShaderProgram textureProgram) { //Bind the position data to the shader attribute vertexArray.setVertexAttribPointer( 0, textureProgram.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE); //Bind the texture coordinate data to the shader attribute vertexArray.setVertexAttribPointer( POSITION_COMPONENT_COUNT, textureProgram.getTextureCoordinatesAttributeLocation(), TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE); } public void drawCircle() { glDrawArrays(GL_TRIANGLE_FAN, 0, 6); } public float getX() { return this.x; } public float getY() { return this.y; } public boolean isPositiveX() { return positiveX; } public boolean isPositiveY() { return positiveY; } public float[] getBounds(float ranX, float ranY) { if(!positiveX) { /*if(ranX >= 0f) { wallBounds[0] = 1.05f + ranX; } else {*/ this.wallBounds[0] = 1.05f + ranX; //} } else { /* if(ranX >= 0f) { wallBounds[0] = 1.05f - ranX; } else {*/ this.wallBounds[1] = 1.05f - ranX; //} } if(!positiveY) { this.wallBounds[2] = 1.75f + ranY; } else { this.wallBounds[3] = 1.75f - ranY; } return this.wallBounds; } public void setPos(float[] modelMatrix, float[] projectionMatrix, TextureShaderProgram textureProgram, int texture, float x, float y, String log) { setIdentityM(modelMatrix, 0); translateM(modelMatrix, 0, 0f, 0.01f, 0f); final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length); textureProgram.useProgram(); textureProgram.setUniforms(projectionMatrix, texture); bindData(textureProgram); drawCircle(); Log.d("Drawing", "Drawing " + log); } public void scaleCircle(float[] modelMatrix, float x, float y, float z) { Matrix.scaleM(modelMatrix, 0, x, y, z); } public void storeResults(float[] results) { this.x = results[0]; this.y = results[1]; } public void translateCircle(float x, float[] modelMatrix, float[] projectionMatrix) { setIdentityM(modelMatrix, 0); translateM(modelMatrix, 0, /*-0.001f*/ x, -3f, -2f); final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length); } } Again, I'm aware of most things I'm doing incorrectly, but currently I just need to figure out why I can't draw multiple objects on the screen. Here is my renderer code: package com.background.gl.glcirclebackgroundanimation; import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; import static android.opengl.GLES20.glClear; import static android.opengl.GLES20.glClearColor; import static android.opengl.GLES20.glViewport; import static android.opengl.Matrix.multiplyMM; import static android.opengl.Matrix.setIdentityM; import static android.opengl.Matrix.translateM; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView.Renderer; import android.util.Log; import com.background.gl.helper.TextureShaderProgram; import com.background.gl.objects.GLCircle; import com.background.gl.objects.Mallet; import com.background.gl.objects.Table; import com.background.gl.util.MatrixHelper; import com.background.gl.util.TextureHelper; public class CircleDynamicBackgroundRenderer implements Renderer { private final Context context; private final float[] projectionMatrix = new float[16]; private final float[] modelMatrix = new float[16]; protected static float ranX, ranY, ranSignX, ranSignY, ranSignVeloX, ranSignVeloY; public boolean logNums; private Table table; private Mallet mallet; private List<GLCircle> circles; private GLCircle circle2; float xPos, yPos; int x = 1; float[] bounds; Random ran; private TextureShaderProgram textureProgram; private int texture; public CircleDynamicBackgroundRenderer(Context context) { this.context = context; circles = new ArrayList<GLCircle>(); xPos = 0.1f; ran = new Random(); logNums = true; } #Override public void onSurfaceChanged(GL10 glUnused, int width, int height) { glViewport(0, 0, width, height); Log.w("Width and height", Integer.toString(width) + ", " + Integer.toString(height)); MatrixHelper.perspectiveM(projectionMatrix, 90, (float) width / (float) height, 1f, 10f); for(int i = 0; i < circles.size(); i++) { circles.get(i).translateCircle(circles.get(i).x, modelMatrix, projectionMatrix); } // /circle2.translateCircle(circle2.x, modelMatrix); /*final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);*/ } #Override public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { glClearColor(0.0f, 0.0f, 1.0f, 0.0f); table = new Table(); mallet = new Mallet(); textureProgram = new TextureShaderProgram(context); texture = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface); //texture2 = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface_2); for(int i = 0; i < 3; i++) { GLCircle circle = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]); circles.add(circle); /*circle[i].x = circle[i].getX(); circle[i].y = circle[i].getY(); circle[i].bounds = circle[i].getBounds();*/ } //circle2 = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]); Log.d("Circles size", Integer.toString(circles.size())); Log.d("circles", Float.toString(circles.get(1).getX()) + " " + Float.toString(circles.get(2).getX())); } #Override public void onDrawFrame(GL10 glUnused) { //Clear the rendering surface glClear(GL_COLOR_BUFFER_BIT); for(int i = 0; i < circles.size(); i++) { circles.get(i).setPos(modelMatrix, projectionMatrix, textureProgram, texture, circles.get(i).x, circles.get(i).y, "1"); if(logNums) { Log.d("Circle1, c2", Float.toString(circles.get(i).x) + ", " + Float.toString(circles.get(i).x)); logNums = false; } //Log.d("Circles", Float.toString(circles.get(i).x)); } } public float[] generateRanFloats() { ranSignX = ran.nextFloat(); ranSignY = ran.nextFloat(); ranSignX = ranSignX > 0.5f? -1:1; ranSignY = ranSignY > 0.5f? -1:1; ranSignVeloX = ran.nextFloat(); ranSignVeloY = ran.nextFloat(); ranX = ran.nextFloat() * 1.05f; ranY = ran.nextFloat() * 1.75f; ranX = ranSignX > 0.5? -ranX:ranX; ranY = ranSignY > 0.5? -ranY:ranY; Log.d("Generated", Float.toString(ranX)); return new float[] {ranX, ranY}; } } It's been two days now and I cannot for the live of me figure out what is wrong and how to fix this. I really need to figure out a way to fix this. Any assistance will be greatly appreciated. If you need to see more code, let me know.
Per the last discussion - did you work on the perspective matrix ? I would recommend first starting with the ortho projection, get your code working, then move to working with perspective projection. You can use the below as a starting point for ortho projection. mat4.ortho(-1.0, 1.0, -1, 1.0, -10.0, 100.0, projectionMatrix); Also remove all the z translations in your code, make your code work on xy, then add z translations. PS: Isnt it better to continue in the same thread as (OpenGL ES 2.0 only draws the object once) ?
Android OpenGL ES Polygon Tutorial Assistance
I have followed some Android tutorials and have this Triangle program that works and runs and creates a filled Triangle successfully. I am now trying to follow several different Polygon tutorials but none seem to help translating my code to a polygon. I have scoured stack and everywhere else, so I know this may seem repetitive. I want to be able to enter the number of sides and have the program generate the polygon with that many sides. I can sort of hard code in vertices in order to generate a polygon but cannot make this a polygon of n sides. Would anyone be able to guide me in the right direction or provide some examples? I am lost. Triangle.java import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; public class Triangle{ private FloatBuffer vertexBuffer; private int vSize = 7; public Triangle(){ float vertices[] = { -.5f, -.433f, 0, 1, 0, 0, 1, .5f, -.433f, 0, 0, 1, 0, 1, 0, .433f, 0, 0, 0, 1, 1 }; ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length*4); byteBuffer.order(ByteOrder.nativeOrder()); vertexBuffer = byteBuffer.asFloatBuffer(); vertexBuffer.put(vertices); } public void onDrawFrame(GL10 gl) { vertexBuffer.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, vSize*4, vertexBuffer); vertexBuffer.position(3); gl.glColorPointer(4, GL10.GL_FLOAT, vSize*4, vertexBuffer); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); // GL_TRAINGLEFAN for polygon? gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); } } MyRenderer.java import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; public class MyRenderer implements Renderer { private Triangle triangle; #Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); triangle.onDrawFrame(gl); } #Override public void onSurfaceChanged(GL10 gl, int width, int height) { if(width<height){ gl.glViewport(0, 0, width, width); }else{ gl.glViewport(0, 0, height, height); } gl.glMatrixMode(GL10.GL_PROJECTION); //to work with the projection matrix //to do: set up ortho projection gl.glLoadIdentity(); gl.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -0.1f, 0.1f); gl.glMatrixMode(GL10.GL_MODELVIEW);//methods should restore model view matrix mode } #Override public void onSurfaceCreated(GL10 gl, EGLConfig arg1) { gl.glClearColor(0.8f, 0.8f, 0.8f, 1); triangle = new Triangle(); } } MainActivity.java import android.opengl.GLSurfaceView; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { private GLSurfaceView view; private MyRenderer renderer; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); view = new GLSurfaceView(this); renderer = new MyRenderer(); view.setRenderer(renderer); setContentView(view); } #Override protected void onPause() { view.onPause(); super.onPause(); } #Override protected void onResume() { view.onResume(); super.onResume(); } #Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
Sample a circle every (2 * pi) / n radians: void glPolygon( unsigned int sides ) { glBegin( GL_TRIANGLE_FAN ); glVertex2f( 0, 0 ); for( unsigned int i = 0; i <= sides; i++ ) { const float u = ( i / (float)sides ); const float a = ( 2 * 3.14159 ) * u; glVertex2f( cos( a ), sin( a ) ); } glEnd(); }
OpenGL ES 2.0 doesn't draw anything
I have a problem with OpenGl ES 2.0. I've designed a very simple framework to help me load OBJ files and draw them on my Android phone, but I have 2 bugs that I haven't been able to fix: My app doesn't show anything until I change the orientation and the Activity gets scraped and reloaded. Until it reloads only GLES20.glClear() can be seen(I've set it to a grayish color). Sometimes when I load an OBJ and do the orientation trick, half of my faces are missing and I see gaps, but the problem might be with the OBJ files I've used. package com.ideas.opengl; import java.io.IOException; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES20; import android.opengl.GLSurfaceView.Renderer; import android.opengl.Matrix; public class DemoRenderer implements Renderer { public static int mProgramHandle; private int mMVPMatrixHandle; private float[] mModelMatrix = new float[16]; private float[] mViewMatrix = new float[16]; private float[] mProjectionMatrix = new float[16]; private float[] mMVPMatrix = new float[16]; public Object banana; private OpenGLDemoActivity activity; private int angle; public DemoRenderer(OpenGLDemoActivity activity) throws IOException { this.activity = activity; } #Override public void onSurfaceCreated(GL10 gl, EGLConfig config){ GLES20.glClearColor(0.65f, 0.65f, 0.65f, 0.65f); //GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_TEXTURE_2D); Shader shader = null; try { shader = new Shader(activity, "simple"); } catch (IOException e) { e.printStackTrace(); } Vector position = new Vector(); Vector speed = new Vector(); Vector accel = new Vector(); Model model = null; try { model = new Model("banana", activity); } catch (IOException e) { e.printStackTrace(); } banana = new Object(position, speed, accel, model); mProgramHandle = shader.getProgramHandle(); final float eyeX = 0.0f; final float eyeY = 0.0f; final float eyeZ = 3.5f; final float lookX = 0.0f; final float lookY = 0.0f; final float lookZ = -5.0f; final float upX = 0.0f; final float upY = 1.0f; final float upZ = 0.0f; Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix"); } #Override public void onSurfaceChanged(GL10 gl, 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(mProjectionMatrix, 0, left, right, bottom, top, near, far); } #Override public void onDrawFrame(GL10 gl) { GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); angle++; Matrix.setIdentityM(mModelMatrix, 0); Matrix.rotateM(mModelMatrix, 0, angle, 0.0f, 1.0f, 1.0f); Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); banana.draw(); } } `
Tried some glGetError() and got to errors, one regarding a variable that had its value unchanged and another was that glGetAttributeLocation() return a -1 if the attribute is not used in the vertex shader. Thaks for the help!
The problem with the geometry is likely due to using the same float array for input and output in the matrix multiplication: Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); According to the multiplyMM() specs the input and output arrays may not have overlapping elements, but you use the same array mMVPMatrix starting with the same index 0. One way to fix the problem is to use another matrix as a buffer for the result of the last multiplication, so instead of: Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); use: Matrix.multiplyMM(mMatrixFinal, 0, mProjectionMatrix, 0, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMatrixFinal, 0);
OpenGL ES texture won't draw
I have followed a tutorial on how to display an image in OpenGL, and I first had to make a square and then texture it. I have tried gl.glColor4f(0f,0f,0f,1f); and that works, I can see the square. But then when I try to texture it, the screen just stays white. What did I do wrong? Here is the screen with the gl.glColor4f(0f,0f,0f,1f); : If I apply the texture (using the custom Texture class that the tutorial suggested), the screen is completely white. Here is my code: Square.java: package com.chrypthic.android.reference; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; public class Square { final int VERTEX_SIZE = (2+2) *4; FloatBuffer vertices; ShortBuffer indices; Texture texture; GL10 gl; Context c; public Square(GL10 gl, Context context) { this.gl = gl; this.c = context; ByteBuffer byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4); byteBuffer.order(ByteOrder.nativeOrder()); vertices = byteBuffer.asFloatBuffer(); vertices.put(new float[]{ 10.0f, 10.0f, 0.0f, 0.0f, //bl 160.0f, 10.0f, 1.0f, 0.0f, //br 160.0f, 160.0f, 1.0f, 1.0f, //tr 10.0f, 160.0f, 1.0f, 0.0f, //tl }); vertices.flip(); byteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * 4); byteBuffer.order(ByteOrder.nativeOrder()); indices = byteBuffer.asShortBuffer(); indices.put(new short[]{ 0, 1, 2, 2, 3, 0 }); indices.flip(); texture = new Texture("image/picture.png", c, gl); } public void draw() { gl.glEnable(GL10.GL_TEXTURE_2D); texture.bind(); //gl.glColor4f(0f, 0f, 0f, 1f); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); vertices.position(0); gl.glVertexPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); vertices.position(2); gl.glTexCoordPointer(2, GL10.GL_FLOAT, VERTEX_SIZE, vertices); gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_SHORT, indices); } } Texture.java package com.chrypthic.android.reference; import java.io.InputStream; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLUtils; public class Texture { String texturePath; Context context; GL10 gl; int textureId; int minFilter; int magFilter; Bitmap texture; public Texture(String texturePath, Context context, GL10 gl) { this.gl = gl; this.texturePath = texturePath; this.context = context; } public void load() { try{ AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open(texturePath); texture = BitmapFactory.decodeStream(is); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); }catch(Exception e) { e.printStackTrace(); } } public void reload() { load(); bind(); setFilters(minFilter, magFilter); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); } public void setFilters(int minFilter, int magFilter) { this.minFilter = minFilter; this.magFilter = magFilter; gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter); } public void bind() { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); } public void dispose() { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); int[] textureIds = {textureId}; gl.glDeleteTextures(1, textureIds, 0); } } OpenGLRenderer.java package com.chrypthic.android.reference; import java.util.Random; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView.Renderer; public class OpenGLRenderer implements Renderer { Random rand = new Random(); int mWidth = 0; int mHeight = 0; Context c; Square square; public OpenGLRenderer(Context c) { this.c = c; } #Override public void onDrawFrame(GL10 gl) { gl.glClearColor(1, 1, 1, 1); gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glViewport(0, 0, mWidth, mHeight); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrthof(0, mWidth, 0, mHeight, -1, 1); if(square != null)square.draw(); } #Override public void onSurfaceChanged(GL10 gl, int width, int height) { mWidth = width; mHeight = height; } #Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { square = new Square(gl, c); } } I hope you can help me, if you need even more information just tell me. Thanks in advance. I did't post the white screen as a screenshot, because it seems kind of pointless with the white background that stackoverflow have.
You never create the texture! public void load() { try{ int []texture = new int[1]; gl.glGenTextures(1, texture,0);//the missing method textureId = texture[0]; //now you can call AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open(texturePath); texture = BitmapFactory.decodeStream(is); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);/*this fails if textureId is a 'random' number. You must/should generate a valid id. */ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0); setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); It is exactly the opposite of your dispose() method.
Going from a comment to an answer. (Comment): Why are you using glVertexPointer twice rather that glVertexPointer and then glTexCoordPointer? Also there seems to be a typo in that line that says GL_FLAT instead of GL_FLOAT. Are you sure you're giving us your actual code? -Answer starts here- It looks like you aren't using texture coordinates at all. You have to specify which corner of the texture you'd like to assign to which corner of the triangle/quad. For example, I see that you've got a "tl" comment next to the top left vertex. You similarly need to supply a texture coordinate that says "use the top left corner of the image with this vertex" and then OpenGL figures out the rest. Then when you go to pass the vertex pointer, you also have to pass a texture coordinate pointer that contains those texture coordinates I were just talking about in the previous paragraph. You do this with glTexCoordPointer in the exact same fashion as glVertexPointer. You can also load texture coordinates into a VBO (in fact, into the same VBO as the vertices, then you can call glTexCoordPointer with the offset into the VBO to where the tex coords start). Let me know (via comment) if you need more elaboration/code examples or more explanation anywhere. Edit 1: See these links for information about texture mapping: gamedev, nehe Edit 2: Okay, stupid me. I didn't notice that you've actually got the texture coordinate data in with the vertex data. Try changing your second call to glVertexPointer to glTexCoordPointer. This might fix your problem entirely.