OGL现代图形(顶点/纹理/状态命令/Shader)和底层渲染顺序(CommandBuffer协同并行/帧前后/drawcall过程)-持续更新

一、OGL显卡中的帧缓存区(非输入的原始顶点和像素数据)

1) 颜色缓存,  左前,右前,左后,右后和任意数量的辅助颜色缓存; OGL 3.1辅助颜色缓存没有,不支持立体观察(VR), 是使用左颜色缓存(启用双缓存是左前,左后颜色缓存,启用单缓存是左前颜色缓存)
2) 深度缓存
3) 模板缓存
4) 累积缓存(累计存储,拷贝回源颜色缓存的,OGL 3.1后已废弃)

OGL中用全局指针和结构体字段接口访问修改API参数

OGL中结构体申请名字,申请空间和填充值,切换绑定对象(类型指针全局唯一,类型结构体众多)
enum { Cube, Cone, NumVAOs };
GLuint VAO[NumVAOs];
glGenVertexArrays(NumVAOs, VAO);
glBindVertexArray(VAO[Cube]);
  glBindVertexArray(VAO[Cone]);


//Create the storage for the object
GLuint objectName;
glGenObject(1, &objectName);

//Put data into the object.
glBindObject(GL_MODIFY, objectName);
glObjectParameteri(GL_MODIFY, GL_OBJECT_COUNT, 5);
glObjectParameterf(GL_MODIFY, GL_OBJECT_OPACITY, 0.4f);
glObjectParameters(GL_MODIFY, GL_OBJECT_NAME, "Some String");

OpenGL拥有所有变量的存储空间。因此,用户只能通过引用来访问这些变量。几乎所有的OpenGL变量都通过无符号整型值(GLuint)来引用。变量通过像glGen*之类的函数创建,这里*是变量的类型。第一个参数是要创建变量的个数,第二个是一个GLuint*的数组用来接受新创建的变量的名字。

要修改这些变量,他们首先必须被绑定到上下文(context)对象。许多的对象可以被绑定到上下文中的不同地址。这样允许同一个对象以不同方式使用。不同的地址称作目标(targets)。所有的变量都有一个合法的目标列表,而有一些仅有一个。在上述例子中,这个虚构的“GL_MODIFY”  就是objectName变量绑定到的地址,GL_MODIFY目标地址类似一个全局指针,所以同一个类型的当前操作缓存指针只有一个。

枚举常量 GL_OBJECT_*表示变量中可以被设置的有名字的值域。glObjectParameter函数族的函数设置绑定到目标的变量的参数。

鉴于OpenGL是C API,因此它需要为不同类型声明不同版本函数。因此glObjectParameteri 对应整数参数,glObjectParameterf 对应浮点型参数版本,依次类推。

OpenGL context

OGL context代表了当前的OGL进程中的一个线程渲染实例集合(一个线程渲染实例渲染到一个帧缓存中,而不是帧缓存对象),集合内包含了这个OGL实例所有的图形数据集合,像素数据集合,渲染状态集合,GLSL显存着色器命令集合,和相关OGL硬件抽象对象例如设备对象等;Context销毁了一个OGL实例就销毁了。OGL进程可以拥有多个OGL Context,context之间可以共享非容器的数据类型例如同步对象,GLSL对象。OGL Context是线程安全的,当前OGL Context是线程本地化的,不能由多个线程共享,所以Unity中都是单线程渲染。

一个渲染流水线只有一个ogl-context所以直接绑定glBindVertexArray,GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER就可以绑定到全局的指针中。在多GPU中,多GPU会抽象为一个逻辑显卡和OGL Context对应,具体在驱动层分配工作。

An OpenGL context represents many things. A context stores all of the state associated with this instance of OpenGL. It represents the (potentially visible)default framebuffer that rendering commands will draw to when not drawing to a framebuffer object. Think of a context as an object that holds all of OpenGL; when a context is destroyed, OpenGL is destroyed.

Contexts are localized within a particular process of execution (an application, more or less) on an operating system. A process can create multiple OpenGL contexts. Each context can represent a separate viewable surface, like a window in an application.

Contexts can share many kinds of objects between each other. Any OpenGL object types which are not containers are sharable, as well as Sync Objects and GLSL Objects (excluding program pipeline objects). All container objects are not shared between contexts.

Any object sharing must be made explicitly, either as the context is created or before a newly created context creates any objects. However, contexts do nothave to share objects; they can remain completely separate from one another.

In order for any OpenGL commands to work, a context must be current; all OpenGL commands affect the state of whichever context is current. The current context is a thread-local variable, so a single process can have several threads, each of which has its own current context. However, a single context cannot be current in multiple threads at the same time.


OGL状态机工作模式

几乎所有的OpenGL函数设置或者获取状态。仅有的不改变状态的函数是那些使用当前状态来渲染图像的函数。

你可以将状态机想象成一个有着很多值域的大型结构体。这个结构体称为OpenGL context,其中的每个值域对于渲染图像都有用。

OpenGL中的变量是在结构体中定义的值域列表,他们可以保存和恢复。绑定一个对象到上下文中,导致上下文中的状态被该对象中的数据替换。因此,绑定后,如果有函数调用读取或者修改了上下文的状态将会读取或者修改这个对象的状态。

对象通常有GLuint来代表,他们是实际的OpenGL对象的句柄。0是个特别的变量,它和NULL指针的类似。绑定对象0意味着解除当前绑定对象的绑定,这样绑定之前的状态将会成为当前状态并起作用。

举个例子,下面的context代表OpenGL的上下文状态:

struct Values
{
    int iValue1;
    int iValue2;
};

struct OpenGL_Context
{
    ...
    Values *pMainValues;
    Values *pOtherValues;
    ...
};

OpenGL_Context context;


创建一个Values 对象,你需要调用glGenValues。你可以将 Values 绑定到GL_MAIN_VALUES(代表着context.pMainValues)或者GL_OTHER_VALUES(代表着context.pOtherValues)。你可以调用glBindValues函数来绑定对象,向这个对象传递两个目标之一。这样目标的指针就指向为你创建的那个对象。

这里也会有一个设置对象值得函数,例如, glValueParam。它将对象的目标作为一个参数,这个参数代表了上下文中的指针;同时使用一个代表对象中值域的枚举常量作为参数。枚举常量GL_VALUE_ONE代表iValue1,GL_VALUE_TWO代表iValue2。

OGL Shader对象和Shader着色器程序Program的创建存储在显存中,渲染时可以激活和去激活

GLuint shader = glCreateShader(eShaderType);//根据类型创建shader  
glShaderSource(shader, 1, &strFileData, NULL);//绑定shader对象到Shader代码字符串  
glCompileShader(shader);//编译shader对象
// 检查编译的Shader编译是否成功
 GLint status;  
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);  
    if (status == GL_FALSE)  
    { }


//构造着色器程序对象
 GLuint programId = glCreateProgram();//创建program  
//绑定多个shader到着色器程序
glAttachShader(programId, shaderList[iLoop]);
//链接shader 
glLinkProgram(programId);
// 检查Shader程序对象链接是否成功
GLint status;  
    glGetProgramiv(programId, GL_LINK_STATUS, &status);  
    if (status == GL_FALSE)  
    {  }


// 得到着色器内部的变量
 offsetLocationId = glGetUniformLocation(programId, "offset"); 


// Draw call渲染时候激活着色器程序
glUseProgram(programId);  
// 更新着色器中的变量
glUniform2f(offsetLocationId, fXOffset, fYOffset);//偏移量发送到顶点着色器 
// 指定解析VBO数据
glBindBuffer(GL_ARRAY_BUFFER, vboId);  
    //启用顶点位置属性索引  
    glEnableVertexAttribArray(0);  
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);  
// 绘制几何图元 
    glDrawArrays(GL_TRIANGLES, 0, 3); 


// 去激活着色器程序

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值