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