/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.mediaeffects; import android.opengl.GLES20; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; public class TextureRenderer { private int mProgram; private int mTexSamplerHandle; private int mTexCoordHandle; private int mPosCoordHandle; private FloatBuffer mTexVertices; private FloatBuffer mPosVertices; private int mViewWidth; private int mViewHeight; private int mTexWidth; private int mTexHeight; private static final String VERTEX_SHADER = "attribute vec4 a_position;\n" + "attribute vec2 a_texcoord;\n" + "varying vec2 v_texcoord;\n" + "void main() {\n" + " gl_Position = a_position;\n" + " v_texcoord = a_texcoord;\n" + "}\n"; private static final String FRAGMENT_SHADER = "precision mediump float;\n" + "uniform sampler2D tex_sampler;\n" + "varying vec2 v_texcoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" + "}\n"; private static final float[] TEX_VERTICES = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; private static final float[] POS_VERTICES = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f }; private static final int FLOAT_SIZE_BYTES = 4; public void init() { // Create program mProgram = GLToolbox.createProgram(VERTEX_SHADER, FRAGMENT_SHADER); // Bind attributes and uniforms mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "tex_sampler"); mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord"); mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position"); // Setup coordinate buffers mTexVertices = ByteBuffer.allocateDirect( TEX_VERTICES.length * FLOAT_SIZE_BYTES) .order(ByteOrder.nativeOrder()).asFloatBuffer(); mTexVertices.put(TEX_VERTICES).position(0); mPosVertices = ByteBuffer.allocateDirect( POS_VERTICES.length * FLOAT_SIZE_BYTES) .order(ByteOrder.nativeOrder()).asFloatBuffer(); mPosVertices.put(POS_VERTICES).position(0); } public void tearDown() { GLES20.glDeleteProgram(mProgram); } public void updateTextureSize(int texWidth, int texHeight) { mTexWidth = texWidth; mTexHeight = texHeight; computeOutputVertices(); } public void updateViewSize(int viewWidth, int viewHeight) { mViewWidth = viewWidth; mViewHeight = viewHeight; computeOutputVertices(); } public void renderTexture(int texId) { // Bind default FBO GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); // Use our shader program GLES20.glUseProgram(mProgram); GLToolbox.checkGlError("glUseProgram"); // Set viewport GLES20.glViewport(0, 0, mViewWidth, mViewHeight); GLToolbox.checkGlError("glViewport"); // Disable blending GLES20.glDisable(GLES20.GL_BLEND); // Set the vertex attributes GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mTexVertices); GLES20.glEnableVertexAttribArray(mTexCoordHandle); GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mPosVertices); GLES20.glEnableVertexAttribArray(mPosCoordHandle); GLToolbox.checkGlError("vertex attribute setup"); // Set the input texture GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLToolbox.checkGlError("glActiveTexture"); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId); GLToolbox.checkGlError("glBindTexture"); GLES20.glUniform1i(mTexSamplerHandle, 0); // Draw GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } private void computeOutputVertices() { if (mPosVertices != null) { float imgAspectRatio = mTexWidth / (float)mTexHeight; float viewAspectRatio = mViewWidth / (float)mViewHeight; float relativeAspectRatio = viewAspectRatio / imgAspectRatio; float x0, y0, x1, y1; if (relativeAspectRatio > 1.0f) { x0 = -1.0f / relativeAspectRatio; y0 = -1.0f; x1 = 1.0f / relativeAspectRatio; y1 = 1.0f; } else { x0 = -1.0f; y0 = -relativeAspectRatio; x1 = 1.0f; y1 = relativeAspectRatio; } float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 }; mPosVertices.put(coords).position(0); } } }