My program does:
Load texture to GPU.
Load VBO of uv coordinates to GPU.
Load VBO of mode coordinates to GPU.
Load VBO of indeces to GPU.
Bind to texture.
Bind to uv coordinates VBO.
Bind to model coordinates VBO.
Bind to index coordiantes VBO.
DRAW
But only part of each texture is actually drawn. If I use all of the same arrays and draw without VBO's (move from client side each draw) it draws fine.....
Any ideas? Been scratching me head for a couple hours now.
I have posted relevant code below:
LOAD TO GPU:
this.texture = new int[1];
GLES20.glGenTextures(1, this.texture, 0);
//GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texture[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
// Generate VBOs for UV data and model data. My indece VBO is done elswhere
this.vbo = new int[2];
GLES20.glGenBuffers(2,vbo,0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[0] );
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, uvsBuff.capacity() * FH_Utilities.SHORT_SIZE,
uvsBuff, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, posBuff.capacity() * FH_Utilities.SHORT_SIZE,
posBuff, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
DRAWING:
GLES20.glUseProgram(this.terrainShader.mProgram);
int mtrxhandle = GLES20.glGetUniformLocation(this.terrainShader.mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texture[0]);
int mSamplerLoc = GLES20.glGetUniformLocation (this.terrainShader.mProgram, "s_texture" );
GLES20.glUniform1i ( mSamplerLoc, 0);
int mTexCoordLoc = GLES20.glGetAttribLocation(this.terrainShader.mProgram, "a_texCoord");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[0]);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
GLES20.glVertexAttribPointer(mTexCoordLoc, 2,
GLES20.GL_SHORT, false,
0, 0);
int mPositionHandle = GLES20.glGetAttribLocation(this.terrainShader.mProgram, "vPosition");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[1]);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_SHORT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, this.drawHandles[0][0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, this.drawHandles[0][1], GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
GENERATE INDECES:
private int[][] genIndeces(int tileSize, int Nindexes){
int[][] indeceHandles = new int[Nindexes][2];
int indMaxLen = ((tileSize-1) * ((tileSize*2) +2))-2;
int indMaxBytes = indMaxLen * FH_Utilities.SHORT_SIZE;
short[][] index = new short[tileSize][tileSize];
short[] IDA = new short[indMaxLen];
ByteBuffer bInd;
int nIndeces;
int x,y;
/* Build an Indece Buffer for course triangle strips */
nIndeces = 0;
for(y=0;y<tileSize;y++){
for(x=0;x<tileSize;x++){
index[y][x] = (short)nIndeces;
nIndeces++;
}
}
/*Run through however many resolutions desired */
bInd = ByteBuffer.allocateDirect(indMaxBytes).order(ByteOrder.nativeOrder());
ShortBuffer sInd = bInd.asShortBuffer();
nIndeces=0;
for(y=0;y<tileSize-1;y++){
for(x=0;x<tileSize;x++){
IDA[nIndeces] = index[y+1][x];
nIndeces++;
IDA[nIndeces] = index[y][x];
nIndeces++;
if(x==tileSize-1 && y != tileSize -2) {
IDA[nIndeces] = index[y][x];
nIndeces++;
IDA[nIndeces] = index[y+2][0];
nIndeces++;
}
}
}
sInd.clear();
sInd.put(IDA, 0, nIndeces);
sInd.position(0);
int tempHandle[] = new int[1];
GLES20.glGenBuffers(1,tempHandle,0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, tempHandle[0]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, sInd.capacity() * FH_Utilities.SHORT_SIZE, sInd, GLES20.GL_STATIC_DRAW);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
indeceHandles[0][0] = tempHandle[0];
indeceHandles[0][1] = nIndeces;
bInd.limit(0);
sInd.limit(0);
bInd=null;
sInd=null;
IDA=null;
index=null;
System.gc();
return indeceHandles;
}
Related
I just started programming opengl-es 2.0 and I'm currently struggling to find an issue concerned with setting the color of a wavefront object im drawing (https://pastebin.com/cEvpj8rt). The drawing is working just fine until I start to manipulate the color at which point im being confronted with opengl error 1281 and I'm unable to pinpoint the cause in my code. I've broken down the shader code to what I believe is the bare minimum required for the fragment shader to work:
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
To eliminate any additional source of error I am setting the color with a constant value as can be seen above. I doubt the error lies with the simple code above but is concerned with the code in my adapted renderer implementation. (it is based on the renderer that came with a sample from the ar-core github repo. The full code of the initial renderer can be found here: https://github.com/google-ar/arcore-android-sdk/blob/master/samples/java_arcore_hello_ar/app/src/main/java/com/google/ar/core/examples/java/helloar/rendering/ObjectRenderer.java while the adapted version can be seen here: https://pastebin.com/9cmKVnLV) Below you can find an excerpt of the code responsible for setting up and drawing the object. I reckoned the issue to be connected to the texturing which is why I removed the code.
I know its a bit much to ask for help given my lack of understanding on the matter at hand but I'd be glad for any hint/advice at this point. The error occurs after the first draw in the following method:
public void draw(float[] cameraView, float[] cameraPerspective) {
multiplyMM(mModelViewMatrix, 0, cameraView, 0, mModelMatrix, 0);
multiplyMM(mModelViewProjectionMatrix, 0, cameraPerspective, 0, mModelViewMatrix, 0);
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
glVertexAttribPointer(mPositionAttribute, COORDS_PER_VERTEX,
GL_FLOAT, false, 0, mVerticesBaseAddress);
glVertexAttribPointer(mNormalAttribute, 3,
GL_FLOAT, false, 0, mNormalsBaseAddress);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Set the ModelViewProjection matrix in the shader.
glUniformMatrix4fv(mModelViewUniform, 1,
false, mModelViewMatrix, 0);
glUniformMatrix4fv(mModelViewProjectionUniform, 1,
false, mModelViewProjectionMatrix, 0);
glEnableVertexAttribArray(mPositionAttribute);
glEnableVertexAttribArray(mNormalAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(mPositionAttribute);
glDisableVertexAttribArray(mNormalAttribute);
// this is where the error is detected
OpenGlHelper.checkGLError(TAG, "After draw");
}
Here the method which is used for initialization:
public void createOnGlThread(Context context) throws IOException {
InputStream objInputStream = context.getAssets()
.open(OBJ_ASSET_NAME);
Obj obj = ObjReader.read(objInputStream);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer wideIndices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
FloatBuffer normals = ObjData.getNormals(obj);
ShortBuffer indices = ByteBuffer.allocateDirect(2 * wideIndices.limit())
.order(ByteOrder.nativeOrder()).asShortBuffer();
while (wideIndices.hasRemaining()) {
indices.put((short) wideIndices.get());
}
indices.rewind();
int[] buffers = new int[2];
glGenBuffers(2, buffers, 0);
mVertexBufferId = buffers[0];
mIndexBufferId = buffers[1];
// Load vertex buffer
mVerticesBaseAddress = 0;
mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.limit();
mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.limit();
final int totalBytes = mNormalsBaseAddress + 4 * normals.limit();
glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
glBufferData(GL_ARRAY_BUFFER, totalBytes, null, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, mVerticesBaseAddress,
4 * vertices.limit(), vertices);
glBufferSubData(GL_ARRAY_BUFFER, mTexCoordsBaseAddress,
4 * texCoords.limit(), texCoords);
glBufferSubData(GL_ARRAY_BUFFER, mNormalsBaseAddress,
4 * normals.limit(), normals);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Load index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
mIndexCount = indices.limit();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * mIndexCount,
indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
OpenGlHelper.checkGLError(TAG, "OBJ buffer load");
mProgram = glCreateProgram();
glAttachShader(mProgram, OpenGlHelper.loadGLShader(TAG, context,
GL_VERTEX_SHADER, R.raw.sphere_vertex));
glAttachShader(mProgram, OpenGlHelper.loadGLShader(TAG, context,
GL_FRAGMENT_SHADER, R.raw.sphere_fragment));
glLinkProgram(mProgram);
glUseProgram(mProgram);
OpenGlHelper.checkGLError(TAG, "Program creation");
mModelViewUniform = glGetUniformLocation(mProgram, "u_ModelView");
mModelViewProjectionUniform =
glGetUniformLocation(mProgram, "u_ModelViewProjection");
mPositionAttribute = glGetAttribLocation(mProgram, "a_Position");
mNormalAttribute = glGetAttribLocation(mProgram, "a_Normal");
OpenGlHelper.checkGLError(TAG, "Program parameters");
setIdentityM(mModelMatrix, 0);
}
I'm trying to create a frameBuffer using a floating point texture and everything has been working fine, the frameBuffer lists as a complete attachment. But now I seem to be getting this error and can not draw into my texture.
07-22 21:00:15.180: W/Adreno-ES20(27203): <validate_render_targets:454>: GL_INVALID_OPERATION
I have no idea what it means by validate render targets or how it could be an invalid operation. Google does not appear to be my friend either in this matter as I return no results as to what it is. I cant seem to find anything within the opengl sdk docs either.
Heres the code for setting up my framebuffer
public void setup(Context context) {
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 1.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);
int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER,
ShaderHelper.readShader(context, R.raw.vertex_shader));
int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER,
ShaderHelper.readShader(context, R.raw.fragment_shader));
mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
new String[] {"a_Position", "a_TexCoord"});
vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER,
ShaderHelper.readShader(context, R.raw.particle_vertex_shader));
fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER,
ShaderHelper.readShader(context, R.raw.particle_fragment_shader));
mPartProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
new String[] {"a_Position"});
// create the ints for the framebuffer, depth render buffer and texture
int[] fb, renderTex; // the framebuffer, the renderbuffer and the texture to render
fb = new int[1];
renderTex = new int[2];
// generate
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glGenTextures(2, renderTex, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);
// parameters - we have to make sure we clamp the textures to the edges
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);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
int GL_OES_texture_half_float = 0x8D61;
int GL_RGBA32F = 0x8814;
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GL_RGBA32F, texW, texH, 0, GLES20.GL_RGBA, GLES20.GL_FLOAT, null);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);
// ShaderHelper.saveTexture(renderTex[0], texW, texH, "test");
posTex = renderTex[0];
posFb = fb[0];
final int buffers[] = new int[2];
GLES20.glGenBuffers(2, buffers, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, spriteBuffer.capacity() * BYTES_PER_FLOAT, spriteBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, renderQuad.capacity() * BYTES_PER_FLOAT, renderQuad, GLES20.GL_STATIC_DRAW);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mTransformsHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Transforms");
mTexDataHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_TexData");
mTexUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
mTexCoordHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoord");
mPosTexHandle = GLES20.glGetUniformLocation(mPartProgramHandle, "u_Positions");
mFBPositionHandle = GLES20.glGetAttribLocation(mPartProgramHandle, "a_Position");
spriteBufferIdx = buffers[0];
fbQuadBufferIdx = buffers[1];
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
and here is the actual draw code
private void renderToTexture() {
GLES20.glViewport(0, 0, this.texW, this.texH);
// Bind the framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, posFb);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, fbQuadBufferIdx);
// check status
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE)
throw new RuntimeException("FrameBuffer Error; Status = " + status);
transforms[0] = Fields.screen_width / 2;
transforms[1] = Fields.screen_height / 2;
transforms[2] = 0;
transforms[3] = Fields.screen_height;
pixels.put(transforms).position(0);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, 1, 1, GLES20.GL_RGBA, GLES20.GL_FLOAT, pixels);
GLES20.glReadPixels(0, 0, 1, 1, GLES20.GL_RGBA, GLES20.GL_FLOAT, pixels);
Log.d("X", "X=" + pixels.get(0));
GLES20.glClearColor(.0f, .0f, .0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mPartProgramHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, posTex);
GLES20.glUniform1i(mPosTexHandle, 0);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 8, 0);
// Clear the currently bound buffer (so future OpenGL calls do not use this buffer).
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
// Draw the cubes.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
// if (!saved)
// ShaderHelper.saveTexture(posTex, texW, texH, "test2");
// saved = true;
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
Any idea how I am generating this error or advice for debugging this in the future?
I'm using gstreamer to retrieve a video feed (sent from a RaspPi), and I need to display it into Google Cardboard.
I based my work on the tutorial-3 example of gstreamer. I managed to display my video into a SurfaceView, by giving my Surface (retrieved from SurfaceView.SurfaceHolder.getSurface(), but I now need to connect it with the Google Cardboard.
If I do not mistake, Google Cardboard relies on some SurfaceTexture. So I thought it would be easy to simply get the Surface from the SurfaceTexture using the Surface(SurfaceTexture) constructor.
The problem is that it simply doesn't work. My Google cardboard application Cardboard Pasthrough example, and I haven't touched the OpenGL code, since I don't know anything about it.
While debugging, I found out that there is (at least) one problem with the code I'm using. It seems that the line
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
are causing me some trouble since GL_TEXTURE_EXTERNAL_OES isn't in the required range for the glActiveTexture methods (which requires a GL from 0 to GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS).
Here are my logs :
GLConsumer W [unnamed-12520-0] bindTextureImage: clearing GL error: 0x500
Adreno-ES20 W <core_glActiveTexture:348>: GL_INVALID_ENUM
So what's working right now ?
It seems that the video feed is received by gstreamer, that tries to update the Surface (I get some notifications about the onFrameAvailable of the SurfaceTexture that are being updated, and the error logs are only sent since there). However, the screens stays black, as if nothing is updated.
Here are the most interesting parts of my code :
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CardboardView cardboardView = (CardboardView) findViewById(R.id.cardboard_view);
cardboardView.setRenderer(this);
setCardboardView(cardboardView);
// Initialize GStreamer and warn if it fails
try {
GStreamer.init(this);
} catch (Exception e) {
//Catch e...
}
mCamera = new float[16];
mView = new float[16];
mHeadView = new float[16];
//gstreamer stuff
nativeInit();
}
#Override
public void onSurfaceCreated(EGLConfig eglConfig) {
Log.d(TAG, "onSurfaceCreated start");
GLES20.glClearColor(0.5f, 0.1f, 0.1f, 0.5f);
ByteBuffer bb = ByteBuffer.allocateDirect(squareVertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareVertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer bb2 = ByteBuffer.allocateDirect(textureVertices.length * 4);
bb2.order(ByteOrder.nativeOrder());
textureVerticesBuffer = bb2.asFloatBuffer();
textureVerticesBuffer.put(textureVertices);
textureVerticesBuffer.position(0);
int vertexShader = loadGLShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadGLShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram);
checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
Log.d(TAG, "Surface created");
texture = createTexture();
initSurface(texture);
}
static private int createTexture()
{
Log.d(TAG + "_cardboard", "createTexture");
int[] texture = new int[1];
GLES20.glGenTextures(1,texture, 0);
checkGLError("GenTextures Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture[0]);
checkGLError("BindTextures Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
return texture[0];
}
//Give the surface to gstreamer.
private void initSurface(int texture) {
mSurface = new SurfaceTexture(texture);
mSurface.setOnFrameAvailableListener(this);
Log.d(TAG, "OnFrameAvailableListener set");
Surface toto = new Surface(mSurface);
nativeSurfaceInit(toto);
toto.release();
}
//When we need to render
#Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
Log.d(TAG, "onFrameAvailable");
this.getCardboardView().requestRender();
}
//Display to cardboard
#Override
public void onNewFrame(HeadTransform headTransform) {
headTransform.getHeadView(mHeadView, 0);
// Build the camera matrix and apply it to the ModelView.
Matrix.setLookAtM(mCamera, 0, 0.0f, 0.0f, 0.01f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
float[] mtx = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
mSurface.updateTexImage();
mSurface.getTransformMatrix(mtx);
float[] test = new float[3];
headTransform.getEulerAngles(test, 0);
//if(networkThread != null){
// networkThread.setRegValue(test);
//}
}
#Override
public void onDrawEye(Eye eye) {
// Log.d(TAG, "onDrawEye");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
Log.d(TAG, "trying to access " + GL_TEXTURE_EXTERNAL_OES +" out of " + GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
GLES20.glEnableVertexAttribArray(mPositionHandle);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, vertexStride, vertexBuffer);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, vertexStride, textureVerticesBuffer);
mColorHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
Matrix.multiplyMM(mView, 0, eye.getEyeView(), 0, mCamera, 0);
}
For more code, here is a gist with the main two files : https://gist.github.com/MagicMicky/4caa3ac669215652e40f
edit: When trying to work with the camera app on gstreamer, the same errors are shown in the logcat as the one I described earlier. So this might be nothing of importance...
Currently I am working on a 3D Game Engine for Android. The Project is just at the beginning, but there is a problem I cant' solve.
I want to use VertexBufferObjects for rendering the models loaded form an .obj file.
Here is the code
public class Mesh {
private final int mBytesPerFloat = 4;
private FloatBuffer vertices;
private FloatBuffer normals;
private IntBuffer faces;
private int vertexBuffer;
private int normalBuffer;
private int indexBuffer;
public Mesh(float[] vertices, float[] normals, int[] faces, int shaderProgram) {
this.normals = ByteBuffer.allocateDirect(normals.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
this.normals.put(normals).position(0);
this.faces = ByteBuffer.allocateDirect(faces.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
this.faces.put(faces).position(0);
this.vertices = ByteBuffer.allocateDirect(vertices.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
this.vertices.put(vertices).position(0);
ByteBuffer bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
IntBuffer buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
vertexBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, this.vertices.capacity() * mBytesPerFloat, this.vertices, GLES20.GL_STATIC_DRAW);
bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
normalBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normalBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, this.normals.capacity() * mBytesPerFloat, this.normals, GLES20.GL_STATIC_DRAW);
bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
indexBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, this.faces.capacity() * mBytesPerFloat, this.faces, GLES20.GL_STATIC_DRAW);
}
public Mesh() {
// TODO Auto-generated constructor stub
}
public void render(int shaderProgram) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(shaderProgram, "vertex"), 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(shaderProgram, "vertex"));
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normalBuffer);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(shaderProgram, "normal"), 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(shaderProgram, "normal"));
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, vertices.capacity()/3, GLES20.GL_INT, faces);
}
}
The problem is that I do not see anything.
The problem is not the shader i am using (which I know is working correctly) and the modelview matrix and projection matrix are correct, so the object should be visible, if it is rendered which it isn't.
Has anyone an idea what the problem might be?
It doesn't seem like glDrawElements accepts GL_INT as data type, so maybe the glDrawElements call just fails (which could have easily been checking with some simple glGetError calls for the sake of debugging). Just try GL_UNSIGNED_INT instead (and maybe a UIntBuffer for faces or something similar, if that exists).
Maybe it doesn't even have GL_UNSIGNED_INT in ES and you need 2-byte GL_UNSIGNED_SHORTs, but I'm not sure about that. But you definitely need an unsigned type (what sense does a signed type make for indices anyway? But ok, that's Java). Anyway, some glGetErrors might do wonders here.
Previously I did a Tutorial on OpenGL-ES 1.0. For reference, this can be found here:
SpaceInvaders (it's in german though)
My goal now is to port the game to OpenGL-ES 2.0. So far, I am able to load meshes and textures and render them.
Now I would like to have a simple rectangle as my background with a texture on it. This should be rendered in Ortho-Perspective. I then change to Projection-Perspective and draw a simple box. When I now call setLookAtM(...), I get a blank sceen. Here is the code:
public void onDrawFrame(GL10 gl) {
long currentFrameStart = System.nanoTime();
deltaTime = (currentFrameStart - lastFrameStart) / 1000000000.0f;
lastFrameStart = currentFrameStart;
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(programHandle);
checkGlError("glUseProgram");
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVMatrix");
mLightPosHandle = GLES20.glGetUniformLocation(programHandle, "uLightPos");
mTextureUniformHandle = GLES20.glGetUniformLocation(programHandle, "uTexture");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "aPosition");
mColorHandle = GLES20.glGetAttribLocation(programHandle, "aColor");
mNormalHandle = GLES20.glGetAttribLocation(programHandle, "aNormal");
mTextureCoordinateHandle = GLES20.glGetAttribLocation
(programHandle,"aTexCoordinate");
Matrix.setIdentityM(mLightModelMatrix, 0);
Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0,
mLightPosInModelSpace, 0);
Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);
Matrix.orthoM(mProjectionMatrix, 0, -width / 2, width / 2, -height / 2, height / 2,
0, 100);
drawBackground();
GLES20.glEnable(GLES20.GL_CULL_FACE);
Matrix.setIdentityM(mProjectionMatrix, 0);
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);
Matrix.setLookAtM(mViewMatrix, 0, 0, 6, 2, 0, 0, -4, 0, 1, 0);
drawBlock();
}
Here the drawBackground method:
private void drawBackground() {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundTextureHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.setIdentityM(mProjectionMatrix, 0);
mBackgroundPositions.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT,
false, 0, mBackgroundPositions);
GLES20.glEnableVertexAttribArray(mPositionHandle);
mBackgroundColors.position(0);
GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false,
0, mBackgroundColors);
GLES20.glEnableVertexAttribArray(mColorHandle);
mBackgroundNormals.position(0);
GLES20.glVertexAttribPointer(mNormalHandle, NORMAL_DATA_SIZE, GLES20.GL_FLOAT,
false, 0, mBackgroundNormals);
GLES20.glEnableVertexAttribArray(mNormalHandle);
mBackgroundTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORD_DATA_SIZE,
GLES20.GL_FLOAT, false, 0, mBackgroundTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1],
mLightPosInEyeSpace[2]);
ShortBuffer buf =
ByteBuffer.allocateDirect(12).order(ByteOrder.nativeOrder()).asShortBuffer();
buf.put(new short[] {0, 1, 2, 0, 2, 3});
buf.position(0);
// Draw the rectangle.
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, buf);
checkGlError("glDrawArrays");
}
And finally the drawBlock method:
private void drawBlocks() {
GLES20.glUseProgram(colorProgramHandle);
checkGlError("glUseProgram");
mMVPMatrixHandle = GLES20.glGetUniformLocation(colorProgramHandle, "uMVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(colorProgramHandle, "uMVMatrix");
mLightPosHandle = GLES20.glGetUniformLocation(colorProgramHandle, "uLightPos");
mTextureUniformHandle = GLES20.glGetUniformLocation(colorProgramHandle, "uTexture");
mPositionHandle = GLES20.glGetAttribLocation(colorProgramHandle, "aPosition");
mColorHandle = GLES20.glGetAttribLocation(colorProgramHandle, "aColor");
mNormalHandle = GLES20.glGetAttribLocation(colorProgramHandle, "aNormal");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(colorProgramHandle,
"aTexCoordinate");
Matrix.setIdentityM(mProjectionMatrix, 0);
Matrix.setIdentityM(mModelMatrix, 0);
blockMesh.vertexBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT,
false, 0, blockMesh.vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
blockMesh.colorBuffer.position(0);
GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false,
0, blockMesh.colorBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
blockMesh.normalBuffer.position(0);
GLES20.glVertexAttribPointer(mNormalHandle, NORMAL_DATA_SIZE, GLES20.GL_FLOAT,
false, 0, blockMesh.normalBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
// This multiplies the view matrix by the model matrix, and stores the result in the
MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the
result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1],
mLightPosInEyeSpace[2]);
// Draw the cube.
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT,
blockMesh.indexBuffer);
checkGlError("glDrawElements");
}
I am not sure what I am missing about ortho and projection perspective. Any help is appreciated.
You're wiping the projection matrix as part of drawBlocks. I don't think you want to do that, if you want to draw it using the perspective projection already computed.
...
Matrix.setIdentityM(mProjectionMatrix, 0); <-----
Matrix.setIdentityM(mModelMatrix, 0);
blockMesh.vertexBuffer.position(0);
...