public GLPicture(BitmapRegionLoader bitmapRegionLoader, int maxHeight) { if (bitmapRegionLoader == null || maxHeight == 0) { return; } mHasContent = true; mVertexBuffer = GLUtil.newFloatBuffer(mVertices.length); mTextureCoordsBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES); int originalWidth = bitmapRegionLoader.getWidth(); int originalHeight = bitmapRegionLoader.getHeight(); int sampleSize = 1; while (originalHeight / (sampleSize << 1) > maxHeight) { sampleSize <<= 1; } mWidth = originalWidth / sampleSize; mHeight = originalHeight / sampleSize; mTileSize = Math.min(512, sMaxTextureSize); int unsampledTileSize = mTileSize * sampleSize; int leftoverHeight = originalHeight % unsampledTileSize; // Load m x n textures mCols = mWidth / (mTileSize + 1) + 1; mRows = mHeight / (mTileSize + 1) + 1; mTextureHandles = new int[mCols * mRows]; Bitmap tileBitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888); Rect rect = new Rect(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = sampleSize; options.inBitmap = tileBitmap; for (int y = 0; y < mRows; y++) { for (int x = 0; x < mCols; x++) { rect.set( x * unsampledTileSize, (mRows - y - 1) * unsampledTileSize, (x + 1) * unsampledTileSize, (mRows - y) * unsampledTileSize); // The bottom tiles must be full tiles for drawing, so only allow edge tiles // at the top if (leftoverHeight > 0) { rect.offset(0, -unsampledTileSize + leftoverHeight); } rect.intersect(0, 0, originalWidth, originalHeight); Bitmap useBitmap = bitmapRegionLoader.decodeRegion(rect, options); mTextureHandles[y * mCols + x] = GLUtil.loadTexture(useBitmap); if (useBitmap != tileBitmap) { useBitmap.recycle(); } } } }
private void render() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); engine.Render(); int error = glGetError(); if (error != GL_NO_ERROR) System.out.println("Error: " + GLUtil.getErrorString(error)); glfwSwapBuffers(window); }
public void destroy() { if (mTextureHandles != null) { GLES20.glDeleteTextures(mTextureHandles.length, mTextureHandles, 0); GLUtil.checkGlError("Destroy picture"); mTextureHandles = null; } }
public static void initGl() { // Initialize shaders and create/link program int vertexShaderHandle = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE); int fragShaderHandle = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE); sProgramHandle = GLUtil.createAndLinkProgram(vertexShaderHandle, fragShaderHandle, null); sAttribPositionHandle = GLES20.glGetAttribLocation(sProgramHandle, "aPosition"); sAttribTextureCoordsHandle = GLES20.glGetAttribLocation(sProgramHandle, "aTexCoords"); sUniformMVPMatrixHandle = GLES20.glGetUniformLocation(sProgramHandle, "uMVPMatrix"); sUniformTextureHandle = GLES20.glGetUniformLocation(sProgramHandle, "uTexture"); sUniformAlphaHandle = GLES20.glGetUniformLocation(sProgramHandle, "uAlpha"); // Compute max texture size int[] maxTextureSize = new int[1]; GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); sMaxTextureSize = maxTextureSize[0]; }
public GLPicture(Bitmap bitmap) { if (bitmap == null) { return; } mTileSize = sMaxTextureSize; mHasContent = true; mVertexBuffer = GLUtil.newFloatBuffer(mVertices.length); mTextureCoordsBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES); mWidth = bitmap.getWidth(); mHeight = bitmap.getHeight(); int leftoverHeight = mHeight % mTileSize; // Load m x n textures mCols = mWidth / (mTileSize + 1) + 1; mRows = mHeight / (mTileSize + 1) + 1; mTextureHandles = new int[mCols * mRows]; if (mCols == 1 && mRows == 1) { mTextureHandles[0] = GLUtil.loadTexture(bitmap); } else { Rect rect = new Rect(); for (int y = 0; y < mRows; y++) { for (int x = 0; x < mCols; x++) { rect.set( x * mTileSize, (mRows - y - 1) * mTileSize, (x + 1) * mTileSize, (mRows - y) * mTileSize); // The bottom tiles must be full tiles for drawing, so only allow edge tiles // at the top if (leftoverHeight > 0) { rect.offset(0, -mTileSize + leftoverHeight); } rect.intersect(0, 0, mWidth, mHeight); Bitmap subBitmap = Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height()); mTextureHandles[y * mCols + x] = GLUtil.loadTexture(subBitmap); subBitmap.recycle(); } } } }
public void draw(float[] mvpMatrix, float alpha) { if (!mHasContent) { return; } // Add program to OpenGL ES environment GLES20.glUseProgram(sProgramHandle); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(sUniformMVPMatrixHandle, 1, false, mvpMatrix, 0); GLUtil.checkGlError("glUniformMatrix4fv"); // Set up vertex buffer GLES20.glEnableVertexAttribArray(sAttribPositionHandle); GLES20.glVertexAttribPointer( sAttribPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VERTEX_STRIDE_BYTES, mVertexBuffer); // Set up texture stuff GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glUniform1i(sUniformTextureHandle, 0); GLES20.glVertexAttribPointer( sAttribTextureCoordsHandle, COORDS_PER_TEXTURE_VERTEX, GLES20.GL_FLOAT, false, TEXTURE_VERTEX_STRIDE_BYTES, mTextureCoordsBuffer); GLES20.glEnableVertexAttribArray(sAttribTextureCoordsHandle); // Set the alpha GLES20.glUniform1f(sUniformAlphaHandle, alpha); // Draw tiles for (int y = 0; y < mRows; y++) { for (int x = 0; x < mCols; x++) { // Pass in the vertex information mVertices[0] = mVertices[3] = mVertices[9] = Math.min(-1 + 2f * x * mTileSize / mWidth, 1); // left mVertices[1] = mVertices[10] = mVertices[16] = Math.min(-1 + 2f * (y + 1) * mTileSize / mHeight, 1); // top mVertices[6] = mVertices[12] = mVertices[15] = Math.min(-1 + 2f * (x + 1) * mTileSize / mWidth, 1); // right mVertices[4] = mVertices[7] = mVertices[13] = Math.min(-1 + 2f * y * mTileSize / mHeight, 1); // bottom mVertexBuffer.put(mVertices); mVertexBuffer.position(0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureHandles[y * mCols + x]); GLUtil.checkGlError("glBindTexture"); // Draw the two triangles GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertices.length / COORDS_PER_VERTEX); } } GLES20.glDisableVertexAttribArray(sAttribPositionHandle); GLES20.glDisableVertexAttribArray(sAttribTextureCoordsHandle); }
@Override public boolean initObject() { if (imageResId != 0) { vertexCount = coordinates.length / COORDS_PER_VERTEX; ByteBuffer buff = ByteBuffer.allocateDirect(coordinates.length * 4); buff.order(ByteOrder.nativeOrder()); vBuffer = buff.asFloatBuffer(); vBuffer.put(coordinates); vBuffer.position(0); ByteBuffer drawBuff = ByteBuffer.allocateDirect(drawOrder.length * 2); drawBuff.order(ByteOrder.nativeOrder()); drawBuffer = drawBuff.asShortBuffer(); drawBuffer.put(drawOrder); drawBuffer.position(0); ByteBuffer textBuff = ByteBuffer.allocateDirect(textureCoordinates.length * 4); textBuff.order(ByteOrder.nativeOrder()); textureBuffer = textBuff.asFloatBuffer(); textureBuffer.put(textureCoordinates); textureBuffer.position(0); // Prepare shaders and OpenGL program vertexShaderHandle = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); fragShaderHandle = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); programHandle = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(programHandle, vertexShaderHandle); // add the vertex shader to program GLES20.glAttachShader(programHandle, fragShaderHandle); // add the fragment shader to program GLES20.glBindAttribLocation(programHandle, 0, "aPosition"); GLES20.glBindAttribLocation(programHandle, 1, "aTexCoordinate"); GLES20.glLinkProgram(programHandle); // create OpenGL program executables final int[] status = new int[1]; GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, status, 0); if (status[0] == 0) { Log.e( "GLSprite", "Error compiling OpenGL program: " + GLES20.glGetProgramInfoLog(programHandle)); GLES20.glDeleteProgram(programHandle); programHandle = 0; throw new RuntimeException("Error creating OpenGL program."); } textureDataHandle = GLUtil.loadTexture(mCanvas.getView().getContext(), imageResId); // get handle to vertex shader's aPosition member positionHandle = GLES20.glGetAttribLocation(programHandle, "aPosition"); textureCoordinateHandle = GLES20.glGetAttribLocation(programHandle, "aTexCoordinate"); mModelMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVMatrix"); GLES20Renderer.checkGLError("glUniformLocation uMVMatrix"); mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "uMVPMatrix"); GLES20Renderer.checkGLError("glUniformLocation uMVPMatrix"); textureUniformHandle = GLES20.glGetUniformLocation(programHandle, "u_Texture"); GLES20Renderer.checkGLError("glUniformLocation u_Texture"); GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); initialized = true; return true; } else { return false; } }
@Override public void onDrawFrame(GL10 gl) { try { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); if (positionBuffer != null) { gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, positionBuffer); } synchronized (camera) { PointF c = getCameraLocation(); if (c == camera) { GLU.gluLookAt(gl, c.x, c.y, zoom, camera.x, camera.y, 0.0f, 0.0f, 1.0f, 0.0f); } else { GLU.gluLookAt( gl, c.x, c.y, zoom / followHeightFactor, camera.x, camera.y, -FOLLOW_LOOK_AT_HEIGHT, 0.0f, 0.0f, -1.0f); } } synchronized (areas) { for (SimArea area : areas.values()) { if (!onlySeenAreas || seenAreas.contains(area.getID())) { area.draw(gl); } } } if (drawWalls) { synchronized (walls) { for (SimWall wall : walls) { wall.draw(gl); } } synchronized (wallTops) { for (SimWallTop wallTop : wallTops) { wallTop.draw(gl); } } } synchronized (objects) { for (SimObject obj : objects.values()) { obj.draw(gl); } } synchronized (robots) { for (SimRobot robot : robots.values()) { robot.draw(gl, drawRedLidar, drawBlueLidar, drawYellowWaypoint); } } synchronized (lastFloorTouch) { GLUtil.drawRect( gl, lastFloorTouch.x - 0.05f, lastFloorTouch.y - 0.25f, -0.01f, 0.1f, 0.5f, GLUtil.GRAY); GLUtil.drawRect( gl, lastFloorTouch.x - 0.25f, lastFloorTouch.y - 0.05f, -0.01f, 0.5f, 0.1f, GLUtil.GRAY); } } catch (ConcurrentModificationException e) { e.printStackTrace(); } }