diff --git a/UI/Triangle/README_zh.md b/UI/Triangle/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..4e8cf98221a0b888b88efc74022571f21c453b4a --- /dev/null +++ b/UI/Triangle/README_zh.md @@ -0,0 +1,16 @@ +# OpenGL绘制三角形 + +### 简介 + +OpenGL是一个跨平台的高性能3D渲染API,OpenGL ES是它的嵌入式平台版本。 + +本示例展示了OpenGL ES接口的使用,通过调用相关函数,在坐标系中绘制三角形,并实现逐帧旋转。 + +### 使用说明 + +点击应用,展示三角形以顶点为轴进行旋转。 + +### 约束与限制 + +本示例仅支持在大型系统上运行。 + diff --git a/UI/Triangle/build.gradle b/UI/Triangle/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..65c90323f5b81b1f7427d57785e9121d2e598537 --- /dev/null +++ b/UI/Triangle/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 +ohos { + compileSdkVersion 6 + defaultConfig { + compatibleSdkVersion 6 + } +} + +buildscript { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.5.0' + classpath 'com.huawei.ohos:decctest:1.2.4.1' + } +} + +allprojects { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + } +} diff --git a/UI/Triangle/entry/build.gradle b/UI/Triangle/entry/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..517434f3eb381e298cda2efd84135d9b43285fdb --- /dev/null +++ b/UI/Triangle/entry/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'com.huawei.ohos.hap' +apply plugin: 'com.huawei.ohos.decctest' +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 +ohos { + compileSdkVersion 6 + defaultConfig { + compatibleSdkVersion 6 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testImplementation 'junit:junit:4.13' + ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.200' +} +decc { + supportType = ['html','xml'] +} diff --git a/UI/Triangle/entry/src/main/config.json b/UI/Triangle/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..db5409b1edd997a4ed7e10ea9ca4c1f2dee380c0 --- /dev/null +++ b/UI/Triangle/entry/src/main/config.json @@ -0,0 +1,45 @@ +{ + "app": { + "bundleName": "ohos.samples.triangle", + "version": { + "code": 1000000, + "name": "1.0.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "ohos.samples.triangle", + "name": ".MyApplication", + "mainAbility": "ohos.samples.triangle.MainAbility", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree": false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "ohos.samples.triangle.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ] + } +} \ No newline at end of file diff --git a/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MainAbility.java b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..c1857bfc6fc698581cbab56183e3350b4acb515a --- /dev/null +++ b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MainAbility.java @@ -0,0 +1,13 @@ +package ohos.samples.triangle; + +import ohos.samples.triangle.slice.MainAbilitySlice; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MyApplication.java b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..da3a73b912dd7a3badedc2361aa4133121e90e4e --- /dev/null +++ b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/MyApplication.java @@ -0,0 +1,10 @@ +package ohos.samples.triangle; + +import ohos.aafwk.ability.AbilityPackage; + +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/MainAbilitySlice.java b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..12aee41e138b013dd92e39a45a24718213cd4cf1 --- /dev/null +++ b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/MainAbilitySlice.java @@ -0,0 +1,35 @@ +package ohos.samples.triangle.slice; + +import ohos.agp.components.DirectionalLayout; +import ohos.agp.components.surfaceprovider.SurfaceProvider; +import ohos.samples.triangle.ResourceTable; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; + +public class MainAbilitySlice extends AbilitySlice { + private DirectionalLayout layout; + private Triangle triangle; + private SurfaceProvider provider; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + layout = (DirectionalLayout) findComponentById(ResourceTable.Id_surface_layout); + triangle = new Triangle(this); + provider = triangle.initSliceLayout(); + + layout.addComponent(provider); + triangle.startDraw(); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } +} diff --git a/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Matrix.java b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Matrix.java new file mode 100644 index 0000000000000000000000000000000000000000..f0d2de4f91d021aee77e8ced4e0e5356abb68541 --- /dev/null +++ b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Matrix.java @@ -0,0 +1,265 @@ +package ohos.samples.triangle.slice; + +public class Matrix { + + /** + * multiplyMM Multiplication matrix operation + * + * @param result float[] + * @param resultOffset int + * @param lhs float[] + * @param rhs float[] + */ + public static void multiplyMM(float[] result, int resultOffset, float[] lhs, float[] rhs) { + float[] result1 = new float[result.length - resultOffset]; + float[] lhs1 = new float[lhs.length]; + float[] rhs1 = new float[rhs.length]; + System.arraycopy(result, resultOffset, result1, 0, result1.length); + System.arraycopy(lhs, 0, lhs1, 0, lhs1.length); + System.arraycopy(rhs, 0, rhs1, 0, rhs1.length); + + for (int i=0; i<4; i++) { + float rhsl0 = rhs1[indexOf(i, 0)]; + float ri0 = lhs1[indexOf(0, 0)] * rhsl0; + float ri1 = lhs1[indexOf(0, 1)] * rhsl0; + float ri2 = lhs1[indexOf(0, 2)] * rhsl0; + float ri3 = lhs1[indexOf(0, 3)] * rhsl0; + for (int j=1; j<4; j++) { + float rhslj = rhs1[indexOf(i, j)]; + ri0 += lhs1[indexOf(j, 0)] * rhslj; + ri1 += lhs1[indexOf(j, 1)] * rhslj; + ri2 += lhs1[indexOf(j, 2)] * rhslj; + ri3 += lhs1[indexOf(j, 3)] * rhslj; + } + result1[indexOf(i, 0)] = ri0; + result1[indexOf(i, 1)] = ri1; + result1[indexOf(i, 2)] = ri2; + result1[indexOf(i, 3)] = ri3; + } + System.arraycopy(result1, 0, result, resultOffset, result1.length); + } + + /** + * setRotateM Create a new matrix + * + * @param rm float[] + * @param angle float[] + * @param xx float + * @param yy float + * @param zz float + */ + public static void setRotateM(float[] rm, float angle, float xx, float yy, float zz) { + rm[3] = rm[7] = rm[11] = rm[12] = rm[13] = rm[14] = 0.0f; + rm[15] = 1.0f; + + float angleTemp = (float)(angle * Math.PI / 180.0f); + float ss = (float) Math.sin(angleTemp); + float cc = (float) Math.cos(angleTemp); + + if (xx == 1.0f && yy == 0.0f && zz == 0.0f) { + rmOne(rm, ss , cc); + } else if (xx == 0.0f && yy == 1.0f && zz == 0.0f) { + rmTwo(rm, ss , cc); + } else if (xx == 0.0f && yy == 0.0f && zz == 1.0f) { + rmThree(rm ,ss , cc); + } else { + float len = length(xx, yy, zz); + float xTemp = xx; + float yTemp = yy; + float zTemp = zz; + if (Math.abs(len -1) > 1e-6f) { + float recIpLen = 1 / len; + xTemp = xx * recIpLen; + yTemp = yy * recIpLen; + zTemp = zz * recIpLen; + } + float nc = 1 - cc; + rm[0] = xTemp * xTemp * nc +cc; + + float xy = xTemp * yTemp; + float zs = zTemp * ss; + rm[4] = xy * nc - zs; + float zx = zTemp * xTemp; + float ys = yTemp * ss; + rm[8] = zx * nc + ys; + rm[1] = xy * nc + zs; + rm[5] = yTemp * yTemp * nc + cc; + + float yz = yTemp * zTemp; + float xs = xTemp * ss; + rm[9] = yz * nc - xs; + rm[2] = zx * nc - ys; + rm[6] = yz * nc + xs; + rm[10] = zTemp * zTemp * nc + cc; + } + } + + /** + * rmThree + * + * @param rm float[] + * @param ss float + * @param cc float + */ + private static void rmThree(float[] rm, float ss, float cc) { + rm[0] = cc; + rm[5] = cc; + rm[1] = ss; + rm[4] = -ss; + rm[2] = 0; + rm[6] = 0; + rm[8] = 0; + rm[9] = 0; + rm[10] = 1; + } + + /** + * rmTwo + * + * @param rm float[] + * @param ss float + * @param cc float + */ + private static void rmTwo(float[] rm, float ss, float cc) { + rm[0] = cc; + rm[10] = cc; + rm[8] = ss; + rm[2] = -ss; + rm[1] = 0; + rm[4] = 0; + rm[6] = 0; + rm[9] = 0; + rm[5] = 1; + } + + /** + * rmOne + * + * @param rm float[] + * @param ss float + * @param cc float + */ + private static void rmOne(float[] rm, float ss, float cc) { + rm[5] = cc; + rm[10] = cc; + rm[6] = ss; + rm[9] = -ss; + rm[1] = 0; + rm[2] = 0; + rm[4] = 0; + rm[8] = 0; + rm[0] = 1; + } + + /** + * indexOf + * + * @param i int + * @param j int + * @return int + */ + private static int indexOf(int i, int j) { + return j + 4 * i; + } + + /** + * frustumM Calculate the perspective projection matrix + * + * @param mm float[] + * @param right float + * @param top float + * @param near float + * @param far float + */ + public static void frustumM(float[] mm, float right, float top, float near, float far) { + final float rWidth = 1/(right * 2); + final float rHeight = 1/(top * 2); + mm[0] = 2.0f * (near * rWidth); + mm[5] = 2.0f * (near * rHeight); + mm[8] = 0; + mm[9] = 0; + final float rDepth = 1/(near - far); + mm[10] = (far + near) * rDepth; + mm[14] = 2.0f * (far * near * rDepth); + mm[11] = -1.0f; + mm[1] = 0.0f; + mm[2] = 0.0f; + mm[3] = 0.0f; + mm[4] = 0.0f; + mm[6] = 0.0f; + mm[7] = 0.0f; + mm[12] = 0.0f; + mm[13] = 0.0f; + mm[15] = 0.0f; + } + + /** + * length + * + * @param x float + * @param y float + * @param z float + * @return float + */ + public static float length(float x, float y, float z) { + return (float) Math.sqrt(x * x + y * y + z * z); + } + + /** + * setLookAtM Defining the camera View + * + * @param rm float[] + * @param eyeZ float + * @param centerX float + * @param centerY float + * @param centerZ float + */ + public static void setLookAtM(float[] rm, float eyeZ, float centerX, float centerY, float centerZ) { + float fx = centerX; + float fy = centerY; + float fz = centerZ - eyeZ; + float rlf = 1 / Matrix.length(fx, fy, fz); + fx *= rlf; + fy *= rlf; + fz *= rlf; + + float sx = -fz; + float sy = -fx; + float sz = fx; + float rls = 1 / Matrix.length(sx, sy, sz); + sx *= rls; + sy *= rls; + sz *= rls; + + rm[0] = sx; + rm[1] = sy * fz -sz * fy; + rm[2] = -fx; + rm[3] = 0.0f; + rm[4] = sy; + rm[5] = sz * fx -sx * fz; + rm[6] = -fy; + rm[7] = 0.0f; + rm[8] = sz; + rm[9] = sx * fy - sy * fx; + rm[10] = -fz; + rm[11] = rm[12] = rm[13] = rm[14] = 0.0f; + rm[15] = 1.0f; + translateM(rm, 0, 0, 0, -eyeZ); + } + + /** + * translateM Translation matrix + * + * @param matrix float[] + * @param offset int + * @param x float + * @param y float + * @param z float + */ + public static void translateM(float[] matrix, int offset, float x, float y, float z) { + for (int i = 0; i < 4; i++) { + int pos = offset + i; + matrix[12 + pos] += matrix[pos] * x + matrix[4 + pos] * y + matrix[8 + pos] * z; + } + } +} diff --git a/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Triangle.java b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Triangle.java new file mode 100644 index 0000000000000000000000000000000000000000..9b62664301a05f6868d410508feeb8418d3aa143 --- /dev/null +++ b/UI/Triangle/entry/src/main/java/ohos/samples/triangle/slice/Triangle.java @@ -0,0 +1,458 @@ +package ohos.samples.triangle.slice; + +import ohos.agp.components.surfaceprovider.SurfaceProvider; +import ohos.agp.graphics.SurfaceOps; +import ohos.agp.render.opengl.*; +import ohos.app.Context; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +import java.nio.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class Triangle { + private SCallBacks callBacks; + private boolean stopRun = false; + private final Context mContext; + private SurfaceOps surfaceOps; + + public Triangle(Context context) { + this.mContext = context; + } + + public SurfaceProvider initSliceLayout() { + SurfaceProvider testSurfaceView = new SurfaceProvider(mContext); + if(testSurfaceView.getSurfaceOps().isPresent()){ + surfaceOps = testSurfaceView.getSurfaceOps().get(); + callBacks = new SCallBacks(); + surfaceOps.addCallback(callBacks); + surfaceOps.setKeepScreenOn(true); + } + testSurfaceView.setWidth(1080); + testSurfaceView.setHeight(2000); + + testSurfaceView.pinToZTop(true); + return testSurfaceView; + } + + public void startDraw() { + Runnable requestRunnable = () -> callBacks.onDrawFrame(); + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); + threadPoolExecutor.execute(() -> { + while (!stopRun) { + mContext.getUITaskDispatcher().asyncDispatch(requestRunnable); + } + }); + } + + public void stop() { + stopRun = true; + surfaceOps.removeCallback(callBacks); + } + + class SCallBacks implements SurfaceOps.Callback { + private final HiLogLabel LOG_TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "SCallBacks"); + private EGLDisplay eglDisplay; + private EGLSurface eglSurface; + + private EGLContext eglContext = null; + private EGLConfig eglConfig = null; + + //三角形的3个顶点 + private final float[] CubeCords = new float[]{ + 0f, 0.5f, 0f, + 0.5f, 0f, 0f, + -0.5f, 0f, 0f, + }; + + + private final short[] indices = new short[]{ + 0, 1, 2 + }; + + //三角形的颜色 + private final float[] colors = { + 0f, 0f, 0f, 1f, + 0f, 0f, 0.8f, 1f, + 0f, 0.8f, 0f, 1f, + 0f, 0.8f, 0.8f, 1f, + 0.8f, 0f, 0f, 1f, + 0.8f, 0f, 0.8f, 1f, + 0.8f, 0.8f, 0f, 1f, + 0.8f, 0.8f, 0.8f, 1f, + 0.8f, 0f, 0f, 1f, + 0f, 0.8f, 0f, 1f, + 0f, 0f, 0.8f, 1f, + 0.8f, 0f, 0.8f, 1f, + }; + + //变换矩阵 + private final float[] vPMatrix = new float[16]; + //投影矩阵 + private final float[] projectionMatrix = new float[16]; + //相机矩阵 + private final float[] viewMatrix = new float[16]; + //旋转矩阵 + private final float[] rotationMatrix = new float[16]; + //临时矩阵,用于存放矩阵运算 + private final float[] tempMatrix = new float[16]; + //旋转角度 + private int angle = 0; + private int disWidth = 0; + private int disHeight = 0; + + //顶点着色器 + private int vertexShader = 0; + //片元着色器 + private int fragmentsShader = 0; + private final CharBuffer shaderCode = CharBuffer.allocate(100); + + @Override + public void surfaceCreated(SurfaceOps ops) { + eglDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + return; + } + int[] version = new int[2]; + if (!EGL.eglInitialize(eglDisplay, version, version)) { + return; + } + + int alphaSize = 3; + int depthSize = 3; + int stencilSize = 3; + int renderType = 0x0004; + int[] attributes = new int[] { + EGL.EGL_RED_SIZE, 3, + EGL.EGL_GREEN_SIZE, 3, + EGL.EGL_ALPHA_SIZE, alphaSize, + EGL.EGL_DEPTH_SIZE, depthSize, + EGL.EGL_STENCIL_SIZE, stencilSize, + + EGL.EGL_RENDERABLE_TYPE, renderType, + EGL.EGL_NONE + }; + int[] configNum = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + if(!EGL.eglChooseConfig(eglDisplay, attributes, configs, 1, configNum)){ + return; + } + if (eglConfig == null) { + eglConfig = configs[0]; + } + int[] contextAttr = new int[] { + 0x3098, 2, EGL.EGL_NONE, + }; + eglContext = EGL.eglCreateContext(eglDisplay, eglConfig, EGL.EGL_NO_CONTEXT, contextAttr); + if (eglContext == EGL.EGL_NO_CONTEXT) { + return; + } + + String openVersion = GLES20.glGetString(GLES20.GL_VERSION); + HiLog.info(LOG_TAG, "OpenVersion: " + openVersion); + } + + @Override + public void surfaceChanged(SurfaceOps ops, int format, int width, int height) { + int[] contextAttr = new int[] { + EGL.EGL_NONE + }; + eglSurface = EGL.eglCreateWindowSurface(eglDisplay, eglConfig, ops.getSurface(),contextAttr); + + if (eglSurface == EGL.EGL_NO_SURFACE) { + return; + } + if (!EGL.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { + return; + } + float ratio = (float) width/height; + + //设置投影矩阵 + Matrix.frustumM(projectionMatrix, ratio, 1, 3, 7); + //设置观察点 + Matrix.setLookAtM(viewMatrix, 4f, 0f, 0f, 0f); + + disWidth = width; + disHeight = height; + onDrawFrame(); + } + + @Override + public void surfaceDestroyed(SurfaceOps ops) { + EGL.eglMakeCurrent(eglDisplay, null, null, null); + EGL.eglDestroySurface(eglDisplay, eglSurface); + EGL.eglDestroyContext(eglDisplay, eglContext); + EGL.eglTerminate(eglDisplay); + stop(); + } + + public void onDrawFrame() { + //启动深度测试 + GLES20.glEnable(GLES20.GL_DEPTH_TEST); + //设置显示范围 + GLES20.glViewport(0,0, disWidth, disHeight); + //设置背景,清除颜色 + GLES20.glClearColor(0.8f,0.8f,0.8f, 1.0f); + //执行背景清除 + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); + //将ourColor设置为我们输入的颜色 + String vertexShaderCode = "uniform mat4 uMatrix;" + + "attribute vec4 aPos;" + "attribute vec4 aColor;" + "attribute float aSize;" + + "varying vec4 ourColor;" + "void main() {" + + " gl_Position = uMatrix * aPos;" + "ourColor = aColor;" + + "}"; + // + String fragmentShaderCode = "precision mediump float;" + "varying vec4 ourColor;" + + "void main() {" + "gl_FragColor = ourColor;" + + "}"; + + int program = createProgram(vertexShaderCode, fragmentShaderCode); + //使用着色器程序 + GLES20.glUseProgram(program); + //获取属性变量位置 + int sizeHandle = GLES20.glGetAttribLocation(program, "aSize"); + GLES20.glVertexAttrib1f(sizeHandle, 1.0f); + + int positionHandle = GLES20.glGetAttribLocation(program, "aPos"); + //启用通用顶点属性数据 + GLES20.glEnableVertexAttribArray(positionHandle); + FloatBuffer vertexBuffer = createFloatBuffer(CubeCords); + //指定顶点的属性数据 + GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false,3*4, vertexBuffer); + + int colorHandle = GLES20.glGetAttribLocation(program, "aColor"); + GLES20.glEnableVertexAttribArray(colorHandle); + FloatBuffer colorBuffer = createFloatBuffer(colors); + + GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false,4*4, colorBuffer); + + //获取统一变量位置 + int matrixHandle = GLES20.glGetUniformLocation(program, "uMatrix"); + + //创建一个旋转矩阵 + Matrix.setRotateM(rotationMatrix, angle, 0, 1, 0); + + //矩阵计算 + Matrix.multiplyMM(tempMatrix, 0, projectionMatrix, viewMatrix); + + Matrix.multiplyMM(vPMatrix, 0, tempMatrix, rotationMatrix); + + //将视图转换器传递给着色器 + GLES20.glUniformMatrix4fv(matrixHandle, 1, false, vPMatrix); + + //索引法绘制三角形 + ShortBuffer indicesBuffer = createShortBuffer(indices); + GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, indices.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer); + + //更新缓冲区显示到屏幕 + if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) { + return; + } + //禁用通用顶点属性数组 + GLES20.glDisableVertexAttribArray(positionHandle); + GLES20.glDisableVertexAttribArray(colorHandle); + + //禁用深度测试 + GLES20.glDisable(GLES20.GL_DEPTH_TEST); + angle += 2; + checkParameter(program); + + } + + /** + * checkParameter + * + * @param program int + */ + private void checkParameter(int program) { + //获取清除深度缓冲区的值 + int[] params = new int[1]; + + GLES20.glGetIntegerv(0x0B73, params); + HiLog.info(LOG_TAG, "glGetInteger: DEPTH_CLEAR = " + params[0]); + + boolean[] paramsb = new boolean[1]; + GLES20.glGetBooleanv(GLES20.GL_DEPTH_TEST, paramsb); + HiLog.info(LOG_TAG, "glGetInteger: DEPTH_CLEAR = " + (paramsb[0] ? "true":"false")); + + //获取顶点着色器数字格式的范围和精度 + IntBuffer range = IntBuffer.allocate(2); + IntBuffer precision = IntBuffer.allocate(2); + GLES20.glGetShaderPrecisionFormat(GLES20.GL_VERTEX_SHADER, 0x8DF1, range, precision); + HiLog.info(LOG_TAG, "Range=[" + range.get(1) + "], precision=" + precision.get(0)); + + //从着色器对象返回源代码字符串 + IntBuffer length = IntBuffer.allocate(4); + + GLES20.glGetShaderSource(GLES20.GL_FRAGMENT_SHADER, shaderCode.capacity(), length, shaderCode); + HiLog.info(LOG_TAG, "glGetShaderSource: length=" + length.get(0) + "shaderCode=" + shaderCode.toString()); + + int bufSize = 256; + int[] size = new int[1]; + int[] len = new int[1]; + int[] type = new int[1]; + byte[] name = new byte[bufSize]; + int[] counts = new int[1]; + + //从程序对象返回状态的统一变量 + GLES20.glGetProgramiv(program, 0x8B86, counts); + if (counts[0] > 0) { + for (int idx = 0; idx < counts[0]; idx++) { + GLES20.glGetActiveUniform(program, idx, bufSize, len, size, type, name); + } + } + + //从程序对象返回活动状态的属性变化 + GLES20.glGetProgramiv(program, 0x8B89, counts); + if (counts[0] > 0) { + for (int idx = 0; idx < counts[0]; idx++) { + GLES20.glGetActiveAttrib(program, idx, bufSize, len, size, type, name); + } + } + + float[] paramsf = new float[2]; + + GLES20.glGetFloatv(0x846E, paramsf); + HiLog.info(LOG_TAG, "glGetFloat: min = " + paramsf[0] + "max =" + paramsf[1]); + GLES20.glLineWidth(2.0f); + + GLES20.glFlush(); + GLES20.glFinish(); + + GLES20.glReleaseShaderCompiler(); + + //从程序对象中分离着色器对象 + GLES20.glDetachShader(program, vertexShader); + GLES20.glDetachShader(program, fragmentsShader); + } + + /** + * createProgram + * + * @param vertexSource String + * @param fragmentSource String + * @return int + */ + private int createProgram(String vertexSource, String fragmentSource) { + vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); + if (vertexShader == 0) { + return 0; + } + boolean isShader = GLES20.glIsShader(vertexShader); + HiLog.info(LOG_TAG, "Is vertexShader" + (isShader ? "True" : "False")); + fragmentsShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); + if (fragmentsShader == 0) { + return 0; + } + isShader = GLES20.glIsShader(fragmentsShader); + HiLog.info(LOG_TAG, "Is fragmentsShader" + (isShader ? "True" : "False")); + + //创建程序对象 + int program = GLES20.glCreateProgram(); + + if (program == 0) { + HiLog.error(LOG_TAG, "Could not create program"); + return 0; + } + + boolean isProgram = GLES20.glIsProgram(program); + HiLog.info(LOG_TAG, "Is program" + (isProgram ? "True" : "False")); + + //将着色器对象附加到程序对象 + GLES20.glAttachShader(program, vertexShader); + + GLES20.glAttachShader(program, fragmentsShader); + + GLES20.glLinkProgram(program); + + GLES20.glDeleteShader(vertexShader); + + GLES20.glDeleteShader(fragmentsShader); + + final int[] compiled = new int[1]; + GLES20.glGetProgramiv(program,GLES20.GL_LINK_STATUS, compiled); + if (compiled[0] != GLES20.GL_TRUE) { + StringBuffer programInfo = new StringBuffer(); + + GLES20.glGetProgramInfoLog(program, 100, null, programInfo); + + HiLog.error(LOG_TAG, "Could not link program: " + programInfo.toString()); + + GLES20.glDeleteProgram(program); + return 0; + } + GLES20.glValidateProgram(program); + final int[] validateStatus = new int[1]; + + GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, validateStatus); + if (validateStatus[0] != GLES20.GL_TRUE) { + StringBuffer programInfoLog = new StringBuffer(); + GLES20.glGetProgramInfoLog(program, 100, null, programInfoLog); + HiLog.error(LOG_TAG, "validate program failed: " + programInfoLog.toString()); + } + return program; + } + + /** + * loadShader + * + * @param type int + * @param shaderCode String + * @return int + */ + private int loadShader(int type, String shaderCode) { + int shader = GLES20.glCreateShader(type); + HiLog.info(LOG_TAG, "loadShader: " + type + ", ret =" + shader); + String[] source = { shaderCode }; + IntBuffer length = IntBuffer.allocate(0); + + //加载代码到着色器对象 + GLES20.glShaderSource(shader, 1, source, length); + + //编译着色器对象 + GLES20.glCompileShader(shader); + int[] compiled = new int[1]; + int max = 100; + + //从着色器对象获取编译状态信息 + GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled); + if (compiled[0] == 0) { + StringBuffer shaderInfoLog = new StringBuffer(); + GLES20.glGetShaderInfoLog(shader, max, null,shaderInfoLog); + GLES20.glDeleteShader(shader); + shader = 0; + } + return shader; + } + } + + /** + * createShortBuffer + * + * @param arr short[] + * @return ShortBuffer + */ + public static ShortBuffer createShortBuffer(short[] arr) { + ByteBuffer buffer = ByteBuffer.allocateDirect(arr.length * 2); + buffer.order(ByteOrder.nativeOrder()); + ShortBuffer sb = buffer.asShortBuffer(); + sb.put(arr).position(0); + return sb; + } + + /** + * createFloatBuffer + * + * @param arr float[] + * @return FloatBuffer + */ + public static FloatBuffer createFloatBuffer(float[] arr) { + ByteBuffer buffer = ByteBuffer.allocateDirect(arr.length * 4); + buffer.order(ByteOrder.nativeOrder()); + FloatBuffer fb = buffer.asFloatBuffer(); + fb.put(arr).position(0); + return fb; + } +} diff --git a/UI/Triangle/entry/src/main/resources/base/element/string.json b/UI/Triangle/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6e532c6b419e85665655857636cef6d6f48429aa --- /dev/null +++ b/UI/Triangle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Triangle" + }, + { + "name": "mainability_description", + "value": "Draw triangles using OpenGL ES" + } + ] +} diff --git a/UI/Triangle/entry/src/main/resources/base/graphic/background_ability_main.xml b/UI/Triangle/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0c0a3df480fa387a452b9c40ca191cc918a3fc0 --- /dev/null +++ b/UI/Triangle/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/UI/Triangle/entry/src/main/resources/base/layout/ability_main.xml b/UI/Triangle/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..655091e796db6c34063919bf381b2f1ad4e5d2f1 --- /dev/null +++ b/UI/Triangle/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/UI/Triangle/entry/src/main/resources/base/media/icon.png b/UI/Triangle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/UI/Triangle/entry/src/main/resources/base/media/icon.png differ diff --git a/UI/Triangle/entry/src/main/resources/en/element/string.json b/UI/Triangle/entry/src/main/resources/en/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6e532c6b419e85665655857636cef6d6f48429aa --- /dev/null +++ b/UI/Triangle/entry/src/main/resources/en/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Triangle" + }, + { + "name": "mainability_description", + "value": "Draw triangles using OpenGL ES" + } + ] +} diff --git a/UI/Triangle/entry/src/main/resources/zh/element/string.json b/UI/Triangle/entry/src/main/resources/zh/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..139a142d9777c3cd306465a9f65558dea461a310 --- /dev/null +++ b/UI/Triangle/entry/src/main/resources/zh/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "三角形" + }, + { + "name": "mainability_description", + "value": "使用 OpenGL_ES 绘制三角形" + } + ] +} \ No newline at end of file diff --git a/UI/Triangle/screenshots/device/screen.png b/UI/Triangle/screenshots/device/screen.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0edcdf43d4db7ecbfb40782c4357aa4df087fb Binary files /dev/null and b/UI/Triangle/screenshots/device/screen.png differ diff --git a/UI/Triangle/settings.gradle b/UI/Triangle/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..4773db73233a570c2d0c01a22e75321acfbf7a07 --- /dev/null +++ b/UI/Triangle/settings.gradle @@ -0,0 +1 @@ +include ':entry'