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

这篇具有很好参考价值的文章主要介绍了【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

一、OpenGL ES简介

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

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

【Android App】三维投影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,它允许指定变量的位置序号;

二、着色器实战效果

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

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

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

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

 代码如下

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
    };

    @Override
    protected 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 {
        // 在表面创建时触发
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // 设置白色背景。0.0f相当于00,1.0f相当于FF
            GLES30.glClearColor(1f, 1f, 1f, 1);
            // 初始化着色器
            mProgramId = GlUtil.initShaderProgram(EsShaderActivity.this, "shader_vertex.glsl", "shader_fragment.glsl");
        }

        // 在表面变更时触发
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES30.glViewport(0, 0, width, height); // 设置输出屏幕大小
            // 开启剔除操作。开启之后才能调用glCullFace方法禁止光照、阴影和颜色等效果,以消除不必要的渲染计算。
            GLES30.glEnable(GLES30.GL_CULL_FACE);
        }

        // 执行框架绘制动作
        @Override
        public 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" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="right"
            android:text="三角形样式:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <Spinner
            android: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.GLSurfaceView
        android:id="@+id/glsv_content"
        android:layout_width="match_parent"
        android:layout_height="400dp" />

</LinearLayout>

 创作不易 觉得有帮助请点赞关注收藏~~~文章来源地址https://www.toymoban.com/news/detail-441122.html

到了这里,关于【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenGL ES 3.0 着色器程序二进制化

    之前有位读者提问:C++ 如何将 OpenGL ES 的着色器程序二进制(保存),然后在其他地方加载使用?现在写篇文章介绍下。 将着色器程序二进制化(Shader Program Binary)有哪些好处? 快速加载和解析 :使用二进制形式的着色器程序可以更快地加载和解析,因为不需要进行编译和

    2024年02月07日
    浏览(44)
  • 第五章 OpenGL ES 基础-透视投影矩阵与正交投影矩阵

    第一章 OpenGL ES 基础-屏幕、纹理、顶点坐标 第二章 OpenGL ES 基础-GLSL语法简单总结 第三章 OpenGL ES 基础-GLSL渲染纹理 第四章 OpenGL ES 基础-位移、缩放、旋转原理 第五章 OpenGL ES 基础-透视投影矩阵与正交投影矩阵 模型都是3D的,但屏幕是2D的。如何将3D空间投影到2D平面,还能保

    2024年03月09日
    浏览(45)
  • Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础

    OpenGL本身是开放图形库的一种标准,定义了一个跨语言、跨平台的编程规范,主要用于3D图形编程。OpenGLES是OpenGL的裁剪版本,主要是针对嵌入式设备/移动设备 (像手机、游戏机这种等等。。。) 进行裁剪后的库。对于Android设备来说主要是用OpenGL ES。从初学者角度来讲 Ope

    2023年04月20日
    浏览(49)
  • 【OpenGL ES】三维图形绘制

    不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵! 颜色的简单搭配: 不红+不绿+不蓝 = 黑 红+绿+蓝 = 白 红+绿 = 黄 红+蓝 = 紫 绿+蓝 = 青蓝 投影主要分为 正交投影 和 透视投影 两种。 正交投影 没有近大远小的效果,是平行投影,投影

    2023年04月08日
    浏览(53)
  • OpenGL ES与EGL的关系(二十一),完美讲解内存缓存LruCache实现原理

    glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); // Blend st

    2024年04月11日
    浏览(40)
  • Android OpenGL ES实现简单绿幕抠图

    目录 正文 OES Filter BlendShader Filter 最后的效果 缺陷 实现绿幕抠图,其实想法很简单。 这里简单粗暴的使用着色器替换。 OES Filter 直接实现在相机预览上的Shader ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #extension GL_OES_EGL_image_external : require precision mediump float ;        

    2024年02月13日
    浏览(31)
  • Android OpenGL ES 学习(九) – 坐标系统和实现3D效果

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年01月25日
    浏览(46)
  • 【Android OpenGL开发】OpenGL ES与EGL介绍

    OpenGL(Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序接口,主要用于图像的渲染。 Android提供了简化版的OpenGL接口,即OpenGL ES。 早先定义 OpenGL ES 是 OpenGL 的嵌入式设备版本,用于移动端平台(Android、iOS),但由于嵌入式设备要求的是高性能,所以一些其它纯

    2024年02月04日
    浏览(90)
  • Android OpenGL ES 学习(一) -- 基本概念

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年01月23日
    浏览(43)
  • Android OpenGL ES 学习(五) -- 渐变色

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年02月07日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包