package com.tencent.tws.assistant.gaussblur; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import android.content.Context; import android.opengl.GLES20; import android.opengl.Matrix; public class PlaneModel { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Shader private static final String mvshader = "precision mediump float;\n" + "attribute vec3 inVertex;\n" + "attribute vec3 inNormal;\n" + "attribute float inAlpha;\n" + "attribute vec2 inTexCoord;\n" + "uniform mat4 MVPMatrix;\n" + "uniform bool odd;\n" + "uniform float minTextureHeight;\n" + "uniform bool gaussianDone;\n" + "varying vec2 TexCoord;\n" + "varying float alpha;\n" + "void main()\n" + "{\n" + " gl_Position = MVPMatrix * vec4(inVertex, 1.0);\n" + " if(odd)\n" + " TexCoord = inTexCoord;\n" + " else\n" + " {\n" + " TexCoord.x = inTexCoord.x;\n" + " TexCoord.y = 1.0 - inTexCoord.y;\n" + " }\n" + " if(gaussianDone)\n" + " {\n" + " if(TexCoord.y < minTextureHeight)\n" + " TexCoord.y = minTextureHeight;\n" + " }\n" + " alpha = inAlpha;\n" + "}\n"; private static final String mfshader = "precision mediump float;\n" + "uniform sampler2D sTexture;\n" + "uniform bool DrawColor;\n" + "uniform int renderTime;\n" + "uniform int nRadius;\n" + "uniform float textureW;\n" + "uniform float textureH;\n" + "uniform float blurAlpha;\n" + "uniform float luminance;\n" + "varying vec2 TexCoord;\n" + "varying float alpha;\n" + "const float PI = 3.14159265359;\n" + "float Gaussian(float x, float variance)\n" + "{\n" + " return (1.0 / sqrt(2.0 * PI * variance)) * exp(-((x * x) / (2.0 * variance)));\n" + "}\n" + "void main()\n" + "{\n" + " if(DrawColor)\n" + " {\n" + " gl_FragColor = vec4(0.4, 0.8, 0.8, alpha);\n" + " }\n" + " else\n" + " {\n" + " if(renderTime != 0)\n" + " {\n" + " vec4 midColors = vec4(0.0);\n" + " float halfBlurRadius = float(nRadius) / 2.0;\n" + " float std = halfBlurRadius * 0.35;\n" + " std *= std;\n" + " for(int i = 0; i < nRadius; ++i)\n" + " {\n" + " float disCenter = float(i) - halfBlurRadius;\n" + " if(renderTime == 1) // horizontal\n" + " {\n" + " vec2 midTexCoord = TexCoord + vec2(textureW * disCenter, 0.0);\n" + " midColors += texture2D(sTexture, midTexCoord) * Gaussian(disCenter * luminance, std);\n" + " }\n" + " else if(renderTime == 2) // vertial\n" + " {\n" + " vec2 midTexCoord = TexCoord + vec2(0.0, textureH * disCenter);\n" + " midColors += texture2D(sTexture, midTexCoord) * Gaussian(disCenter * luminance, std);\n" + " }\n" + " }\n" + " midColors = clamp(midColors, 0.0, 1.0);\n" + " if(renderTime == 2)\n" + " midColors[3] *= blurAlpha;\n" + " else \n" + " midColors[3] *= 1.0;\n" + " gl_FragColor = midColors;\n" + " }\n" + " else\n" + " {\n" + " mediump vec4 midColors;\n" + " midColors = texture2D(sTexture, TexCoord);\n" + " //midColors[3] *= 1.0;\n" + " gl_FragColor = midColors;\n" + " }\n" + " }\n" + "}\n"; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // define vertex3, every 3 float class Vec3 { private float[] value = new float[3]; public Vec3() { // TODO Auto-generated constructor stub value[0] = value[1] = value[2] = 0.0f; } public Vec3(float x, float y, float z) { value[0] = x; value[1] = y; value[2] = z; } public float[] getValue() { return value; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // define vertex, every vertex contain 1 position, 1 normal, 1 alpha of vertex and texture coordinate class Vertex { public Vec3 position; private Vec3 normal; private float alpha = 0.0f; private float[] txtCoord = new float[2]; public Vertex() { } public Vec3 getPosition() { return position; } public Vec3 getNormal() { return normal; } public float getAlpha() { return alpha; } public float[] getTxtCoord() { return txtCoord; } } public static int getVertexSize() { return ((3 + 3 + 1 + 2) * 4); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Plane's data and functions private Vertex[] m_Vertex = new Vertex[16]; private short[] m_Indexs = new short[6]; private short[] m_borderIndes = new short[48]; private int NumCenter = 0; private int NumBorder = 0; private int[] mVertexbuffer = new int[1]; private int[] mbuffers = new int[2]; private FloatBuffer mPlaneVertexBuffer; private ShortBuffer mCenterBufferIndex; private ShortBuffer mBorderBufferIndex; private int newProgramId = 0; private int attributeVertexHandler = 0; private int attributeNormalHandler = 0; private int attributeAlphaHandler = 0; private int attributeTextureHandler = 0; private int UniformMVPMatrixHandler = 0; private int UniformOddHandler = 0; private int UniformMinTextureHeightHandler = 0; private int UniformGaussianDoneHandler = 0; private int UniformDrawColorHandler = 0; private int UniformRenderTimeHandler = 0; private int UniformRadiusHandler = 0; private int UniformTxtureWHandler = 0; private int UniformTxtureHHandler = 0; private int UniformBlurAlphaHandler = 0; private int UniformLuminanceHandler = 0; private float mMinTexHeight = 0.0f; private int mDrawTime = 0; private int mBlurRadius = 10; private float mTxtWidth = 1.0f; private float mTxtHeight = 1.0f; private float mblurAlpha = 1.0f; private float mLuminance = 1.0f; private boolean mResetting = false; private boolean initIndexVbo = false; private boolean loadShadered = false; void Init(float width, float height) { for(int i = 0; i < 16; ++i) m_Vertex[i] = new Vertex(); float dim = 0.5f; float dimLess = dim * 1.0f; Vec3 normal = new Vec3(0.0f, 1.0f, 0.0f); m_Vertex[0].position = new Vec3(-dim, dim, 0.0f); m_Vertex[1].position = new Vec3(-dimLess, dim, 0.0f); m_Vertex[2].position = new Vec3(dimLess, dim, 0.0f); m_Vertex[3].position = new Vec3(dim, dim, 0.0f); m_Vertex[4].position = new Vec3(-dim, dimLess, 0.0f); m_Vertex[5].position = new Vec3(-dimLess, dimLess, 0.0f); m_Vertex[6].position = new Vec3(dimLess, dimLess, 0.0f); m_Vertex[7].position = new Vec3(dim, -dimLess, 0.0f); m_Vertex[8].position = new Vec3(-dim, -dimLess, 0.0f); m_Vertex[9].position = new Vec3(-dimLess, -dimLess, 0.0f); m_Vertex[10].position = new Vec3(dimLess, -dimLess, 0.0f); m_Vertex[11].position = new Vec3(dim, -dimLess, 0.0f); m_Vertex[12].position = new Vec3(-dim, -dim, 0.0f); m_Vertex[13].position = new Vec3(-dimLess, -dim, 0.0f); m_Vertex[14].position = new Vec3(dimLess, -dim, 0.0f); m_Vertex[15].position = new Vec3(dim, -dim, 0.0f); for (int i = 0; i < 16; ++i) { m_Vertex[i].normal = normal; m_Vertex[i].alpha = 0.0f; m_Vertex[i].txtCoord[0] = m_Vertex[i].position.value[0] + dim; m_Vertex[i].txtCoord[1] = m_Vertex[i].position.value[1] + dim; m_Vertex[i].position.value[0] *= width; m_Vertex[i].position.value[1] *= height; } m_Vertex[5].alpha = 1.0f; m_Vertex[6].alpha = 1.0f; m_Vertex[9].alpha = 1.0f; m_Vertex[10].alpha = 1.0f; if(!initIndexVbo) { for(int row = 0; row < 3; ++row) { for(int col = 0; col < 3; ++col) { int start = (row*4)+col; if(row==1 && col == 1) { m_Indexs[NumCenter++] = (short) (start+1); m_Indexs[NumCenter++] = (short) start; m_Indexs[NumCenter++] = (short) (start+4); m_Indexs[NumCenter++] = (short) (start+1); m_Indexs[NumCenter++] = (short) (start+4); m_Indexs[NumCenter++] = (short) (start+5); } else { m_borderIndes[NumBorder++] = (short) (start+1); m_borderIndes[NumBorder++] = (short) start; m_borderIndes[NumBorder++] = (short) (start+4); m_borderIndes[NumBorder++] = (short) (start+1); m_borderIndes[NumBorder++] = (short) (start+4); m_borderIndes[NumBorder++] = (short) (start+5); } } } m_borderIndes[0] = 1; m_borderIndes[1] = 0; m_borderIndes[2] = 5; m_borderIndes[3] = 0; m_borderIndes[4] = 4; m_borderIndes[5] = 5; //bottom right m_borderIndes[42] = 11; m_borderIndes[43] = 10; m_borderIndes[44] = 15; m_borderIndes[45] = 10; m_borderIndes[46] = 14; m_borderIndes[47] = 15; } createVbo(); } private void createVbo() { ByteBuffer vertexArray = ByteBuffer.allocateDirect(m_Vertex.length * getVertexSize()); vertexArray.order(ByteOrder.nativeOrder()); mPlaneVertexBuffer = vertexArray.asFloatBuffer(); for(int i = 0; i < m_Vertex.length; ++i) { Vertex temp = m_Vertex[i]; mPlaneVertexBuffer.put(temp.getPosition().getValue()); // put position mPlaneVertexBuffer.put(temp.getNormal().getValue()); // put normal mPlaneVertexBuffer.put(temp.getAlpha()); // put alpha mPlaneVertexBuffer.put(temp.getTxtCoord()); // put texture coordinates } mPlaneVertexBuffer.position(0); GLES20.glGenBuffers(1, mVertexbuffer, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexbuffer[0]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mPlaneVertexBuffer.capacity() * 4, mPlaneVertexBuffer, GLES20.GL_STATIC_DRAW); if(!initIndexVbo) { ByteBuffer centerIndex = ByteBuffer.allocateDirect(m_Indexs.length * 2); centerIndex.order(ByteOrder.nativeOrder()); mCenterBufferIndex = centerIndex.asShortBuffer(); mCenterBufferIndex.put(m_Indexs); mCenterBufferIndex.position(0); ByteBuffer borderIndex = ByteBuffer.allocateDirect(m_borderIndes.length * 2); borderIndex.order(ByteOrder.nativeOrder()); mBorderBufferIndex = borderIndex.asShortBuffer(); mBorderBufferIndex.put(m_borderIndes); mBorderBufferIndex.position(0); GLES20.glGenBuffers(2, mbuffers, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mbuffers[0]); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, mCenterBufferIndex.capacity() * 2, mCenterBufferIndex, GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mbuffers[1]); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, mBorderBufferIndex.capacity() * 2, mBorderBufferIndex, GLES20.GL_STATIC_DRAW); initIndexVbo = true; } GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,0); } private static float[] mProjMatrix = new float[16]; private static float[] mViewMatrix = new float[16]; private static float[] mMVPMatrix = new float[16]; public void LoadShader(Context mv) { if(!loadShadered) { // String newVertexShader = ShaderFactory.loadShaderFromAssets("myvshader.sh", mv.getResources()); // String newFragmentShader = ShaderFactory.loadShaderFromAssets("myfshader.sh", mv.getResources()); // newProgramId = ShaderFactory.createPrograme(newVertexShader, newFragmentShader); newProgramId = ShaderFactory.createPrograme(mvshader, mfshader); attributeVertexHandler = GLES20.glGetAttribLocation(newProgramId, "inVertex"); attributeNormalHandler = GLES20.glGetAttribLocation(newProgramId, "inNormal"); attributeAlphaHandler = GLES20.glGetAttribLocation(newProgramId, "inAlpha"); attributeTextureHandler = GLES20.glGetAttribLocation(newProgramId, "inTexCoord"); UniformMVPMatrixHandler = GLES20.glGetUniformLocation(newProgramId, "MVPMatrix"); UniformOddHandler = GLES20.glGetUniformLocation(newProgramId, "odd"); UniformMinTextureHeightHandler = GLES20.glGetUniformLocation(newProgramId, "minTextureHeight"); UniformGaussianDoneHandler = GLES20.glGetUniformLocation(newProgramId, "gaussianDone"); UniformDrawColorHandler = GLES20.glGetUniformLocation(newProgramId, "DrawColor"); UniformRenderTimeHandler = GLES20.glGetUniformLocation(newProgramId, "renderTime"); UniformRadiusHandler = GLES20.glGetUniformLocation(newProgramId, "nRadius"); UniformTxtureWHandler = GLES20.glGetUniformLocation(newProgramId, "textureW"); UniformTxtureHHandler = GLES20.glGetUniformLocation(newProgramId, "textureH"); UniformBlurAlphaHandler = GLES20.glGetUniformLocation(newProgramId, "blurAlpha"); UniformLuminanceHandler = GLES20.glGetUniformLocation(newProgramId, "luminance"); loadShadered = true; } float radio = (float)540 / 960; Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 4, 0, 0, 0, 0, 1, 0); Matrix.frustumM(mProjMatrix, 0, -radio, radio, -1, 1, 1.0f, 10.0f); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mViewMatrix, 0); } public void resetting() { mResetting = false; } public void setMinTextureHeight(float minTV) { mMinTexHeight = minTV; } public void seRenderTimeValue(int time) { mDrawTime = time; } public void setBlurRadiusValue(int BlurRadius) { mBlurRadius = BlurRadius; } public void setTxtureWidth(float tw) { mTxtWidth = 1.0f / tw; } public void setTxtureHeight(float th) { mTxtHeight = 1.0f / th; } public void setBlurAlpha(float blurAlpha) { mblurAlpha = blurAlpha; } public void setBlurLuminance(float lu) { mLuminance = lu; } public void drawPlaneModel(float[] mvpMatrix, boolean hadtexure) { GLES20.glUseProgram(newProgramId); if(mResetting) GLES20.glUniform1i(UniformOddHandler, 1); else { GLES20.glUniform1i(UniformOddHandler, 0); mResetting = true; } if(mDrawTime == 0) // gaussian had done, can be change texture size GLES20.glUniform1i(UniformGaussianDoneHandler, 1); else GLES20.glUniform1i(UniformGaussianDoneHandler, 0); GLES20.glUniform1f(UniformMinTextureHeightHandler, mMinTexHeight); GLES20.glUniform1i(UniformRenderTimeHandler, mDrawTime); GLES20.glUniform1i(UniformRadiusHandler, mBlurRadius); GLES20.glUniform1f(UniformTxtureWHandler, mTxtWidth); GLES20.glUniform1f(UniformTxtureHHandler, mTxtHeight); GLES20.glUniform1f(UniformBlurAlphaHandler, mblurAlpha); GLES20.glUniform1f(UniformLuminanceHandler, mLuminance); final int stride = getVertexSize(); // GLES20.glEnable(GLES20.GL_BLEND); // GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexbuffer[0]); GLES20.glUniformMatrix4fv(UniformMVPMatrixHandler, 1, false, mvpMatrix, 0); if(!hadtexure) GLES20.glUniform1i(UniformDrawColorHandler, 1); else GLES20.glUniform1i(UniformDrawColorHandler, 0); GLES20.glEnableVertexAttribArray(attributeVertexHandler); GLES20.glEnableVertexAttribArray(attributeNormalHandler); GLES20.glEnableVertexAttribArray(attributeAlphaHandler); GLES20.glEnableVertexAttribArray(attributeTextureHandler); GLES20.glVertexAttribPointer(attributeVertexHandler, 3, GLES20.GL_FLOAT, false, stride, 0); GLES20.glVertexAttribPointer(attributeNormalHandler, 3, GLES20.GL_FLOAT, false, stride, (3 * 4)); GLES20.glVertexAttribPointer(attributeAlphaHandler, 1, GLES20.GL_FLOAT, false, stride, (6 * 4)); GLES20.glVertexAttribPointer(attributeTextureHandler, 2, GLES20.GL_FLOAT, false, stride, (7 * 4)); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mbuffers[0]); GLES20.glDrawElements(GLES20.GL_TRIANGLES, mCenterBufferIndex.capacity(), GLES20.GL_UNSIGNED_SHORT, 0); // GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mbuffers[1]); // GLES20.glDrawElements(GLES20.GL_TRIANGLES, mBorderBufferIndex.capacity(), GLES20.GL_UNSIGNED_SHORT, 0); GLES20.glDisableVertexAttribArray(attributeVertexHandler); GLES20.glDisableVertexAttribArray(attributeNormalHandler); GLES20.glDisableVertexAttribArray(attributeAlphaHandler); GLES20.glDisableVertexAttribArray(attributeTextureHandler); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,0); GLES20.glDisable(GLES20.GL_BLEND); } public static float[] getViewMatrix() { return mViewMatrix; } public static float[] getProjectionMatrix() { return mProjMatrix; } public void destroy() { NumCenter = 0; NumBorder = 0; initIndexVbo = false; loadShadered = false; GLES20.glDeleteProgram(newProgramId); newProgramId = 0; } }