class Light3D { public float[] pos; public float[] color; } class Material3D { public float[] ambient; public float[] diffuse; } class FaceMat { public Material3D material; public int faces; public short[] indexBuffer; public int bufOffset; } class Object3D { public ArrayList<FaceMat> faceMats; public int vertCount; public int indCount; public int glVertices; public int glIndices; public float[] vertexBuffer; } public class Scene3D { public ArrayList<Material3D> materials; public ArrayList<Object3D> objects; public ArrayList<Light3D> lights; public float[] ambient; }
int[] genbuf = new int[1]; private int createBuffer(float[] buffer) { FloatBuffer floatBuf = ByteBuffer.allocateDirect(buffer.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); floatBuf.put(buffer); floatBuf.position(0); GLES20.glGenBuffers(1, genbuf, 0); int glBuf = genbuf[0]; GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, glBuf); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.length * 4, floatBuf, GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); return glBuf; } ... int i, num = scene.objects.size(); for (i = 0; i < num; i++) { Object3D obj = scene.objects.get(i); obj.glVertices = createBuffer(obj.vertexBuffer); GLES20.glGenBuffers(1, genbuf, 0); obj.glIndices = genbuf[0]; GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, obj.glIndices); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, obj.indCount * 2, null, GLES20.GL_STATIC_DRAW); int k, mats = obj.faceMats.size(); for (k = 0; k < mats; k++) { FaceMat mat = obj.faceMats.get(k); ShortBuffer indBuf = ByteBuffer.allocateDirect(mat.indexBuffer.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer(); indBuf.put(mat.indexBuffer); indBuf.position(0); GLES20.glBufferSubData(GLES20.GL_ELEMENT_ARRAY_BUFFER, mat.bufOffset * 2, mat.indexBuffer.length * 2, indBuf); } GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); }
private final String vertexShaderCode = "precision mediump float;\n" + "uniform mat4 uMVPMatrix;\n" + "uniform mat4 uMVMatrix;\n" + "uniform mat3 uNMatrix;\n" + "uniform vec4 uAmbient;\n" + "uniform vec4 uDiffuse;\n" + "const int MaxLights = 8;\n" + "struct LightSourceParameters {\n" + " bool enabled;\n" + " vec4 color;\n" + " vec3 position;\n" + "};\n" + "uniform LightSourceParameters uLight[MaxLights];\n" + "attribute vec4 vPosition;\n" + "attribute vec3 vNormal;\n" + "varying vec4 FrontColor;\n" + "vec4 light_point_view_local(vec3 epos, vec3 normal, int idx);\n" + "void main() {\n" + " gl_Position = uMVPMatrix * vPosition;\n" + " vec4 epos = uMVMatrix * vPosition;\n" + " vec3 normal =uNMatrix * vNormal;\n" + " vec4 vcolor = uAmbient;\n" + " int i;\n" + " for (i = 0; i < MaxLights; i++) {\n" + " if (uLight[i].enabled) {\n" + " vcolor += light_point_view_local(epos.xyz, normal, i);\n" + " }\n" + " }\n" + " FrontColor = clamp(vcolor, 0.0, 1.0);\n" + "}\n" + "vec4 light_point_view_local(vec3 epos, vec3 normal, int idx) {\n" + " vec3 vert2light = uLight[idx].position - epos;\n" + " vec3 ldir = normalize(vert2light);\n" + " float NdotL = dot(normal, ldir);\n" + " vec4 outCol = vec4(0.0, 0.0, 0.0, 1.0);\n" + " if (NdotL > 0.0) {\n" + " outCol = uLight[idx].color * uDiffuse * NdotL;\n" + " }\n" + " return outCol;\n" + "}\n"; private final String fragmentShaderCode = "precision mediump float;\n" + "varying vec4 FrontColor;\n" + "void main() {\n" + " gl_FragColor = FrontColor;\n" + "}\n"; private int mProgram; private int maPosition; private int maNormal; private int muMVPMatrix; private int muMVMatrix; private int muNMatrix; private int muAmbient; private int muDiffuse; private int[] muLightOn = new int[8]; private int[] muLightPos = new int[8]; private int[] muLightCol = new int[8];
private int loadShader(int type, String shaderCode) { int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); Log.i("Shader", GLES20.glGetShaderInfoLog(shader)); return shader; } private int Compile(String vs, String fs) { int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vs); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fs); int prog = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(prog, vertexShader); // add the vertex shader to program GLES20.glAttachShader(prog, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(prog); // creates OpenGL program executables return prog; } ... mProgram = Compile(vertexShaderCode, fragmentShaderCode); // get handle to the vertex shader's vPosition member maPosition = GLES20.glGetAttribLocation(mProgram, "vPosition"); maNormal = GLES20.glGetAttribLocation(mProgram, "vNormal"); muMVPMatrix = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); muMVMatrix = GLES20.glGetUniformLocation(mProgram, "uMVMatrix"); muNMatrix = GLES20.glGetUniformLocation(mProgram, "uNMatrix"); muAmbient = GLES20.glGetUniformLocation(mProgram, "uAmbient"); muDiffuse = GLES20.glGetUniformLocation(mProgram, "uDiffuse"); int i; for (i = 0; i < 8; i++) { muLightOn[i] = GLES20.glGetUniformLocation(mProgram, String.format("uLight[%d].enabled", i)); muLightPos[i] = GLES20.glGetUniformLocation(mProgram, String.format("uLight[%d].position", i)); muLightCol[i] = GLES20.glGetUniformLocation(mProgram, String.format("uLight[%d].color", i)); }
private void DrawScene() { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glUseProgram(mProgram); GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glEnable(GLES20.GL_DEPTH_TEST); Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, mMMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix, 0); // Apply a ModelView Projection transformation GLES20.glUniformMatrix4fv(muMVPMatrix, 1, false, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(muMVMatrix, 1, false, mMVMatrix, 0); int i, j, num; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) mNMatrix[i*3 + j] = mMVMatrix[i*4 + j]; GLES20.glUniformMatrix3fv(muNMatrix, 1, false, mNMatrix, 0); num = min(scene.lights.size(), 8); float[] eyepos = new float[3]; for (i = 0; i < num; i++) { Light3D light = scene.lights.get(i); for (j = 0; j < 3; j++) { eyepos[j] = mVMatrix[4*3 + j]; for (k = 0; k < 3; k++) eyepos[j] += light.pos[k] * mVMatrix[k*4 + j]; } GLES20.glUniform1i(muLightOn[i], 1); GLES20.glUniform3fv(muLightPos[i], 1, eyepos, 0); GLES20.glUniform4fv(muLightCol[i], 1, light.color, 0); } for (i = num; i < 8; i++) GLES20.glUniform1i(muLightOn[i], 0); // Prepare the triangle data GLES20.glEnableVertexAttribArray(maPosition); GLES20.glEnableVertexAttribArray(maNormal); num = scene.objects.size(); for (i = 0; i < num; i++) { Object3D obj = scene.objects.get(i); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, obj.glVertices); GLES20.glVertexAttribPointer(maPosition, 3, GLES20.GL_FLOAT, false, 24, 0); GLES20.glVertexAttribPointer(maNormal, 3, GLES20.GL_FLOAT, false, 24, 12); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, obj.glIndices); int mats = obj.faceMats.size(); for (j = 0; j < mats; j++) { FaceMat mat = obj.faceMats.get(j); for (int k = 0; k < 3; k++) mAmbient[k] = mat.material.ambient[k] * scene.ambient[k]; GLES20.glUniform4fv(muAmbient, 1, mAmbient, 0); GLES20.glUniform4fv(muDiffuse, 1, mat.material.diffuse, 0); GLES20.glDrawElements(GLES20.GL_TRIANGLES, mat.indexBuffer.length, GLES20.GL_UNSIGNED_SHORT, mat.bufOffset * 2); } GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); } GLES20.glDisableVertexAttribArray(maPosition); GLES20.glDisableVertexAttribArray(maNormal); }
private final String quadVS = "precision mediump float;\n" + "attribute vec4 vPosition;\n" + "attribute vec4 vTexCoord0;\n" + "varying vec4 TexCoord0;\n" + "void main() {\n" + " gl_Position = vPosition;\n" + " TexCoord0 = vTexCoord0;\n" + "}\n"; private final String quadFS = "precision mediump float;\n" + "uniform sampler2D uTexture0;\n" + "varying vec4 TexCoord0;\n" + "void main() {\n" + " gl_FragColor = texture2D(uTexture0, TexCoord0.xy);\n" + "}\n"; private int mQProgram; private int maQPosition; private int maQTexCoord; private int muQTexture; private int glQuadVB; ... final float quadv[] = { -1, 1, 0, 0, 1, -1, -1, 0, 0, 0, 1, 1, 0, 1, 1, 1, -1, 0, 1, 0 }; glQuadVB = createBuffer(quadv); mQProgram = Compile(quadVS, quadFS); maQPosition = GLES20.glGetAttribLocation(mQProgram, "vPosition"); maQTexCoord = GLES20.glGetAttribLocation(mQProgram, "vTexCoord0"); muQTexture = GLES20.glGetUniformLocation(mQProgram, "uTexture0");
private int filterBuf1; private int filterBuf2; private int renderTex1; private int renderTex2; public int scrWidth; public int scrHeight; public int texWidth; public int texHeight; ... private int makeRenderTarget(int width, int height, int[] handles) { GLES20.glGenTextures(1, genbuf, 0); int renderTex = genbuf[0]; GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); IntBuffer texBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder()).asIntBuffer(); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer); GLES20.glGenRenderbuffers(1, genbuf, 0); int depthBuf = genbuf[0]; GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthBuf); GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, width, height); GLES20.glGenFramebuffers(1, genbuf, 0); int frameBuf = genbuf[0]; GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuf); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex, 0); GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthBuf); int res = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); handles[0] = frameBuf; handles[1] = renderTex; return res; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { ratio = (float) width / height; int[] handles = new int[2]; scrWidth = width; scrHeight = height; texWidth = 256; texHeight = 256; makeRenderTarget(texWidth, texHeight, handles); filterBuf1 = handles[0]; renderTex1 = handles[1]; makeRenderTarget(texWidth, texHeight, handles); filterBuf2 = handles[0]; renderTex2 = handles[1]; }
private void setRenderTexture(int frameBuf, int texture) { if (frameBuf == 0) GLES20.glViewport(0, 0, scrWidth, scrHeight); else GLES20.glViewport(0, 0, texWidth, texHeight); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuf); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); } private void DrawQuad() { GLES20.glUseProgram(mQProgram); GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, glQuadVB); GLES20.glEnableVertexAttribArray(maQPosition); GLES20.glVertexAttribPointer(maQPosition, 3, GLES20.GL_FLOAT, false, 20, 0); GLES20.glEnableVertexAttribArray(maQTexCoord); GLES20.glVertexAttribPointer(maQTexCoord, 2, GLES20.GL_FLOAT, false, 20, 12); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glUniform1i(muQTexture, 0); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLES20.glDisableVertexAttribArray(maQPosition); GLES20.glDisableVertexAttribArray(maQTexCoord); }
class FilterKernelElement { public float du; public float dv; public float coef; } ... float mOffsets[] = new float[4]; private float[] pix_mult = new float[4]; private FilterKernelElement[] mvGaussian1D = new FilterKernelElement[44]; private float mfPerTexelWidth; private float mfPerTexelHeight; ... float cent = (mvGaussian1D.length - 1.0f) / 2.0f, radi; for (int u = 0; u < mvGaussian1D.length; u++) { FilterKernelElement el = mvGaussian1D[u] = new FilterKernelElement(); el.du = ((float)u) - cent - 0.1f; el.dv = 0.0f; radi = (el.du * el.du) / (cent * cent); el.coef = (float)((0.24/Math.exp(radi*0.18)) + 0.41/Math.exp(radi*4.5)); } float rr = texWidth / (float) texHeight; float rs = rr / ratio; mfPerTexelWidth = rs / texWidth; mfPerTexelHeight = 1.0f / texHeight;
private final String gaussVS = "precision mediump float;\n" + "attribute vec4 vPosition;\n" + "attribute vec4 vTexCoord0;\n" + "uniform vec4 uTexOffset0;\n" + "uniform vec4 uTexOffset1;\n" + "uniform vec4 uTexOffset2;\n" + "uniform vec4 uTexOffset3;\n" + "varying vec4 TexCoord0;\n" + "varying vec4 TexCoord1;\n" + "varying vec4 TexCoord2;\n" + "varying vec4 TexCoord3;\n" + "void main() {\n" + " gl_Position = vPosition;\n" + " TexCoord0 = vTexCoord0 + uTexOffset0;\n" + " TexCoord1 = vTexCoord0 + uTexOffset1;\n" + " TexCoord2 = vTexCoord0 + uTexOffset2;\n" + " TexCoord3 = vTexCoord0 + uTexOffset3;\n" + "}\n"; private final String gaussFS = "precision mediump float;\n" + "uniform sampler2D uTexture0;\n" + "uniform vec4 uTexCoef0;\n" + "uniform vec4 uTexCoef1;\n" + "uniform vec4 uTexCoef2;\n" + "uniform vec4 uTexCoef3;\n" + "varying vec4 TexCoord0;\n" + "varying vec4 TexCoord1;\n" + "varying vec4 TexCoord2;\n" + "varying vec4 TexCoord3;\n" + "void main() {\n" + " vec4 c0 = texture2D(uTexture0, TexCoord0.xy);\n" + " vec4 c1 = texture2D(uTexture0, TexCoord1.xy);\n" + " vec4 c2 = texture2D(uTexture0, TexCoord2.xy);\n" + " vec4 c3 = texture2D(uTexture0, TexCoord3.xy);\n" + " gl_FragColor = uTexCoef0 * c0 + uTexCoef1 * c1 + uTexCoef2 * c2 + uTexCoef3 * c3;\n" + "}\n"; private int mGProgram; private int maGPosition; private int maGTexCoord; private int muGTexture; private int[] muGTexCoef = new int[4]; private int[] muGTexOffset = new int[4]; ... mGProgram = Compile(gaussVS, gaussFS); maGPosition = GLES20.glGetAttribLocation(mGProgram, "vPosition"); maGTexCoord = GLES20.glGetAttribLocation(mGProgram, "vTexCoord0"); muGTexture = GLES20.glGetUniformLocation(mGProgram, "uTexture0"); for (i = 0; i < 4; i++) { muGTexOffset[i] = GLES20.glGetUniformLocation(mGProgram, String.format("uTexOffset%d", i)); muGTexCoef[i] = GLES20.glGetUniformLocation(mGProgram, String.format("uTexCoef%d", i)); }
private void DrawGauss(boolean invert) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glUseProgram(mGProgram); GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, glQuadVB); GLES20.glEnableVertexAttribArray(maGPosition); GLES20.glVertexAttribPointer(maGPosition, 3, GLES20.GL_FLOAT, false, 20, 0); GLES20.glEnableVertexAttribArray(maGTexCoord); GLES20.glVertexAttribPointer(maGTexCoord, 2, GLES20.GL_FLOAT, false, 20, 12); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glUniform1i(muGTexture, 0); int i, n, k; for (i = 0; i < mvGaussian1D.length; i += 4) { for (n = 0; n < 4; n++) { FilterKernelElement pE = mvGaussian1D[i + n]; for (k = 0; k < 4; k++) pix_mult[k] = pE.coef * 0.10f; GLES20.glUniform4fv(muGTexCoef[n], 1, pix_mult, 0); mOffsets[0] = mfPerTexelWidth * (invert ? pE.dv : pE.du); mOffsets[1] = mfPerTexelHeight * (invert ? pE.du : pE.dv); GLES20.glUniform4fv(muGTexOffset[n], 1, mOffsets, 0); } GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } GLES20.glDisableVertexAttribArray(maGPosition); GLES20.glDisableVertexAttribArray(maGTexCoord); }
@Override public void onDrawFrame(GL10 arg0) { setRenderTexture(filterBuf1, 0); DrawScene(); GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE); setRenderTexture(filterBuf2, renderTex1); DrawGauss(false); setRenderTexture(filterBuf1, renderTex2); DrawGauss(true); GLES20.glDisable(GLES20.GL_BLEND); setRenderTexture(0, 0); DrawScene(); GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE); setRenderTexture(0, renderTex1); DrawQuad(); GLES20.glDisable(GLES20.GL_BLEND); }
for (i = 0; i < uLights; i++)
Source: https://habr.com/ru/post/144831/
All Articles