目录
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 转场
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 函数
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES GPUImage 使用
零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES GLSL 编程
OpenGL ES 定义了一个渲染图形的 API。它没有定义窗口系统。为了使 OpenGL ES 可以工作于各种平台之上,我们可以通过 google angle 完成;
ANGLE 的目标是通过将 OpenGL ES API 调用转换为该平台可用的硬件支持的 API 之一,。就是把 OpenGL ES 翻译成其他的语言,譬如说 D3D9 / OpenGL ES / Vulkan / Metal 等等。

ANGLE 支持 Windows / Mac / Linux / Android / Ios ;
ANGLE 目前提供从 OpenGL ES 2.0、3.0 和 3.1 到 Vulkan、桌面 OpenGL、OpenGL ES、Direct3D 9 和 Direct3D 11 的转换;

详细参考:《OpenGL ES EGL 简介》
EGLNativeDisplayType 在 OpenGL ES 与本地窗口系统之间架起了一座沟通的桥梁,EGLNativeDisplayType 一般使用默认的 EGL_DEFAULT_DISPLAY,在不同平台其实现是不同的,EGL 只提供抽象标准,在 Windwos 中 该值默认为 DX ,如果想使用 OPenGL,可以通过如下设置配置
EGLAttrib dispattrs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,EGL_NONE };
EGLNativeWindowType 表示窗口句柄,在不同平台其实现是不同的,EGL 只提供抽象标准,在 Windows 中 EGLNativeWindowType 实际上就是窗口句柄 HWND ,头文件声明如下:
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
typedef HWND EGLNativeWindowType;
#else
/* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeWindowType;
#endif
如果是想在窗口实时查看渲染结果,我们可以通过 eglCreateWindowSurface 创建可显示的 EGLSurface ,绑定窗口 HWND 后预览显示;
如果是离屏幕渲染,不需要绑定窗口,那么就不需要该参数,可以直接使用 eglCreatePbufferSurface 创建不可显示的 EGLSurface,保存在显存中的帧;
**EGLDisplay 是一个关联系统物理屏幕的通用数据类型。**对于 PC 来说, EGLDisplay 就是显示器的句柄。不管是嵌入式系统或 PC ,都可能有多个物理显示设备。为了使用系统的显示设备, EGL 提供了 EGLDisplay 数据类型,以及一组操作设备显示的 API 。

在不同平台上有不同的机制以关联窗口系统,在 Windows 上是 WGL ,在 Linux 上是 GLX ,在 Apple OS 上是 AGL 等。
**EGL 则是平台上 WGL / GLX / AGL 的等价物。**eglGetDisplay 为原生窗口系统 displayId 获取一个 EGL display 连接,在 OpenGL ES 与本地窗口系统之间架起了一座沟通的桥梁
EGLDisplay eglGetDisplay(EGLNativeDisplayType displayId);
EGLNativeDisplayType 默认为 EGL_DEFAULT_DISPLAY ,即返回与默认原生窗口的连接,在 Windows 中默认为 DX 渲染
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLAttrib dispattrs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,EGL_NONE };
eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
EGL_DEFAULT_DISPLAY, dispattrs);
EGLConfig 是对 EGLSurface 的 EGL 配置,可以理解为绘制目标 framebuffer 的配置属性
EGLSurface 也被称为渲染区域,系统窗口或 frame buffer 句柄 ,可以理解为一个后端的渲染目标窗口 ;
** EGLSurface 相当于一块画布(一块内存空间),用户想绘制的信息首先都要先绘制到 EGLSurface 上**
EGLSurface 分为以下三类:
1.Surface – 可显示的 Surface,实际上就是一个 FrameBuffer,用于绑定窗口后预览显示;
2.PixmapSurface – 不是可显示的 Surface,保存在系统内存中的位图;
3.PBufferSurface – 不是可显示的 Surface,保存在显存中的帧,用于离屏渲染,不需要绑定窗口
eglCreateWindowSurface 成功时返回新创建的 EGLSurface ,失败时返回 EGL_NO_SURFACE.
EGLSurface eglCreateWindowSurface(
EGLDisplay display, //对应的EGL display连接
EGLConfig config, //EGL frame buffer配置
NativeWindowType native_window, //原生窗口
EGLint const * attrib_list); // Window Surface属性列表,可以为NULL
创建一个离屏 pixel buffer surface 返回它的句柄
EGLSurface eglCreatePbufferSurface(
EGLDisplay display, // 指定EGL显示连接
EGLConfig config, // 指定配置
const EGLint *attribList) // 指定像素缓冲区属性
相关错误码:
EGL_BAD_MATCH :提供了与窗口属性不匹配的 EGLConfig,或该 EGLConfig 不支持渲染到窗口
EGL_BAD_CONFIG :提供的 EGLConfig 没有得到系统支持
EGL_BAD_NATIVE_WINDOW :提供的原生窗口句柄无效
EGL_BAD_ALLOC :无法为新的窗口分配资源,或已经有和提供的原生窗口关联的 EGLConfig
除了可以用 OpenGL ES 3.0 在屏幕上的窗口渲染之外,还可以渲染称作 Pbuffer (像素缓冲区 Pixel buffer 简写)的不可见的屏幕外表面,不需要绑定窗口,用于离屏渲染。
和窗口一样,pbuffer 可以利用 OpenGL ES 3.0 中的任何硬件加速。Pbuffer 最常用于生成纹理贴图。如果你想要做的是渲染到一个纹理,那么我们建议使用帧缓冲区代替 Pbuffer,因为 帧缓冲区更高效。
创建 Pbuffer 和创建 EGL 窗口非常类似,只有少数微小的不同。为了创建 Pbuffer ,需要和窗口一样找到 EGLConfig ,并作一处修改:我们需要扩增 EGL_SURFACE_TYPE 的值,使其包含 EGL_PBUFFER_BIT。
EGLSurface eglCreatePbufferSurface(
EGLDisplay display, // 指定EGL显示连接
EGLConfig config, // 符合条件的 EGLConfig
const EGLint *attribList); // 指定像素缓冲区属性列表,可为 NULL
创建一个 EGL 像素缓冲区:
EGLint attribList[] = {
EGL_SURFACE_TYPE,EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 1,
EGL_NONE
};
// 查询EGL表面配置
const EGLint MaxConfigs = 10;
EGLConfig configs[MaxConfigs]; // We'll only accept 10 configs
EGLint numConfigs;
if (!eglChooseConfig(display, attribList, configs, MaxConfigs, &numConfigs)) {
// Something didn't work … handle error situation
} else {
// Everything's okay. Continue to create a rendering surface
}
// Proceed to create a 512*512 pbuffer
EGLSurface pbuffer;
EGLint attribList2[] =
{
EGL_WIDTH, 512,
EGL_HEIGHT, 512,
EGL_LARGEST_PBUFFER, EGL_TRUE,
EGL_NONE
};
pbuffer = eglCreatePbufferSurface(display, config, attribList2);
if (pbuffer == EGL_NO_SURFACE) {
switch (eglGetError()) {
case EGL_BAD_ALLOC:
// Not enough resources available. Handle and recover
break;
case EGL_BAD_CONFIG:
// Verify that provided EGLConfig is valid
break;
case EGL_BAD_PARAMETER:
// Verify that EGL_WIDTH and EGL_HEIGHT are non-negative values
break;
case EGL_BAD_MATCH:
// Check window and EGLConfig attributes to determine
// compatibility, or verify that the EGLConfig
// supports rendering to a window,
break;
}
}
EGLint width;
EGLint height;
if(!eglQuerySurface( display,pbuffer,EGL_WIDTH,&width) ||
!eglQuerySurface( display,pbuffer,EGL_HEIGHT,&height))
{
//Unable to query surface information
}
OpenGL ES 图形上下文,它代表了 OpenGL 状态机;如果没有它,OpenGL 指令就没有执行的环境。
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(
EGLDisplay display,
EGLConfig config,
EGLContext share_context,
const EGLint *attribList);
EGLContext 上下文包含了操作所需的所有状态信息,OpenGL ES 必须有一个可用的上下文才能进行绘图。
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(
EGLDisplay display,
EGLSurface draw,
EGLSurface read, EGLContext context);
eglQueryContext 用于获取 Context 信息
EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(
EGLDisplay display,
EGLContext context,
EGLint attribute,
EGLint *value);
成功时返回 EGL_TRUE,失败时返回 EGL_FALSE,可能的错误为:
EGL_BAD_DISPLAY
EGL_NOT_INITIALIZED
EGL_BAD_CONTEXT
EGL_BAD_ATTRIBUTE
attribute 取值可以是:
EGL_CONFIG_ID
EGL_CONTEXT_CLIENT_TYPE
EGL_CONTEXT_CLIENT_VERSION
EGL_RENDER_BUFFER
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context);
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有
我使用Ruby编程已经有一段时间了,现在只使用Ruby的标准MRI实现,但我一直对我经常听到的其他实现感到好奇。前几天我在读有关Rubinius的文章,这是一个用Ruby编写的Ruby解释器。我试着在不同的地方查找它,但我很难弄清楚这样的东西到底是如何工作的。我在编译器或语言编写方面从来没有太多经验,但我真的很想弄明白。一门语言究竟如何才能被自己解释?编译中是否有一个我不明白这有意义的基本步骤?有人可以像我是个白痴一样向我解释这个吗(因为无论如何这都不会太离谱) 最佳答案 它比你想象的要简单。Rubinius并非100%用Ruby编
谁能解释一下这段Ruby代码:defadd_spec_path_to(args)#:nodoc:args我看到了运算符用于连接字符串或在其他语言中用作按位运算符,但有人可以在这种情况下对其进行解释。它是以某种方式将一个空白的lamda附加到args上还是我完全错了?我还可以看到它是这样使用的:before_parts(*args)是Hash关键字?我也不确定||=是什么接线员在说。我同样对什么一无所知caller(0)[2]是。 最佳答案 我假设args是一个Array。Hash是类的名称-第一行将空哈希{}推送到argsunles
在编译型语言中,源代码由编译器转化为目标代码,不同的目标文件(如果有多个文件)由链接器链接并由加载器加载到内存中执行。如果我有一个使用解释性语言(例如ruby或python)编写的应用程序,并且如果源代码跨多个文件拆分,那么这些文件究竟何时组合在一起。换句话说,链接何时完成?解释型语言一开始就有链接器和加载器,还是解释器包揽一切?我真的很困惑,无法理解它!!谁能对此有所启发?! 最佳答案 解释型语言或多或少是可执行文件的大型配置,称为解释器。该可执行文件(例如/usr/bin/python)是实际运行的程序。然后它读取它要执行的
我打算学习Ruby。我知道这是一种解释语言。我知道编译语言最终会被翻译成机器码,但是ruby解释器是做什么的呢?我读到解释器是用C编写的,但是每一行ruby都转换为c,然后再次编译为机器代码吗?我也听说过JIT,但是如果这会增加答案的复杂性,那么您就不需要回答它了。我正在寻找的是我的Ruby代码发生了什么。 最佳答案 它将Ruby代码转换为某种更简单的“中间”表示形式(在最近的版本中,它编译为字节码)。它还会在您计算机的内存中构建一个虚拟机,模拟执行该表示的物理机。这台机器是一台物理机器的镜像,至少在合理和有用的范围内。它通
我刚刚在我的程序中的一些数字操作中发现了一个错误,我得到了一个FloatDomainError(NaN)所以我开始记录传入的数字:if(metric.is_a?(Numeric))self.metric=metricelseLOGGER.warn("metric#{metric}isnotanumber")self.metric=0end但传入的数字是NaN显然is_a?(Numeric)因为我没有收到日志警告,它会将指标传递给我的指标=方法,这是我获取FloatDomainError的地方现在,如果我错了,请纠正我,但是NaN(不是数字)的类型似乎在语义上是错误的吗??谁能给我解释一
我现在正在努力学习Ruby和RubyonRails。我正在学习LearningRails,第1版,但我很难理解其中的一些代码。我通常使用C、C++或Java工作,因此Ruby对我来说是一个很大的改变。我目前对数据库迁移器的以下代码块感到困惑:defself.upcreate_table:entriesdo|t|t.string:namet.timestampsendendt变量来自哪里?它实际上代表什么?它有点像for(i=0;i另外,:entries是在什么地方定义的?(entries是我的Controller的名称,但是这个函数怎么知道的?) 最佳答案