美文网首页
OpenGL/GLES Notes

OpenGL/GLES Notes

作者: CrystalDragon | 来源:发表于2018-07-18 14:19 被阅读0次

    @(Graphics)[OpenGL, OpenGLES]

    OpenGL/GLES Notes

    EGL

    opengl和host app window system之间的glue层

    使用egl进行绑定例程中, 主要创建的对象包括

    • display device: eglGetDisplay 使用default即可
    • config object: 包含了当前render相关的所有参数, 包括target的buffer格式, frame组成, onscreen/offscreen等, 通过eglGetConfigseglChooseConfig进行查询, 获取一个合适的config
    • rendering surface: 根据onscreen/offscreen区分, 使用eglCreateWindowSurfaceeglCreatePbufferSurface. 前者需要传入一个平台相关的window对象(例如Windows上就是HWND). 需要额外指定surface的模式参数, 例如单/双缓冲, frame的大小等
    • rendering context: 包含了所有的gl state. eglCreateContext. 可以实现context共享, 但是一般用不到. 需要额外的context参数, 主要是opengl/es的版本
    • 把context和surface绑定: eglMakeCurrent

    iOS Apple自己有提供context: EAGLContext, 创建非常简单, 不需要使用到EGL.

    Program Object & Shaders

    从Host app向Shader传递数据有2种主要形式

    • attribute
    • uniform

    Attributes

    attribute的数据处理时是per vertex的, 但我们可以给所有vertex赋予不同, 也可以给相同的值. (后者在OpenGLES3.0 PG这本书中称为 constant vertex attribute)

    当program编译并完成之后, 其attribute入参的相关meta data都确定了, 可以通过一些列query方法抽取.

    • 调用glGetProgram提供GL_ACTIVE_ATTRIBUTESGL_ACTIVE_ATTRIBUTE_MAX_LENGTH, 可以获知indexCount和max name length
    • 调用glGetActiveAttrib可以一次性获取到attribute的name, type, size等参数. 调用时的index一定是属于0..<indexCountrange内

    注意: OpenGL里对类似GL_MAX_VERTEX_ATTRIBS这类state限制的解释: 都是以vec4为单位的, 如果出现数组或者struct或者mat4, 是按复数倍来计算的. 因此最终programmer真正能使用的active attribute的参数个数可能会少于GL_MAX_VERTEX_ATTRIBS. 即: 仍然是从0开始递增计数, 但上限会更小.

    但一般host app在给shader提供具体data时, 并不会从program从头开始query参数来决定如何提供data, 而是根据先验的知识(例如location, name等)来决定提供data的方式.

    • attribute的layout location和index不是一个概念, index一定从0开始以step为1递增, 但location可以在shader中, 用layout(location = x)指定. 同时当一个attribute的size较大时, 相邻index的attribute的location差大于1, 具体规则可以理解成一个vec4会加1, array中的每个元素一定按vec4的stride进行align
    • 如果知道attribute名, 也可以通过glGetAttribLocation进行获取
    • 也可以在program link之前, 预先用glBindAttribLocation指定某个name的location(但不可以和layout qualifier冲突)
    • 获取location后, 调用glVertexAttribglVertexAttribPointer传递数据. 后者可以进一步把将对应的data buffer绑定到GL_ARRAY_BUFFER/GL_ELEMENT_ARRAY_BUFFER. 对同一个location, constant/array(包含VBO)这2种模式可以同时指定, 通过glEnableVertexAttribArray启用后者

    VAO: vertex array pointer

    如上所述, 在GLES3.0前, 有三种提供vertex attributes的方式

    1. constant vertex attribute glVertexAttrib
    2. client vertex array glVertexAttribPointer withglEnableVertexAttribArray
    3. VBO, glVertexAttribPointer with buffer bound to GL_ARRAY_BUFFER / GL_ELEMENT_ARRAY_BUFFER

    事实上, 上述API更改的是当前active的VAO对象. 通过预先配置好不同的VAO, 并且实时切换, 可以快速提供一组新的对象给GPU绘制.
    默认有一个VAO(id是0), glGenVertexArrays可以生成额外的, 不同的VAO用glBindVertexArray切换

    Uniforms

    Uniforms是全局constant, vertex shader和fragment shader中每次执行都获取相同的值. 但uniform有2种定义方式.

    • 使用uniform Type identifier;定义的uniform, 位于匿名的default uniform group
    • 也可以通过uniform Name{ Type identifier; }方式定义一个实名为Name的uniform group.
      • 使用layout(std140)可以使用标准化的布局, 便于在host app中准备数据

    和vertex attributes一样, 可以从program中获取大量信息

    • 调用glGetProgram提供GL_ACTIVE_UNIFORMSGL_ACTIVE_UNIFORM_MAX_LENGTH, 可以获知indexCount和max name length. 这边获取的param是所有包含于任何default/named uniform group的uniforms的值.
    • 以index为0..<indexCount范围内的值调用glGetActiveUniform可以一次性获取uniform的name, type, size等参数, 这一点和attribute类似. 除此之外, 还可以调用glGetActiveUniformsiv批量获取一组index的信息, 这个方法主要支援的是隶属于named uniform block的uniforms, 可以额外获取该uniform隶属的uniform block的index, 以及其在block中的offset/stride等属性; 如果对default uniform block中的uniform调用此方法, 上面这些参数值只能取到-1.

    named uniform block是gles 3.0新增概念, 对于uniform block本身也有metadata可以获取

    • 调用glGetProgram提供GL_ACTIVE_UNIFORM_BLOCKSGL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, 可以获取block的indexCount和max name Length. 不包括default uniform block.
    • 提供0..<indexCount范围内的值, 给glGetActiveUniformBlockName可以获取到block的name, 而glGetActiveUniformBlockiv可以获取到更多param, 包括buffer binding, size; 最终要的属性是该bblock所包含的uniform列表, 可以按uniform的global index进行索引.

    Host app提供uniform data和attribute也有两种方式, trivial value/buffer. 同样我们一般拥有先验知识: uniform的name. 而想要提供数据, 无论如何, 也都需要首先获取到shader中uniform的位置.

    • 对于default uniform block中的uniform, 和attribute类似, 需要获取location, 该值和index不是一个概念:
      • glGetUniformLocation可以根据uniform的name查询location
      • 获取到location后, 使用glUniform传递data即可
    • 对于named uniform block, 即使已经获取到了成员的index(无论是通过glGetUniformIndices直接由name获取, 还是通过获取到block index后, 使用glGetActiveUniformBlock间接获取), 也无法通过glGetUniformLocation获取location.
      • 必须在通过glGetActiveUniformBlock获取到uniform block的index后, 调用glUniformBlockBinding将该block和一个user-defined的binding point联系起来.
      • 紧接着, 将一个bind到GL_UNIFORM_BUFFERtarget的data buffer, 通过glBindBufferBase/glBindBufferRange和该binding point进行关联. 此时buffer中的data即可传递. (事实上这2个方法可以同时bind到这个index binding point, 同时bind到这个target; 因此有时可以省去一次单独的glBindBuffer)

    Buffers

    in gpu/ opengl controlled

    Types

    • uniform (block )buffer
    • vertex array buffer
    • vertex element buffer

    Copy

    gpu memory 1 -> gpu memory 2

    Map

    gpu memory -> client

    DrawCalls

    • drawArrays
    • drawElements
    • instanced drawing
    • drawing query object
      • Q: if we enable instance divisor on an indexed per-vertex attribute, what will happen?
        A: it will behavior as per-instance, ignoring indexing

    Shaders

    Vertex Shader

    Fragment Shader

    • gl_PointCoord, 用于GL_POINTS绘制时, 如果VS输出的gl_PointSize大于1, 则每个fragment会指示自己位于整个point的哪个位置.
      • 注意: 左上角为0, 0, 右下角为1, 1. 此坐标系为OpenGL特例! .
      • 可以方便用来实现point sprite的纹理渲染

    相关文章

      网友评论

          本文标题:OpenGL/GLES Notes

          本文链接:https://www.haomeiwen.com/subject/bpyvuxtx.html