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