OpenGL es 综述

OpenGL ES是嵌入式和移动系统的3D图形API,提供了2D和3D图形呈现。从OpenGL ES 1.0的固定功能到3.2版本的增强功能,如可编程着色器和计算能力。API包括扩展头文件,如<GL/glext.h>,以及具有特定语法的GL命令。NVIDIA为基于Tegra的设备提供了简化GL项目创建的框架。
摘要由CSDN通过智能技术生成

嵌入式加速的3D制图法标准

OpenGL ES是一种免版税的、跨平台的API,用于在嵌入式和移动系统(包括控制台、电话、设备和车辆)上呈现高级2D和3D图形。它由定义良好的适合低功耗设备的桌面OpenGL子集组成,并在软件和图形加速硬件之间提供了灵活而强大的接口。

OpenGL ES版本一览

OpenGL ES 3.2 -附加的OpenGL功能

在本系列的最新版本中,OpenGL ES 3.2为OpenGL ES 3.1添加了基于Android扩展包的附加功能,这使得移动API的功能与桌面API OpenGL更加接近。

OpenGL ES 3.1 -将计算引入移动图形

尽管OpenGL ES 3.1只是API的一个小修改,但它对API来说是一个巨大的里程碑,因为它增加了在API中进行通用计算的能力,将计算引入了移动图形。

OpenGL ES 3.0 -增强的图形

OpenGL ES 3.0是OpenGL ES的另一个进化步骤,特别是包括多个渲染目标,额外的纹理功能,统一的缓冲,实例化和转换反馈。

OpenGL ES 2.0 -可编程的阴影

OpenGL ES 2.0是第一个在最新一代图形硬件中公开可编程着色器的便携移动图形API。它仍然是当今流行的API,并且仍然是最广泛可用的3D图形API,并且仍然是瞄准市场上最广泛设备的可靠选择。

 OpenGL ES - 1  固定函数图形

OpenGL ES 1.0和1.1是第一个可移植的移动图形api,定义相对于OpenGL 1.5规范,提供固定的功能图形加速

 

API和拓展头文件

由于扩展因平台和驱动程序的不同而不同,OpenGL开发人员不能期望所有扩展的接口都在标准的gl.h和glx中定义。和wgl.h头文件提供的OS /图形驱动程序。这里提供了额外的头文件,包括:

 

下面描述的几乎所有头文件都依赖于一个平台头文件,该文件是多个Khronos api所共有的<KHR/khrplatform.h>。

  • <GL/glext.h> - OpenGL 1.2及以上的兼容性配置文件和扩展接口
  • <GL/glcorearb.h> - OpenGL核心配置文件和ARB扩展接口,如OpenGL 4.3规范的附录G.2所述。不包括仅在兼容性配置文件中找到的接口
  • <GL/glxext.h> - GLX 1.3及以上API和GLX扩展接口
  • <GL/wglext.h> - WGL扩展接口

这些头定义了包括枚举数在内的接口;原型;对于支持动态运行时扩展查询的平台,如Linux和Microsoft Windows,函数指针类型为defs。

 

GL命令语法

GL命令是函数或过程。执行不同的命令组相同的操作,但是不同的参数是如何提供给它们的。为了方便地适应这种变化,我们采用了一种描述命令的符号和他们的论点。GL命令由后面的名称组成,具体取决于具体的名称命令,最多4个字符。第一个字符表示值的数量必须呈现给命令的指定类型。第二个字符或字符对指示参数的特定类型:8位整数、16位整数、32位整数、单精度浮点数或双精度浮点数。最后一个字符(如果存在)是v,表示命令接受a指向值数组(向量)的指针,而不是一系列单独的参数。

两个具体的顶点命令的例子:

void Vertex3f( float x, float y, float z );

void Vertex2sv( short v[2] );

这些示例显示了这些命令的ANSI C声明。一般来说,命令声明的格式是:

rtype Name{1234}{ b s i f d ub us ui}{v} ( [args ,] T arg1 , . . . , T argN [, args] );

type是函数的返回类型。大括号({})括起一系列字符(或字符对),从中选择一个。表示 没有 character.的

括号中的参数([args,]和[,args])可能存在,也可能不存在。

使用NVIDIA框架创建GL项目

对于基于tegra的设备,NVIDIA提供了一个框架,大大简化了这个过程(该框架可能也适用于其他Android设备,但我们还没有测试过)。现在我们将实现一个与前一个非常相似的项目,但是我们将使用这个助手来展示它的基本用法。应用程序会根据触摸的x和y位置改变背景颜色,但除此之外,如果应用程序处于焦点或暂停状态,它还会覆盖不同的文本。为了执行后者,我们将处理UI生成的事件。如果应用程序是焦点,我们将显示“活动模式!”,我们将跟踪触摸的位置。当返回按钮被按下一次,或“最近的应用”按钮被按下,或按下右下角,应用将被认为是暂停,或失焦,文本将被更改为:

Auto-pause
Press back to quit
Tap window to resume

当应用程序暂停时,除非生成一个新事件,否则将再呈现4帧,之后就不会发生其他任何事情。首先,我们像以前一样创建一个项目(SimpleNativeGL_NV)。按照上面描述的第一步操作,直到修改AndroidManifest.xml文件的部分。清单文件的唯一区别是我们给库的名字:

[...]
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
	   android:value="SimpleNativeGL_NV" />
[...]

现在让我们修改Android项目jni文件夹中的mk文件: 

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := SimpleNativeGL_NV
LOCAL_SRC_FILES := SimpleNativeGL_NV.cpp Engine.cpp
LOCAL_LDLIBS    := -lc -lm -llog -landroid -ldl -lGLESv2 -lEGL
LOCAL_STATIC_LIBRARIES := nv_and_util nv_egl_util nv_bitfont nv_math nv_glesutil nv_hhdds nv_log nv_shader nv_file nv_thread
LOCAL_CFLAGS    += -std=gnu++0x

include $(BUILD_SHARED_LIBRARY)

# Add the folder with the NVIDIA helper, assuming we are at the nvsample_workspace
$(call import-add-path, $(NVPACK_PATH)/TDK_Samples/tegra_android_native_samples_v10p14/libs/jni)

# Import the modules from the NVIDIA helper
$(call import-module, nv_and_util)
$(call import-module, nv_egl_util)
$(call import-module, nv_bitfont)
$(call import-module, nv_math)
$(call import-module, nv_glesutil)
$(call import-module, nv_hhdds)
$(call import-module, nv_log)
$(call import-module, nv_shader)
$(call import-module, nv_file)
$(call import-module, nv_thread)

除了我们在示例中所做的之外,我们还从头创建了一个OpenGL项目,这里我们只是链接到NVIDIA库并导入相应的模块。注意,我们再次假设您使用的是$NVPACK_PATH/nvsample_workspace工作区。如果没有,您将不得不更改NVIDIA助手文件夹的指针。因为我们将创建一个名为Engine的类,所以我们将相应的源文件添加到LOCAL_SRC_FILES列表中。此外,我们需要字体的文本,我们将覆盖在屏幕上。我们可以从工作区中其他项目的assets文件夹中获取它们。例如,在Project Explorer中展开文件夹NativeBasic > assets。复制两个*。abc和*。将dds文件复制到我们项目的assets文件夹中(总共需要复制4个文件)。在Eclipse Project Explorer中按住ALT键拖放可能是最简单的方法。最后,为了确保我们的应用程序得到充分优化,我们需要application .mk。您可以像从头创建OpenGL项目那样创建它,或者直接从其他项目复制它。因为我们想要使用新的c++ 11 STL的智能指针,我们需要添加一行来表明我们将使用GNU STL实现:

APP_ABI := armeabi-v7a
APP_STL := gnustl_static

现在,我们将从前面的示例创建一个扩展引擎结构的类,并将大部分代码移动到它。在Project Explorer窗格中,右键单击jni文件夹,然后单击New >类。在类名字段中,键入Engine,然后单击Finish。Eclipse现在已经为我们创建了类的头文件和源文件。让我们从头文件开始:

#ifndef __ENGINE_H
#define __ENGINE_H

// Includes for the NVIDIA helper libraries
#include <nv_and_util/nv_native_app_glue.h>
#include <nv_egl_util/nv_egl_util.h>

// Logging macros
#define APP_NAME "SimpleNativeGL_NV"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG,APP_NAME, __VA_ARGS__))
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, APP_NAME, __VA_ARGS__))

#define FRAMES_TO_RENDER 4

/**
 *  This is the engine which implements the required callback functions,
 *  as well as a few utility functions.
 *  This implementation relies on the NVIDIA utilities.
 */
class Engine
{
public:
    /**
     * The constructor saves a pointer to the engine and to the callback
     * functions in the Android app. It also initializes the nv_shader library.
     */
    Engine( NvEGLUtil& egl, struct android_app *app );

    /**
     * The destructor mainly frees the allocated BitFonts.
     */
    ~Engine();

    /**
     * The application can be active or paused. This function returns
     * false when the application is paused.
     */
    bool isActiveMode()
    {
	return mActiveMode;
    }

    /**
     * Render the frame, after checking what the status of the Android app is.
     * Interactible should be true if the app is running, it is active, focused,
     * and has a valid surface.
     */
    void updateFrame( bool interactible );

protected:

    /**
     *  Wrapper to handle commands generated by the UI.
     */
    static void handleCmdThunk( struct android_app *app, int32_t cmd );

    /**
     * Handle commands.
     */
    void handleCommand( int cmd );

    /**
     * Wrapper to handle input events generated by the UI.
     */
    static int32_t handleInputThunk( struct android_app *app, AInputEvent *event );

    /**
     * Handle inputs.
     */
    int handleInput( AInputEvent *event );

    /* Auxiliary functions */

    /**
     * Set mActiveMode; we use mActiveMode to keep track of whether the app is actually
     * running or paused. Examples of when the app is paused is when the user has pressed
     * the back button, the "Recent apps" button, or the time at the bottom right corner
     * of the screen.
     */
    void setActiveMode( bool running );

    /**
     * If the app's window had been resized returns true and forces the frame to be
     * rendered.
     */
    bool checkWindowResized();

    /**
     * Resets the number of frames that need to be rendered.
     */
    void requestForceRender()
    {
	// Even when no events are generated, we required that the system still renders
	// FRAMES_TO_RENDER frames.
	mForceRender = FRAMES_TO_RENDER;
    }

    /*
     * Check if we are done rendering frames.
     */
    bool isForcedRenderPending()
    {
	// mForceRender is decremented every time a frame is rendered and
	// reinitialized to FRAMES_TO_RENDER when a new event is generated
	// by the UI
	return mForceRender > 0;
    }

    /**
     * This is the actual method which renders the frame.
     * It returns false if either EGL was not ready to render or
     * the UI could not be initialized.
     */
    bool renderFrame( bool allocateIfNeeded );

    /**
     * Initialize the UI
     * Returns true if the UI was initialized, false if the fonts could not be
     * initialized.
     */
    bool initUI();

    /**
     * If there is a pending window resize, perform it and return true.
     */
    bool resizeIfNeeded();

    /* Variables */
    struct android_app *mApp; // Pointer to the Android app
    NvEGLUtil &mEgl;          // NvEGLUtil is the NVIDIA wrapper to EGL
    bool  mResizePending;     // Is there a window-resize pending?
    bool  mActiveMode;        // Is the app active or has it been paused?
    bool  mUiInitialized;     // Has the UI been initialized?
    void *mUiText[2];         // We need this variable to get a pointer to the bftext objects
    int   mTouchX, mTouchY;   // Position of the touch event
    int   mForceRender;       // This variable counts how many more frames we want
   			      // to render in case no new requests are generated.
};

#endif // __ENGINE_H

 注释以及方法和变量的命名应该是不言自明的。所以我们可以看看不同方法的实现,从包含、构造函数和析构函数开始:

#include "Engine.h"

// Includes for GL and EGL
#include <EGL/egl.h>
#include <EGL/eglplatform.h>
#include <GLES2/gl2.h>

// Includes for the NVIDIA helper libraries
#include <nv_and_util/nv_native_app_glue.h>
#include <nv_egl_util/nv_egl_util.h>
#include <nv_bitfont/nv_bitfont.h>
#include <nv_shader/nv_shader.h>

Engine::Engine( NvEGLUtil& egl, struct android_app *app )
		: mEgl( egl ), mApp( app ), mResizePending( false ), mActiveMode( true ),
		  mForceRender( 4 ), mUiInitialized( false )
{
    // Save a pointer to the engine in the Android app
    app->userData = this;

    // Save pointers to the implementation of the callback functions in the
    // Android app
    app->onAppCmd     = &Engine::handleCmdThunk;
    app->onInputEvent = &Engine::handleInputThunk;

    // Initialize the nv_shader library
    nv_shader_init( app->activity->assetManager );

    // Initialize the pointers to the bftext objects
    mUiText[0] = NULL;
    mUiText[1] = NULL;
}

Engine::~Engine()
{
    // Free the allocated BitFonts
    NVBFTextFree( mUiText[1] );
    NVBFTextFree( mUiText[0] );
    NVBFCleanup();
}

在上面的代码中,我们使用了一些NVIDIA库,比如EGL实用程序。没有关于这些库的全面文档,但是代码注释得很好。让我们研究一下EGL是由什么组成的。将光标放在NvEGLUtil引擎构造函数的参数列表中,然后按F3(或者按CTRL-click [CMD-click on Mac])。这将把您带到nv_egl_util.h中该对象的定义。如果索引器工作正常,您现在可以执行相同的操作,在某些成员函数(如swap())的声明和定义之间进行切换。可以使用CTRL-TAB在头文件和实现文件之间切换。使索引器为nv_egl_util工作。h,你需要转到项目属性> C/ c++一般>路径和符号>源位置,并将文件夹链接到nv_egl_util.cpp文件所在的位置(它在$NVPACK_PATH/TDK_Samples/tegra_android_native_samples_v10p14/libs/jni/nv_egl_util中)。无论如何,浏览这两个文件可以看到NvEGLUtil类是如何工作的。到目前为止,除了初始化了nv_shader库之外,它与前面的代码非常相似。现在我们需要编写处理来自UI的命令的函数。在构造函数中,我们将app->onAppCmd回调链接到方法引擎::handleCmdThunk();这个方法只是从应用程序获取一个指向引擎对象的指针,并调用一个实际处理命令的方法。

这一部分来源于https://docs.nvidia.com/gameworks/content/technologies/mobile/native_android_opengles.htm 

OpenGL ES 3.0 英文版 第1章——OpenGL ES 3.0简介   第1章简单介绍OpenGL ES,概述了OpenGL ES 3.0图形管线,讨论了OpenGL ES 3.0的设计理念和限制,最后介绍了OpenGL ES 3.0中使用的一些约定和类型。   第2章——你好,三角形:一个OpenGL ES 3.0示例   第2章介绍绘制三角形的一个简单OpenGL ES 3.0示例。我们的目的是说明OpenGL ES 3.0程序的样子,向读者介绍一些API概念,并说明如何构建和运行OpenGL ES 3.0示例程序。   第3章——EGL简介   第3章介绍EGL——为OpenGL ES 3.0创建表面和渲染上下文的API。我们说明与原生窗口系统通信、选择配置和创建EGL渲染上下文及表面的方法,传授足够多的EGL知识,你可以了解到启动OpenGL ES 3.0进行渲染所需的所有知识。   第4章——着色器和程序   着色器对象和程序对象是OpenGL ES 3.0中最基本的对象。第4章介绍创建着色器对象、编译着色器和检查编译错误的方法。这一章还说明如何创建程序对象、将着色器对象连接到程序对象以及链接最终程序对象的方法。我们讨论如何查询程序对象的信息以及加载统一变量(uniform)的方法。此外,你将学习有关源着色器和程序二进制代码之间的差别以及它们的使用方法。   第5章——OpenGL ES着色语言   第5章介绍编写着色器所需的着色语言的基础知识。这些着色语言基础知识包括变量和类型、构造器、结构、数组、统一变量、统一变量块(uniform block)和输入/输出变量。该章还描述着色语言的某些更细微的部分,例如精度限定符和不变性。   第6章——顶点属性、顶点数组和缓冲区对象   从第6章开始(到第11章为止),我们将详细介绍管线,教授设置和编程图形管线各个部分的方法。这一旅程从介绍几何形状输入图形管线的方法开始,包含了对顶点属性、顶点数组和缓冲区对象的讨论。   第7章——图元装配和光栅化   在前一章讨论几何形状输入图形管线的方法之后,第7章将讨论几何形状如何装配成图元,介绍OpenGL ES 3.0中所有可用的图元类型,包括点精灵、直线、三角形、三角形条带和三角扇形。此外,我们还说明了在顶点上进行坐标变换的方法,并简单介绍了OpenGL ES 3.0管线的光栅化阶段。   第8章——顶点着色器   我们所介绍的管线的下一部分是顶点着色器。第8章概述了顶点着色器如何融入管线以及OpenGL ES 着色语言中可用于顶点着色器的特殊变量,介绍了多个顶点着色器的示例,包括逐像素照明和蒙皮(skinning)。我们还给出了用顶点着色器实现OpenGL ES 1.0(和1.1)固定功能管线的示例。   第9章——纹理   第9章开始介绍片段着色器,描述OpenGL ES 3.0中所有可用的纹理功能。该章提供了创建纹理、加载纹理数据以及纹理渲染的细节,描述了纹理包装模式、纹理过滤、纹理格式、压缩纹理、采样器对象、不可变纹理、像素解包缓冲区对象和Mip贴图。该章介绍了OpenGL ES 3.0支持的所有纹理类型:2D纹理、立方图、2D纹理数组和3D纹理。   第10章——片段着色器   第9章的重点是如何在片段着色器中使用纹理,第10章介绍编写片段着色器所需知道的其他知识。该章概述了片段着色器和所有可用的特殊内建变量,还演示了用片段着色器实现OpenGL ES 1.1中所有固定功能技术的方法。多重纹理、雾化、Alpha测试和用户裁剪平面的例子都使用片段着色器实现。   第11章——片段操作   第11章讨论可以适用于整个帧缓冲区或者在OpenGL ES 3.0片段管线中执行片段着色器后适用于单个片段的操作。这些操作包括剪裁测试、模板测试、深度测试、多重采样、混合和抖动。本章介绍OpenGL ES 3.0图形管线的最后阶段。   第12章——帧缓冲区对象   第12章讨论使用帧缓冲区对象渲染屏幕外表面。帧缓冲区对象有多种用法,最常见的是渲染到一个纹理。本章提供API帧缓冲区对象部分的完整概述。理解帧缓冲区对象对于实现许多高级特效(如反射、阴影贴图和后处理)至关重要。   第13章——同步对象和栅栏   第13章概述同步对象和栅栏,它们是在OpenGL ES 3.0主机应用和GPU执行中同步的有效图元。我们讨论同步对象和栅栏的使用方法,并以一个示例作为结束。   第14章——OpenGL ES 3.0高级编程   第14章是核心章节,将本书介绍的许多主题串联在一起。我们已经选择了高级渲染技术的一个样本,并展示了实现这些功能的示例。该章包含使用法线贴图的逐像素照明、环境贴图、粒子系统、图像后处理、程序纹理、阴影贴图、地形渲染
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值