需要源码请点赞关注收藏后评论区留言私信~~~

一、OpenGL ES简介

虽然OpenGL的三维制图功能非常强大,但是它主要为计算机设计的,对于嵌入式设备和移动端设备来说显得比较臃肿,所以业界又设计了专供嵌入式设备的OpenGL ES 它相当于OpenGL的精简版,因为嵌入式设备追求性价比,所以能不做的渲染操作尽量不做,以便优化整体的系统性能

OpenGL ES将所有的渲染过程划分为若干着色器,每个着色器只负责自己这块的渲染操作。

着色器的小程序保存在扩展名为glsl的配置文件中,它采用GLSL语言编写,语法框架类似于C语言

OpenGL ES 2.0与3.0之间的GLSL语法差异如下:

(1)对于ES 3.0来说,glsl文件开头多了一行“#version 300 es”,表示当前小程序使用ES 3.0; (2)取消了ES 2.0的限定符attribute和varying,取而代之的是in和out;

(3)删除了ES 2.0的内置变量gl_FragColor和gl_FragData,改为通过out声明相关输出参数; (4)ES 2.0内置的纹理方法texture2D和texture3D都被新方法texture所取代;

(5)ES 3.0新增修饰符layout,它允许指定变量的位置序号;

二、着色器实战效果

如下图所示 可以在下拉框中选择不同颜色填充

代码如下

Java类

package com.example.threed;import androidx.appcompat.app.AppCompatActivity;import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;import com.example.threed.util.GlUtil;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;public class EsShaderActivity extends AppCompatActivity {private final static String TAG = "EsShaderActivity";private GLSurfaceView glsv_content; // 声明一个图形库表面视图对象private int mProgramId; // 声明glsl小程序的编号private int mStyle; // 三角形样式// 三角形的顶点坐标数组private float mCoordArray[] = { // 默认按逆时针方向顺序绘制0.0f, 0.622008459f, 0.0f,   // 顶-0.5f, -0.311004243f, 0.0f,   // 左底0.5f, -0.311004243f, 0.0f    // 右底};// 三角形的顶点颜色数组(纯色)private float[] mColorPureArray = {1.0f, 0.0f, 0.0f, 1.0f,1.0f, 0.0f, 0.0f, 1.0f,1.0f, 0.0f, 0.0f, 1.0f};// 三角形的顶点颜色数组(彩色)private float[] mColorFullArray = {0.0f, 1.0f, 0.0f, 1.0f,1.0f, 0.0f, 0.0f, 1.0f,0.0f, 0.0f, 1.0f, 1.0f};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_es_shader);showEsVersion(); // 显示OpenGL ES的版本号initStyleSpinner(); // 初始化样式下拉框glsv_content = findViewById(R.id.glsv_content);// 声明使用OpenGL ES的版本号为3.0。使用ES30方法之前务必指定版本号glsv_content.setEGLContextClientVersion(3);// 给OpenGL的表面视图注册三维图形的渲染器glsv_content.setRenderer(new ShaderRender());// 设置渲染模式(关闭自动刷新)glsv_content.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);}// 显示OpenGL ES的版本号private void showEsVersion() {ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);ConfigurationInfo info = am.getDeviceConfigurationInfo();String versionDesc = String.format("%08X", info.reqGlEsVersion);String versionCode = String.format("%d.%d", Integer.parseInt(versionDesc)/10000,Integer.parseInt(versionDesc)%10000);Toast.makeText(this, "系统的OpenGL ES版本号为"+versionCode, Toast.LENGTH_SHORT).show();}// 初始化样式下拉框private void initStyleSpinner() {ArrayAdapter<String> styleAdapter = new ArrayAdapter<>(this,R.layout.item_select, styleArray);Spinner sp_style = findViewById(R.id.sp_style);sp_style.setPrompt("请选择三角形样式");sp_style.setAdapter(styleAdapter);sp_style.setOnItemSelectedListener(new StyleSelectedListener());sp_style.setSelection(0);}private String[] styleArray = { "只画线条", "绘制纯色表面", "绘制彩色表面" };class StyleSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {mStyle = arg2;glsv_content.requestRender(); // 主动请求渲染操作}public void onNothingSelected(AdapterView<?> arg0) {}}// 定义一个三维图形的渲染器private class ShaderRender implements GLSurfaceView.Renderer {// 在表面创建时触发@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 设置白色背景。0.0f相当于00,1.0f相当于FFGLES30.glClearColor(1f, 1f, 1f, 1);// 初始化着色器mProgramId = GlUtil.initShaderProgram(EsShaderActivity.this, "shader_vertex.glsl", "shader_fragment.glsl");}// 在表面变更时触发@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {GLES30.glViewport(0, 0, width, height); // 设置输出屏幕大小// 开启剔除操作。开启之后才能调用glCullFace方法禁止光照、阴影和颜色等效果,以消除不必要的渲染计算。GLES30.glEnable(GLES30.GL_CULL_FACE);}// 执行框架绘制动作@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕和深度缓存GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);GLES30.glLineWidth(3); // 指定线宽drawTriangle(); // 绘制三角形}}// 绘制三角形private void drawTriangle() {FloatBuffer vertexBuffer = GlUtil.getFloatBuffer(mCoordArray);FloatBuffer colorBuffer;if (mStyle == 2) { // 绘制彩色表面colorBuffer = GlUtil.getFloatBuffer(mColorFullArray);} else { // 绘制纯色表面colorBuffer = GlUtil.getFloatBuffer(mColorPureArray);}// 获取顶点着色器的vPosition位置(来自shader_vertex.glsl)int positionLoc = GLES30.glGetAttribLocation(mProgramId, "vPosition");// 获取片段着色器的vColor位置(来自shader_vertex.glsl)int colorLoc = GLES30.glGetAttribLocation(mProgramId, "inColor");GLES30.glEnableVertexAttribArray(positionLoc); // 启用顶点属性数组GLES30.glEnableVertexAttribArray(colorLoc); // 启用顶点属性数组// 指定顶点属性数组的位置信息GLES30.glVertexAttribPointer(positionLoc, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);// 指定顶点属性数组的颜色信息GLES30.glVertexAttribPointer(colorLoc, 4, GLES30.GL_FLOAT, false, 0, colorBuffer);if (mStyle == 0) { // 只绘制线条// 绘制物体的轮廓线条GLES30.glDrawArrays(GLES30.GL_LINE_LOOP, 0, mCoordArray.length/3);} else { // 也绘制表面// 绘制物体的轮廓表面GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, mCoordArray.length/3);}GLES30.glDisableVertexAttribArray(colorLoc); // 禁用顶点属性数组GLES30.glDisableVertexAttribArray(positionLoc); // 禁用顶点属性数组}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="right"android:text="三角形样式:"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_style"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:spinnerMode="dialog" /></LinearLayout><!-- 注意这里要使用控件的全路径android.opengl.GLSurfaceView --><android.opengl.GLSurfaceViewandroid:id="@+id/glsv_content"android:layout_width="match_parent"android:layout_height="400dp" /></LinearLayout>

 创作不易 觉得有帮助请点赞关注收藏~~~

【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)相关推荐

  1. 【Android App】给三维的地球仪贴上动物贴纸实战(附源码和演示 超详细必看)

    需要源码和图片集请点赞关注收藏后评论区留言~~~ 一.纹理贴图 给三维物体穿衣服的动作,通常叫做给三维图形贴图,更专业地说叫纹理渲染. 渲染纹理的过程主要由三大项操作组成,分别说明如下: (1)启用纹 ...

  2. 【Android App】利用自带的人脸检测器和OpenCV检测人脸讲解及实战(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~~ 一.利用人脸检测器识别人脸 对于简单的人脸识别操作,Android已经提供了专门的识别工具,名叫人脸检测器FaceDetector,部分常用方法如下 F ...

  3. 【Android App】定位导航GPS中开启手机定位功能讲解及实战(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.开启定位功能 手机定位分为卫星定位和网络定位两大类. (1)卫星定位 卫星定位服务由几个全球卫星导航系统提供. 卫星定位的原理是根据多颗卫星与导航芯片 ...

  4. 【Android App】人脸识别中借助摄像头和OpenCV实时检测人脸讲解及实战(附源码和演示 超详细)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.借助摄像头实时检测人脸 与Android自带的人脸检测器相比,OpenCV具备更强劲的人脸识别功能,它可以通过摄像头实时检测人脸,实时检测的预览空 ...

  5. 【Android App】实战项目之仿拼多多的直播带货(附源码和演示 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 近年来电商业态发生了不小的改变,传统的电商平台把商品分门别类,配上精美的图文说明供消费者挑选,新潮的电商平台则请来明星网红,开启直播秀向广大粉丝推销商品, ...

  6. 【Android App】人脸识别中扫描识别二维码实战解析(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.扫描识别二维码 不仅可以利用zxing库生成二维码,同样利用zxing库可以扫描二维码并解析得到原始文本,此时除了给build.gradle添加如下一 ...

  7. 【Android App】实战项目之仿微信的视频通话(附源码和演示 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 虽然手机出现许多年了,它具备的功能也越来越丰富,但是最基本的通话功能几乎没有变化.从前使用固定电话的时候,通话就是听声音:如今使用最新的智能手机,通话仍旧 ...

  8. 【Android App】获取照片里的位置信息及使用全球卫星导航系统(GNSS)获取位置实战(附源码和演示 超详细)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.获取照片里的位置信息 手机拍摄的相片还保存着时间.地点.镜头参数等信息,这些信息由相片接口工具ExifInterface管理,它的常用方法说明如下 ...

  9. 【Android App】实战项目之仿微信的附近的人(附源码和演示 超详细)

    需要全部源码请点赞关注收藏后评论区留言私信~~~ 艺术家常说"距离产生美",其实距离近才是优势,谁不希望自己的工作事少钱多离家近呢?不光是工作,像租房买房.恋爱交友,大家都希望找个 ...

最新文章

  1. 复旦 计算机 学硕 延毕,研究生招考呈现新趋势:非全日制招生遇冷 延期毕业现象越发明显...
  2. 65 Airflow组成部分的概念介绍
  3. python polar contour_Python将2darray的最后一行和第二列添加到最后位置 - Polar Contour图...
  4. python中random是什么意思_Python代码中的“importrandom”是什么意思?
  5. 验证视图状态 MAC 失败 的解决办法
  6. 我的Python成长之路---第六天---Python基础(18)---2016年2月20日(晴)
  7. MS SQL 不常用但却十分有用的一些语法
  8. ASP.NET 2.0与SQL Express 2005在迁移到Windows 2003时发生数据库为只读的错误
  9. 【模式识别】Fisher线性判别实验报告之MATLAB仿真
  10. 软件与软件工程的概念
  11. 【LeetCode - 123】买卖股票的最佳时机 III
  12. @async 如何返回list_图解 Await 和 Async
  13. 【百度地图API】如何批量转换为百度经纬度
  14. 微课|中学生可以这样学Python(5.5.3节):字符串格式化2
  15. 华为魔术手机拆机图解_华为荣耀20进水不开机
  16. django系列8.3--django中间件实现登录验证(1)
  17. [译] 第二天:AngularJS - 认识AngularJS
  18. Windows平台release版本内存泄漏检查办法
  19. godot读写本地文件
  20. 文件名 绝对路径与相对路径

热门文章

  1. python写剧情文字游戏_python 简单文字游戏代码
  2. 双绞线的两种接法和选择
  3. Go复合数据类型学习总结
  4. 如何在linux中后台运行R
  5. java 字符串第一个_java 截取字符串第一个字符
  6. SparkFun ATMEGA32U4 Breakout 编译流程
  7. 成都职业技术学院计算机应用技术分数线,成都职业技术学院
  8. Superfetch Prefetch
  9. 淘集集秒杀活动需要隐身上架链接吗?
  10. ARM架构与x86架构的区别