1*90c8c64dSAndroid Build Coastguard Worker /* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker 17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.mediaeffects; 18*90c8c64dSAndroid Build Coastguard Worker 19*90c8c64dSAndroid Build Coastguard Worker import android.opengl.GLES20; 20*90c8c64dSAndroid Build Coastguard Worker 21*90c8c64dSAndroid Build Coastguard Worker import java.nio.ByteBuffer; 22*90c8c64dSAndroid Build Coastguard Worker import java.nio.ByteOrder; 23*90c8c64dSAndroid Build Coastguard Worker import java.nio.FloatBuffer; 24*90c8c64dSAndroid Build Coastguard Worker 25*90c8c64dSAndroid Build Coastguard Worker public class TextureRenderer { 26*90c8c64dSAndroid Build Coastguard Worker 27*90c8c64dSAndroid Build Coastguard Worker private int mProgram; 28*90c8c64dSAndroid Build Coastguard Worker private int mTexSamplerHandle; 29*90c8c64dSAndroid Build Coastguard Worker private int mTexCoordHandle; 30*90c8c64dSAndroid Build Coastguard Worker private int mPosCoordHandle; 31*90c8c64dSAndroid Build Coastguard Worker 32*90c8c64dSAndroid Build Coastguard Worker private FloatBuffer mTexVertices; 33*90c8c64dSAndroid Build Coastguard Worker private FloatBuffer mPosVertices; 34*90c8c64dSAndroid Build Coastguard Worker 35*90c8c64dSAndroid Build Coastguard Worker private int mViewWidth; 36*90c8c64dSAndroid Build Coastguard Worker private int mViewHeight; 37*90c8c64dSAndroid Build Coastguard Worker 38*90c8c64dSAndroid Build Coastguard Worker private int mTexWidth; 39*90c8c64dSAndroid Build Coastguard Worker private int mTexHeight; 40*90c8c64dSAndroid Build Coastguard Worker 41*90c8c64dSAndroid Build Coastguard Worker private static final String VERTEX_SHADER = 42*90c8c64dSAndroid Build Coastguard Worker "attribute vec4 a_position;\n" + 43*90c8c64dSAndroid Build Coastguard Worker "attribute vec2 a_texcoord;\n" + 44*90c8c64dSAndroid Build Coastguard Worker "varying vec2 v_texcoord;\n" + 45*90c8c64dSAndroid Build Coastguard Worker "void main() {\n" + 46*90c8c64dSAndroid Build Coastguard Worker " gl_Position = a_position;\n" + 47*90c8c64dSAndroid Build Coastguard Worker " v_texcoord = a_texcoord;\n" + 48*90c8c64dSAndroid Build Coastguard Worker "}\n"; 49*90c8c64dSAndroid Build Coastguard Worker 50*90c8c64dSAndroid Build Coastguard Worker private static final String FRAGMENT_SHADER = 51*90c8c64dSAndroid Build Coastguard Worker "precision mediump float;\n" + 52*90c8c64dSAndroid Build Coastguard Worker "uniform sampler2D tex_sampler;\n" + 53*90c8c64dSAndroid Build Coastguard Worker "varying vec2 v_texcoord;\n" + 54*90c8c64dSAndroid Build Coastguard Worker "void main() {\n" + 55*90c8c64dSAndroid Build Coastguard Worker " gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" + 56*90c8c64dSAndroid Build Coastguard Worker "}\n"; 57*90c8c64dSAndroid Build Coastguard Worker 58*90c8c64dSAndroid Build Coastguard Worker private static final float[] TEX_VERTICES = { 59*90c8c64dSAndroid Build Coastguard Worker 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f 60*90c8c64dSAndroid Build Coastguard Worker }; 61*90c8c64dSAndroid Build Coastguard Worker 62*90c8c64dSAndroid Build Coastguard Worker private static final float[] POS_VERTICES = { 63*90c8c64dSAndroid Build Coastguard Worker -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f 64*90c8c64dSAndroid Build Coastguard Worker }; 65*90c8c64dSAndroid Build Coastguard Worker 66*90c8c64dSAndroid Build Coastguard Worker private static final int FLOAT_SIZE_BYTES = 4; 67*90c8c64dSAndroid Build Coastguard Worker init()68*90c8c64dSAndroid Build Coastguard Worker public void init() { 69*90c8c64dSAndroid Build Coastguard Worker // Create program 70*90c8c64dSAndroid Build Coastguard Worker mProgram = GLToolbox.createProgram(VERTEX_SHADER, FRAGMENT_SHADER); 71*90c8c64dSAndroid Build Coastguard Worker 72*90c8c64dSAndroid Build Coastguard Worker // Bind attributes and uniforms 73*90c8c64dSAndroid Build Coastguard Worker mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, 74*90c8c64dSAndroid Build Coastguard Worker "tex_sampler"); 75*90c8c64dSAndroid Build Coastguard Worker mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord"); 76*90c8c64dSAndroid Build Coastguard Worker mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position"); 77*90c8c64dSAndroid Build Coastguard Worker 78*90c8c64dSAndroid Build Coastguard Worker // Setup coordinate buffers 79*90c8c64dSAndroid Build Coastguard Worker mTexVertices = ByteBuffer.allocateDirect( 80*90c8c64dSAndroid Build Coastguard Worker TEX_VERTICES.length * FLOAT_SIZE_BYTES) 81*90c8c64dSAndroid Build Coastguard Worker .order(ByteOrder.nativeOrder()).asFloatBuffer(); 82*90c8c64dSAndroid Build Coastguard Worker mTexVertices.put(TEX_VERTICES).position(0); 83*90c8c64dSAndroid Build Coastguard Worker mPosVertices = ByteBuffer.allocateDirect( 84*90c8c64dSAndroid Build Coastguard Worker POS_VERTICES.length * FLOAT_SIZE_BYTES) 85*90c8c64dSAndroid Build Coastguard Worker .order(ByteOrder.nativeOrder()).asFloatBuffer(); 86*90c8c64dSAndroid Build Coastguard Worker mPosVertices.put(POS_VERTICES).position(0); 87*90c8c64dSAndroid Build Coastguard Worker } 88*90c8c64dSAndroid Build Coastguard Worker tearDown()89*90c8c64dSAndroid Build Coastguard Worker public void tearDown() { 90*90c8c64dSAndroid Build Coastguard Worker GLES20.glDeleteProgram(mProgram); 91*90c8c64dSAndroid Build Coastguard Worker } 92*90c8c64dSAndroid Build Coastguard Worker updateTextureSize(int texWidth, int texHeight)93*90c8c64dSAndroid Build Coastguard Worker public void updateTextureSize(int texWidth, int texHeight) { 94*90c8c64dSAndroid Build Coastguard Worker mTexWidth = texWidth; 95*90c8c64dSAndroid Build Coastguard Worker mTexHeight = texHeight; 96*90c8c64dSAndroid Build Coastguard Worker computeOutputVertices(); 97*90c8c64dSAndroid Build Coastguard Worker } 98*90c8c64dSAndroid Build Coastguard Worker updateViewSize(int viewWidth, int viewHeight)99*90c8c64dSAndroid Build Coastguard Worker public void updateViewSize(int viewWidth, int viewHeight) { 100*90c8c64dSAndroid Build Coastguard Worker mViewWidth = viewWidth; 101*90c8c64dSAndroid Build Coastguard Worker mViewHeight = viewHeight; 102*90c8c64dSAndroid Build Coastguard Worker computeOutputVertices(); 103*90c8c64dSAndroid Build Coastguard Worker } 104*90c8c64dSAndroid Build Coastguard Worker renderTexture(int texId)105*90c8c64dSAndroid Build Coastguard Worker public void renderTexture(int texId) { 106*90c8c64dSAndroid Build Coastguard Worker // Bind default FBO 107*90c8c64dSAndroid Build Coastguard Worker GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 108*90c8c64dSAndroid Build Coastguard Worker 109*90c8c64dSAndroid Build Coastguard Worker // Use our shader program 110*90c8c64dSAndroid Build Coastguard Worker GLES20.glUseProgram(mProgram); 111*90c8c64dSAndroid Build Coastguard Worker GLToolbox.checkGlError("glUseProgram"); 112*90c8c64dSAndroid Build Coastguard Worker 113*90c8c64dSAndroid Build Coastguard Worker // Set viewport 114*90c8c64dSAndroid Build Coastguard Worker GLES20.glViewport(0, 0, mViewWidth, mViewHeight); 115*90c8c64dSAndroid Build Coastguard Worker GLToolbox.checkGlError("glViewport"); 116*90c8c64dSAndroid Build Coastguard Worker 117*90c8c64dSAndroid Build Coastguard Worker // Disable blending 118*90c8c64dSAndroid Build Coastguard Worker GLES20.glDisable(GLES20.GL_BLEND); 119*90c8c64dSAndroid Build Coastguard Worker 120*90c8c64dSAndroid Build Coastguard Worker // Set the vertex attributes 121*90c8c64dSAndroid Build Coastguard Worker GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 122*90c8c64dSAndroid Build Coastguard Worker 0, mTexVertices); 123*90c8c64dSAndroid Build Coastguard Worker GLES20.glEnableVertexAttribArray(mTexCoordHandle); 124*90c8c64dSAndroid Build Coastguard Worker GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false, 125*90c8c64dSAndroid Build Coastguard Worker 0, mPosVertices); 126*90c8c64dSAndroid Build Coastguard Worker GLES20.glEnableVertexAttribArray(mPosCoordHandle); 127*90c8c64dSAndroid Build Coastguard Worker GLToolbox.checkGlError("vertex attribute setup"); 128*90c8c64dSAndroid Build Coastguard Worker 129*90c8c64dSAndroid Build Coastguard Worker // Set the input texture 130*90c8c64dSAndroid Build Coastguard Worker GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 131*90c8c64dSAndroid Build Coastguard Worker GLToolbox.checkGlError("glActiveTexture"); 132*90c8c64dSAndroid Build Coastguard Worker GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId); 133*90c8c64dSAndroid Build Coastguard Worker GLToolbox.checkGlError("glBindTexture"); 134*90c8c64dSAndroid Build Coastguard Worker GLES20.glUniform1i(mTexSamplerHandle, 0); 135*90c8c64dSAndroid Build Coastguard Worker 136*90c8c64dSAndroid Build Coastguard Worker // Draw 137*90c8c64dSAndroid Build Coastguard Worker GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 138*90c8c64dSAndroid Build Coastguard Worker GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 139*90c8c64dSAndroid Build Coastguard Worker GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 140*90c8c64dSAndroid Build Coastguard Worker } 141*90c8c64dSAndroid Build Coastguard Worker computeOutputVertices()142*90c8c64dSAndroid Build Coastguard Worker private void computeOutputVertices() { 143*90c8c64dSAndroid Build Coastguard Worker if (mPosVertices != null) { 144*90c8c64dSAndroid Build Coastguard Worker float imgAspectRatio = mTexWidth / (float)mTexHeight; 145*90c8c64dSAndroid Build Coastguard Worker float viewAspectRatio = mViewWidth / (float)mViewHeight; 146*90c8c64dSAndroid Build Coastguard Worker float relativeAspectRatio = viewAspectRatio / imgAspectRatio; 147*90c8c64dSAndroid Build Coastguard Worker float x0, y0, x1, y1; 148*90c8c64dSAndroid Build Coastguard Worker if (relativeAspectRatio > 1.0f) { 149*90c8c64dSAndroid Build Coastguard Worker x0 = -1.0f / relativeAspectRatio; 150*90c8c64dSAndroid Build Coastguard Worker y0 = -1.0f; 151*90c8c64dSAndroid Build Coastguard Worker x1 = 1.0f / relativeAspectRatio; 152*90c8c64dSAndroid Build Coastguard Worker y1 = 1.0f; 153*90c8c64dSAndroid Build Coastguard Worker } else { 154*90c8c64dSAndroid Build Coastguard Worker x0 = -1.0f; 155*90c8c64dSAndroid Build Coastguard Worker y0 = -relativeAspectRatio; 156*90c8c64dSAndroid Build Coastguard Worker x1 = 1.0f; 157*90c8c64dSAndroid Build Coastguard Worker y1 = relativeAspectRatio; 158*90c8c64dSAndroid Build Coastguard Worker } 159*90c8c64dSAndroid Build Coastguard Worker float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 }; 160*90c8c64dSAndroid Build Coastguard Worker mPosVertices.put(coords).position(0); 161*90c8c64dSAndroid Build Coastguard Worker } 162*90c8c64dSAndroid Build Coastguard Worker } 163*90c8c64dSAndroid Build Coastguard Worker 164*90c8c64dSAndroid Build Coastguard Worker } 165