• openGL一些概念01


    顶点数据:

    顶点数据是一系列顶点的集合。

    一个顶点(Vertex)是一个3d坐标的数据的集合。

    而顶点数据是用顶点属性(Vertex Attribute)表示的,它可以包含任何我们想用的数据

    (但是简单起见,我们还是假定每个顶点只有一个3D位置和一些颜色值组成的。)

    图元:

    为了让openGL知道我们的坐标和颜色值构成的到底是什么,openGL需要你去指定这些数据所表示的渲染类型。

    我们是希望把这些数据渲染成一系列的点?一系列的三角形?还是仅仅是一个长长的线?做出这些提示的叫做图元(Primitive)

    任何一个绘制指令的调用都将把图元传递给openGL。这是其中的几个:

    GL_POINTS 、GL_TRIANGLES、 GL_LINE_STRIP。

    图形渲染管线的第一个部分是顶点着色器(Vertex Shader),它把一个单独的顶点作为输入。

    顶点着色器主要的目的是把3D坐标转换为另一种3D坐标,同时顶点着色器允许我们对顶点属性进行一些基本处理。

    图元装配(Primitive Assembly)阶段将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),

    并所有的点装配成指定图元的形状;

    图元装配阶段的输出会传递给几何着色器(Geometry Shader)。几何着色器把图元形式的一系列顶点的集合作为输入,

    它可以通过产生新顶点构造出新的(或是其他的)图元来生成其他形状。

    几何着色器的输出会被传入光栅化阶段(Rasterization Stage),这里它会把图元映射为最终屏幕上相应的像素,

    生成供片段着色器(Fragment Shader)使用的片段(Fragment) 。在片段着色器运行之前会执行裁切(Clipping),

    裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

    OpenGL 中的一个片段是OpenGL渲染一个像素所需的所有数据。

    片段着色器的主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。

    通常片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。

     在所有对应颜色值确定以后,最终的对象将会被传到最后一个阶段,我们叫做Alpha测试和混合(Blending)阶段

    这个阶段检测片段的对应的深度(和模版(Stencil))值,用它们来判断这个像素是其他物体的前面还是后面,

    决定是否应该丢弃。这个阶段也会检查alpha值 并对物体进行混合(Blend)。

    然而,对于大多数场合,我们只需要配置定点和片段着色器就行了。几何着色器是可选的,通常使用它默认的着色器就行了。

    在现代OpenGL中,我们必须定义至少一个顶点着色器和一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。

    渲染一个2D的三角形,我们将它顶点的z坐标设置为0.0,这样子的话三角形每一点的深度(Depth) 都是一样的,从而使它看上去像是2D的。

    通常深度可以理解为z坐标,它代表一个像素在空间中和你的距离,如果离你远就可能被别的像素遮挡,你就看不到它了,它会被丢弃,以节省资源。

    标准化设备坐标(Normalized Device Coordinates,NDC)

    一旦你的顶点坐标已经在顶点着色器中处理过,它们就应该是标准化设备坐标了,

    标准化坐标是一个x、y和z值在-1.0到1.0的一小段空间。

    标准化设备坐标接着会变换为屏幕空间坐标(Screen-space Coordinates),这是使用你通过glViewport 函数提供的数据,进行视口变换(Viewport Transform)完成的。

    所得的屏幕空间坐标又会被变换为片段输入到片段着色器中。

    定义这样的顶点数据以后,我们会把它输入发送给图形渲染管线的第一个处理阶段:顶点着色器。

    它会在GPU上创建内存用于存储我们的顶点数据,还要配置OpenGL如何解释这些内存,并且指定其如何发送给显卡。

    我们通过顶点缓冲对象(Vertex Buffer Objects,VBO)管理这个内存。

    顶点缓冲对象是我们在OpenGL中第一个出现的OpenGL对象。

    这个缓冲有一个独一无二的ID,所以我们可以使用glGenBuffers 函数和一个缓冲ID生成一个VBO对象:

    GLuint VBO;
    glGenBuffers(1, &VBO);  

    OpenGL有很多缓冲对象类型,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER。OpenGL允许我们同时绑定多个缓冲,

    只要它们的是不同的缓冲类型。我们可以使用glBindBuffer 函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上:

    glBindBuffer(GL_ARRAY_BUFFER,VBO);

    从这一刻起,我们使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)。

    然后我们可以调用glBufferData函数,它会把之前定义的顶点数据复制到缓冲的内存中

    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    glBufferData是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数。

    1个参数是目标缓冲的类型;

    2个参数是指定传输数据大小(以字节为单位);

    3个参数是我们希望发送的实际数据;

    4个参数指定了我们希望显卡如何管理给定的数据。它有3种形式:

    GL_STATIC_DRAW :数据不会或几乎不会改变。

    GL_DYNAMIC_DRAW:数据会被改变很多。

    GL_STREAM_DRAW:数据每次绘制时都会改变。

    向量(Vector)它简明的表达了任意空间中的位置和方向,并且它有非常有用的数学属性。

    在GLSL中一个向量有最多4个分量,每个分量都代表空间中的一个坐标,它们可以通过vec.x、vec.y、vec.z和vec.w来获取。

    vec.w分量而是用在所谓透视划分(Perspective Division)上。

    在真实的程序里输入数据通常都不是标准化设备坐标,顶点着色器一般会先把它们转换至OpenGL的可视区域内。

    顶点着色器(VertexShader)

    const GLchar* vertexShaderSource = "#version 330 core 
                                       layout(location = 0) in vec3 position;    
                                       void main()    
                                       {    
                                       gl_Position = vec4(position.x,position.y,position.z,1.0);    
                                       }    
        "; 

    编译着色器

    编写之后的顶点着色器源码,为了能让OpenGL使用它,我们必须在运行时动态编译它的源码。

    首先创建一个着色器对象,注意还是用ID来引用的。所以我们存储这个顶点着色器为GLuint,

    然后用glCreateShader 创建这个着色器:

    GLuint vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);

    我们把需要创建的着色器类型以参数形式提供给glCreateShader。

    由于我们正创建一个顶点着色器,传递的参数是GL_VERTEX_SHADER。

    下一步我们把这个顶点着色器源码附加到着色器对象上,然后编译它:

    glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
    glCompileShader(vertexShader);

    glShaderSource函数参数:

    1个参数要编译的着色器对象;

    2个参数指定传递的源码字符串数量,上面这里只有一个;

     3个参数是顶点着色器真正的源码;

    4个参数我们先设置为NULL。

    如果想检测glCompileShader是否成功可以用glGetShaderiv 检查是否编译成功。如果失败可以用glGetShaderInfoLog获取错误信息。

    片段着色器(Fragment Shader)

    该着色器全是关于计算你的像素最后的颜色输出。

    const GLchar* fragmentShaderSource = "#version 330 core    
                                         out vec4 color;    
                                         void main()    
                                         {    
                                         color = vec4(1.0f,0.5f,0.2f,1.0f);    
                                         }    
        ";

    在计算机图形中颜色被表示为有4个元素的数组:红色、绿色、蓝色和alpha(透明度)分量,通常缩写为RGBA。

    每个分量的强度设置在0.0到1.0之间。

    编译片段着色器的过程与顶点着色器类似,只不过我们使用GL_FRAGMENT_SHADER常量作为着色器类型:

    GLuint fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,null);
    glCompileShader(fragmentShader);

     两个着色器现在都编译了,剩下的事情是把两个着色器对象链接到一个用来渲染的着色器程序(Shader Program)中。

    ------------------------------

    https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

  • 相关阅读:
    离线语音
    云知声语音开发
    自定义View -- 柱状图 我也来自定义个柱状图来玩玩
    android studio中如何替换gradle以防下载卡住
    如何查询当前手机的cpu架构,so库导入工程又出异常了?
    android 学习mvc 和 mvp 和 mvvm参考项目
    【整理】Android中EditText中的InputType类型含义与如何定义( 转 )
    Android点击EditText文本框之外任何地方隐藏键盘的解决办法
    Android开发 adb命令提示:Permission denied (转)
    Node.js-串行化流程控制
  • 原文地址:https://www.cnblogs.com/wainiwann/p/6702973.html
Copyright © 2020-2023  润新知