精华内容
下载资源
问答
  • opengl渲染流程

    2020-02-26 20:01:15
    简单来说,opengl渲染流程主要包括顶点变换,图元装配,纹理计算或着色和光栅化四个阶段。 图片截至博客https://www.cnblogs.com/zhanglitong/p/3238989.html ...

    opengl渲染管线是一系列数据处理过程,作用是将应用程序的数据转换到最终渲染的图形。简单来说,opengl渲染流程主要包括顶点变换,图元装配,纹理或着色和光栅化四个阶段。

                                         

                                             图1(截至博客https://www.cnblogs.com/zhanglitong/p/3238989.html

    顶点变换:所有的图形在计算机中都是一串串数据,在三维坐标系中可以表示为一个N*3的矩阵,N为顶点的数量,3分别代表x、y、z位置坐标,顶点变换就是通过一系列矩阵变换在坐标系中对顶点进行平移、缩小\放大、旋转等操作;

    图元装配:图元装配就是告诉电脑怎么去连接这些顶点,例如三个点,可以画成一个三角形,也可以连成两条直线;

    着色,纹理:就是对图元进行颜色渲染或者纹理渲染,注意这里的颜色或者纹理并不代表可以实际看见,必须光栅化后输出帧缓存才能实际可见;

    光栅化:经过以上步骤,基本上一个图形就形成了,但是这个图形的坐标还是在自己的坐标系中,光栅化就是将图形的坐标转化为屏幕像素坐标,最终将图元的数学描述转化为用于显示在屏幕上的片段,然后通过帧缓存就可以在电脑上看到一个个美丽的图形。

    现代opengl渲染管线严重依赖着色器处理数据,如果不使用着色器,那么用opengl可以做到的可能只有清除窗口内容,因此下面从着色器的角度来讲opengl渲染流程。

    什么是着色器呢?opengl红宝书中是这么说的:它是图形硬件设备所执行的一类特殊函数,可以理解为专为图形处理单元(GPU)编译的一种小型程序,opengl内部自带了着色器的编译工具。opengl应用程序本质上可以分为两部分,cpu端,采用C++编写,GPU端,采用glsl语言编写(即着色器)。

    opengl红宝书第9版给出的渲染流程:顶点数据->顶点着色器(标准化设备坐标)->细分控制着色器->细分计算着色器->几何着色器->图元装配->裁剪和剪切->光栅化->片元着色器

    上面流程包含了目前opengl几乎所有的着色器,但是一般只有顶点着色器片元着色器是必须要的,其他着色器都是可选,但是如果有,相对渲染顺序不会变。

    顶点着色器:顶点着色器用于处理顶点相关的数据,一般就是变换矩阵、顶点的颜色、纹理坐标;

    这里说一下纹理坐标的事,这里纹理一般指图片,在opengl中,纹理坐标系表示如下:

    在opengl中,图片的长度归一化了为1,纹理坐标如(0,1)就表示图片的左上角,在顶点着色器中,纹理坐标的作用就是确定纹理该怎么贴到模型上,如可以正着贴,倒贴,斜贴等,这就需要通过纹理坐标与模型顶点数据对应来完成。

    要注意,一旦顶点坐标经过顶点着色器,它们就该是标准化设备坐标

    细分着色:细分着色包括细分控制着色器和细分计算着色器,细分控制着色器和细分计算着色器是相互依存的,要么都不要,要么都要,细分着色的作用就是通过面片(patch)来描述一个物体的形状。顶点着色器只能处理每个顶点关联的数据,而细分着色能通过面片的形式分割更多的数据点。细分示例如下图(其中黑色点表示输入的控制点,其他连接处的点就是通过面片细分出来的点):

    细分控制着色器:细分控制着色器的一个常见应用就是将输入面片顶点(控制点)传递给细分计算着色器和通过设置细分层次因素,告诉opengl怎么生成顶点,每个顶点的标注化二维坐标(细分坐标)以二维向量(也就是说只有其x和y分量是有效的)的方式保存在变量gl_TessCorrd内,该变量会被传递到细分计算着色器中(注:gl_TessCorrd保存的是一个线段的因子,如一个线段的0.5横坐标处,那么gl_TessCorrd.x=0.5);

    细分计算着色器:细分控制着色器完成后,细分计算着色器就通过控制点和细分坐标生成一系列顶点坐标,输出跟顶点着色器是一样的。

    细分着色器更具体的可以看文章https://www.jianshu.com/p/3d974e69f842

    几何着色器:几何着色器提供了一种更加灵活的图元生成方法,它能够将(这一组)顶点变换为完全不同的图元,并且还能生成比原来更多的顶点。原理上来说,几何着色器通过一些手段也可以完成细分着色器的任务,但是为什么需要细分着色器呢?这是因为在某些图元生成上,细分着色器可以更加精确或者方便,比如生成三角形网格顶点。

    顶点着色器可以参考博客https://blog.csdn.net/cui6864520fei000/article/details/89949871

    综上,我们可以看到,顶点着色器,细分着色器和几何着色器本质上都是对顶点进行处理,因而可以归到图1顶点变换的范畴中。

    裁剪和剪切:opengl红宝书中流程中提到了裁剪和剪切,这是一种视口变换,即顶点可能落在我们要绘制的窗口区域以外,视口变换原理很简单,这里不多加赘述。

    片元着色器:片元着色器是opengl渲染的最后一个流程,它的主要作用就是赋予我们图形最终的颜色,纹理渲染也在这个阶段,这里要跟顶点着色器区别一下,顶点着色器只是得到纹理坐标,最终还是要传递到片元着色器,用具体的纹理(如一张图片)来渲染。

    还有颜色要注意一下,我们可以看到顶点着色器可以每个顶点赋予一个颜色值,那么当传递到片元着色器,如果片元着色器不做其他处理,那么片元将会自动根据顶点颜色进行插值;

    //片元着色器
    in vec4 Color;//顶点着色器传递过来的每个顶点的颜色
    void main
    {
     FragColor = Color;
    }

    opengl渲染的大概流程就是这样,因为平时工作中用到opengl并不是很多,更多是用基于opengl的高级引擎,即使用到opengl一般也大多用它的固定管线模式,因此可能出现错误,请多多指正。

    展开全文
  • OpenGLOpenGL渲染流程详解

    万次阅读 多人点赞 2017-12-24 18:56:45
    查阅过很多资料,在OpenGL的整个渲染流程中很多资料上描述的过程大致相同却又略去了很多细节,可以说是每一份资料的描述都不尽相同,或许每个作者所阐述的重点都不太相同,不存在孰对孰错 例如:《OpenGL ES 3.0...

    查阅过很多资料,在OpenGL的整个渲染流程中很多资料上描述的过程大致相同却又略去了很多细节,可以说是每一份资料的描述都不尽相同,或许每个作者所阐述的重点都不太相同,不存在孰对孰错

    • 例如:《OpenGL ES 3.0编程指南》中对可编程管线的流程介绍如下:

      1. VBO/VAO(顶点缓冲区对象或顶点数组对象)
      2. VertexShader(顶点着色器)
      3. rasterization(光栅化)
      4. FragmentShader(片段着色器)
      5. Per-Fragment Operations(逐片段操作)
        • pixelOwnershipTest(像素归属测试)
        • ScissorTest(剪裁测试)
        • StencilTest and DepthTest(模板和深度测试)
        • Blending(混合)
        • dithering(抖动)
      6. Frame Buffer (帧缓冲区)
    • 又例如:《实时计算机图形学》一书中,将图形绘制管线分为三个主要阶段:应用程序阶段、几何阶段、光栅阶段

      1. 应用程序阶段:
        • 主要和CPU、内存进行交互,在此阶段有碰撞检测、场景图建立、空间八叉树更新、视锥剪裁等算法都在此阶段执行
        • 几何体数据(顶点坐标、法向量、纹理坐标、纹理等)这些信息会通过数据总线传送到图形硬件数据总线规范了一个大的集成应用系统中同构系统、异构系统等方面进行数据共享和交换实现方法。 系统间数据交换标准
      2. 几何阶段:
        • 顶点坐标变换、光照、剪裁、投影、屏幕映射 均在GPU进行运算(顶点着色器就在此阶段执行
        • 该阶段的末端会得到经过变换和投影之后的顶点坐标、颜色、纹理坐标,这些数据将作为光栅化阶段的输入进一步处理
      3. 光栅阶段:
        • 光栅化:决定哪些像素被集合图元覆盖的过程(其实就是将图元拆分成多个片段的过程,图元是由几个点组成的点、线、面)
          • 例如:面形状的图元最少3个点(A、B、C三个点)即可组成,那么屏幕是由众多个像素点组成的,那ABC三个点围成的三角形中有多少个像素点呢?那么其实光栅化就是用来分解图元得到这些像素点的过程,当然这其中还有一个重要的过程就是插值,插值出那个图形区域的像素(纹理坐标v_texCoord、颜色等信息)。注意,此时的像素并不是屏幕上的像素,是不带有颜色的。接下来的片段着色器完成上色的工作。
          • 注意:光栅化不是着色的阶段!片段着色器才是给每个像素绘制颜色的阶段,我在很多博客上都看到过错误的讲解,都有提到光栅化是上色的过程
        • 着色器上色

    以上,都是关于流程的简要过程,下面会详细的描述整个渲染流程


    渲染管线详解

    下面这个图取自《OpenGL ES 3.0编程指南》,此流程为可编程管线。
    这里写图片描述

    1. VBO/VAO(顶点缓冲区对象或顶点数组对象):
      VBO/VAO(到底是啥,下回讲解)是cpu提供给GPU的顶点信息,包括了顶点的位置、颜色(只是顶点的颜色,和纹理的颜色无关)、纹理坐标(用于纹理贴图)等顶点信息。

    2. VertexShader(顶点着色器):
      顶点着色器是处理VBO/VAO提供的顶点信息的程序。VBO/VAO提供的每个顶点都执行一遍顶点着色器。Uniforms(一种变量类型)在每个顶点保持一致,Attribute每个顶点都不同(可以理解为输入顶点属性)。执行一次VertexShader输出一个Varying(可变变量)和gl_positon。

      • 顶点着色器的输入包括:

        • 着色器程序:描述顶点上执行操作的顶点着色器程序源代码或者可执行文件
        • 顶点着色器输入(或者属性):用顶点数组提供的每个顶点的数据
        • 统一变量(uniform):顶点/片段 着色器使用的不变数据
        • 采样器(Samplers):代表顶点着色器使用纹理的特殊统一变量类型

        这里写图片描述

      • 重点:VertexShader就是顶点着色器编程可以操作的阶段,用于控制顶点坐标的转换过程,片段着色器控制着每个像素颜色的计算过程

      • 该阶段在很多书中被描述为几何阶段:原因是,例如3D模型输入到计算机中是一系列的三维顶点,但最终我们都需要将其转换为能在2D屏幕上可见的二维坐标,所以就需要一个三维坐标转换二维坐标的转换过程,在一些面试中会问到有具体哪些转换步骤,步骤如下:

        先说说坐标类型:
        Object Space(模型坐标空间)
        World Space(世界坐标空间)
        Eye Space(观察坐标空间)
        Clip and Project Space(屏幕坐标空间)

      • 顶点坐标空间变换流程:
        1. Object Space到World Space
          • 模型坐标空间有2层核心含义:
            • 其一:模型文件中的顶点值,这些数据是在建模的时候得到的,例如说用3D MAX建模并导出一个.max文件,文件中包含的数据就是object space coordinate
            • 其二: object space coordinate与任何物体都没有参照关系,这个概念很重要,相当于是一个相对于坐标原点的具体位置,但是导入计算机之后这个模型还应该被赋予一个世界坐标(例如说一个人在中国-北京-天安门-国旗下)是一个具体的位置,而不是本地坐标(比如说在二楼的最左边第一个房间,这是参照当前这栋楼而言的一个位置),那么从object space coordinate转换到world space coordinate这个变换过程由一个四阶矩阵控制,通常叫做world matrix
          • 光照计算:通常都是在world space coordinate中进行,符合人类常识
          • 顶点法向量:在模型文件中属于object space,然而在GPU的顶点着色器程序中必须将法向量转换到world space中才能使用,需要注意的是这个转换不能使用world matrix这个转置矩阵!!!而是需要使用world matrix的逆矩阵,这个错误非常的难以发现
        2. World Space到Eye Space
          • 这个转换不难理解,同人类一样,对每个人而言,都是从自己的双眼去观察这个世界,我们的眼镜就相当于是eye space,所以计算机也一样,每次的渲染都是从某一个视角去渲染物体,游戏中通常摄像机就是eye space
          • eye space概念:视点(camera、相机、眼睛)为原点,由视线的方向、视角范围、远近平面,组成一个梯形的三维空间,我们称之为 viewing frustum(视锥)
          • 这里写图片描述
          • 超出这个梯形范围的物体将会被剔除,也就是说我们看不见,这项技术被称之为Furstum Culling(视锥剪裁)
        3. Eye Space到Clip and Project Space
          • 在视锥体中(那个不规则的梯形)进行剪裁并非易事,所以图形学前辈们精心分析之后,剪裁被安排到一个单位立方体中进行,该立方体的对角顶点分别是(-1,-1,-1)和(1,1,1),称之为规范立方体(简称CVV:Canonical view volume),CVV的近平面(梯形较小的矩形面)对应的屏幕像素坐标是(左下角的0,0)
          • 1.把视锥体变换到CVV中,这个过程就是“投影”,投影的方法有2种:正投影(平行投影)和透视投影,一般在游戏里都有这两种类型的摄像机,正投影就好像一个无限延伸的长方体,透视投影就好像是一个梯形
          • 2.确定只有图元完全或者一部分在视锥体内部的时候,才需要进行光栅化
            • 如果图元完全在视锥体内部:该图元直接进入下一个阶段
            • 如果图元部分在视锥体内部:进行剪裁处理,详细的剪裁算法大家自行查阅一下《计算机图形学》第12章第5节
            • 如果图元完全不在视锥体内部:直接剔除

      3.Primitive Assembly(图元装配):
      顶点着色器下一个阶段是图元装配,图元(prmitive)是三角形、直线或者点精灵等几何对象。这个阶段,把顶点着色器输出的顶点组合成图元。

      • 将顶点数据根据Primitive(原始链接关系)还原出网格结构,网格由顶点和索引组成,在此阶段根据索引将顶点链接在一起,组成点、线、面三种不同的图元,之后就是对超出屏幕的三角形进行剪裁,如果三角形ABC三个顶点其中一个点在屏幕的外面,另外两个点在屏幕里面,其实屏幕上看到的应该是个四边形,然后再将这个四边形切成2个小的三角形
      • 简而言之,将顶点着色器计算之后得到的点根据链接关系组成点、线、面(三角形)

    4.rasterization(光栅化):

    • 光栅化是将图元转化为一组二维片段的过程,然后,这些片段由片段着色器处理(片段着色器的输入)。这些二维片段代表着可在屏幕上绘制的像素。用于从分配给每个图元顶点的顶点着色器输出生成每个片段值的机制称作插值(Interpolation)。这句不是人话的话解释了一个问题,就是从cpu提供的分散的顶点信息是如何变成屏幕上密集的像素的,图元装配后顶点可以理解成变为图形,光栅化时可以根据图形的形状,插值出那个图形区域的像素(纹理坐标v_texCoord、颜色等信息)。注意,此时的像素并不是屏幕上的像素,是不带有颜色的。接下来的片段着色器完成上色的工作。

      问题1:如果该图元是点线面中的“点”,那么它的坐标为浮点数,但是像素是由整数来表示的,如何正确计算屏幕坐标所对应的像素?
      答: 根据《计算机图形学(第二版)》52页示例:如果一条线段的位置是(10.48,20.51),那么转换到像素的位置则是(10,21)也就是我们说的四舍五入

      问题2:为什么通过三个点就能自动连接成一个三角形,如果有ABCDEFG….很多个点,如何知道ABC三个点需要组成三角形,而不是用AFG组成三角形?
      答:这个问题涉及到划线算法和区域图元填充算法
      划线算法有:DDA算法、Bresenham划线算法
      区域图元填充算法有:扫描线多边形填充算法、边界填充算法

      更多详细的算法内容可以查阅《计算机图形学》第三章

    5.FragmentShader(片段着色器):
    片段着色器为片段(像素)上的操作实现了通用的可编程方法,光栅化输出的每个片段都执行一遍片段着色器,对光栅化阶段生成每个片段执行这个着色器,生成一个或多个(多重渲染)颜色值作为输出。
    这里写图片描述

    6.Per-Fragment Operations(逐片段操作)

    • 在该阶段,每个片段都会执行下面的5个操作

    这里写图片描述

    附上一张中文翻译图,嘿嘿~

    这里写图片描述
    (1)pixelOwnershipTest(像素归属测试):

    • 这个用来确定帧缓冲区中位置(x,y)的像素是不是归当前上下文所有。例如,如果一个显示帧缓冲区窗口被另一个窗口所遮蔽,则窗口系统可以确定被遮蔽的像素不属于此opengl的上下文,从而不显示这些像素。

    (2)ScissorTest(剪裁测试):

    • 如果该片段位于剪裁区域外,则被抛弃

    (3)StencilTest and DepthTest(模板和深度测试):

    • 深度测试比较好理解,若片段着色器返回的深度小于缓冲区中的深度,则舍弃。模板测试没有用过,不清楚具体功能,猜测功能应该和名字一样,模板形状内可通过。

    (4)Blending(混合):

    • 将新生成的片段颜色值与保存在帧缓冲区的颜色值组合起来,产生新的RGBA。

    (5)dithering(抖动):

    • 在逐片段操作阶段的最后,片段要么被拒绝,要么在帧缓冲区(x,y)的某个位置写入片段的颜色,深度或者模板值。写入片段颜色,深度和模板值取决于弃用的相应写入掩码。写入掩码可以更精确的控制写入相关缓冲区的颜色、深度和模板值。例如:可以设置颜色缓冲区的写入掩码,使得任何红色值都不能被写入颜色缓冲区。

    最后把产生的片段放到帧缓冲区(前缓冲区或后缓冲区或FBO)中,若不是FBO,则屏幕绘制缓冲区中的片段,产生屏幕上的像素。

    展开全文
  • OpenGL渲染流程

    2017-04-17 20:56:32
    推酷 文章站点主题活动APP 荐 ...OpenGL渲染流程 时间 2015-12-23 01:56:00 博客园-原创精华区 原文 http://www.cnblogs.com/BigFeng/p/5068715.html 主题 OpenGL 一.什么是openGL OpenG
     
    

    OpenGL渲染流程

    一.什么是openGL

    OpenGL被定义为“图形硬件的一种软件接口”。从本质上说,它是一个3D图形和模型库,具有高度的可移植性,具有非常快的速度。

    二.管线

    管线这个术语描述了opengl渲染的整个过程。openGL采用cs模型:c是cpu,s是GPU,c给s的输入是 vertex信息和Texture信息 ,s的输出是显示器上显示的图像。下面这2个图比较清楚的讲解了opengl的渲染管线。 

    相信没有opengl基础的应该看不懂,下面会简单的介绍这个流程,再看下文之前,建议先看 GPU大百科全书系列文章 ,对理解opengl工作原理绝对有帮助。

    三.管线详解

    下面这个图取自《 OpenGL ES 3.0编程指南 》,此流程为可编程管线。

    1.VBO/VAO(顶点缓冲区对象或顶点数组对象):

    VBO/VAO(到底是啥,下回讲解)是cpu提供给GPU的顶点信息,包括了顶点的位置、颜色(只是顶点的颜色,和纹理的颜色无关)、纹理坐标(用于纹理贴图)等顶点信息。

    2.VertexShader(顶点着色器):

    顶点着色器是处理VBO/VAO提供的顶点信息的程序。 VBO/VAO提供的每个顶点都执行一遍顶点着色器 。Uniforms(一种变量类型)在每个顶点保持一致,Attribute每个顶点都不同(可以理解为输入顶点属性)。 执行一次VertexShader输出一个Varying和gl_positon。

    3.PrimitiveAssembly(图元装配):

    顶点着色器下一个阶段是图元装配,图元(prmitive)是三角形、直线或者点精灵等几何对象。这个阶段,把顶点着色器输出的顶点组合成图元。

    4.rasterization(光栅化):

    光栅化是将图元转化为一组二维片段的过程,然后,这些片段由片段着色器处理(片段着色器的输入)。这些二维片段代表着可在屏幕上绘制的像素。 用于从分配给每个图元顶点的顶点着色器输出生成每个片段值的机制称作插值(Interpolation) 。这句不是人话的话解释了一个问题,就是从cpu提供的分散的顶点信息是如何变成屏幕上密集的像素的,图元装配后顶点可以理解成变为图形,光栅化时可以根据图形的形状,插值出那个图形区域的像素(纹理坐标v_texCoord、颜色等信息)。注意,此时的像素并不是屏幕上的像素,是不带有颜色的。接下来的片段着色器完成上色的工作。

    5. FragmentShader( 片段着色器 ):

    片段着色器为片段(像素)上的操作实现了通用的可编程方法, 光栅化输出的每个片段都执行一遍片段着色器 ,对光栅化阶段生成每个片段执行这个着色器,生成一个或多个(多重渲染)颜色值作为输出。

    6.Per-Fragment Operations(逐片段操作)

    在此阶段,每个片段上执行如下功能:

    (1)pixelOwnershipTest(像素归属测试):

    这个用来确定帧缓冲区中位置(x,y)的像素是不是归当前上下文所有。例如,如果一个显示帧缓冲区窗口被另一个窗口所遮蔽,则窗口系统可以确定被遮蔽的像素不属于此opengl的上下文,从而不显示这些像素。

    (2)ScissorTest(剪裁测试):

    如果该片段位于剪裁区域外,则被抛弃

    (3)StencilTest and DepthTest(模板和深度测试):

    深度测试比较好理解,若片段着色器返回的深度小于缓冲区中的深度,则舍弃。模板测试没有用过,不清楚具体功能,猜测功能应该和名字一样,模板形状内可通过。

    (4)Blending(混合):

    将新生成的片段颜色值与保存在帧缓冲区的颜色值组合起来,产生新的RGBA。

    (5)dithering(抖动):

    不知道这个是神马作用?

    最后把产生的片段放到帧缓冲区(前缓冲区或后缓冲区或FBO)中,若不是FBO,则屏幕绘制缓冲区中的片段, 产生屏幕上的像素 。

    7.固定管线

    固定管线是没有shader参与的OpenGL绘制管线,OpenGL3.0已经废除了这个功能。固定管线的流程如下所示:

    代码示例:

    #include <iostream>
    #include <GLUT/GLUT.h>
    #include <OpenGL/gl.h>
    
    void RenderScene(void) {
        glClear(GL_COLOR_BUFFER_BIT);
        
        glShadeModel(GL_SMOOTH);
        
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        
        glBegin(GL_TRIANGLES);
        glColor3ub((GLubyte)255, (GLubyte)0, (GLubyte)0);
        glVertex3f(0, 200, 0);
        
        glColor3ub((GLubyte)0, (GLubyte)255, (GLubyte)0);
        glVertex3f(200, -70, 0);
        
        glColor3ub((GLubyte)0, (GLubyte)0, (GLubyte)255);
        glVertex3f(-200, -70, 0);
        
        glEnd();
        glutSwapBuffers();
    }
    
    void SetupRC(void) {
        glClearColor(0, 0, 0, 1);
    }
    
    void changeSize(int w, int h) {
        GLfloat windowHeight, windowWidth;
        
        if (h == 0) {
            h = 1;
        }
        
        glViewport(0, 0, w, h);
        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        
        windowHeight = windowWidth = 250;
        
        glOrtho(-windowWidth, windowWidth, -windowHeight, windowHeight, -1, 1);
    }
    
    int main(int argc, char * argv[]) {
        
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(600, 600);
        
        glutCreateWindow("Simple");
        
        const GLubyte * info = glGetString(GL_VERSION);
        std::cout << ( const char *)info << std::endl;
        
        glutReshapeFunc(changeSize);
        glutDisplayFunc(RenderScene);
        SetupRC();
        
        glutMainLoop();
        
        return 0;
    }

    效果为:

    8.可编程管线:

    OpenGL 2.0引入了可编程管线,shader得到支持,流程如下图所示:

    要得到相同的效果,代码如下:

    #include <iostream>
    #include <GLUT/GLUT.h>
    #include <OpenGL/gl.h>
    
    GLuint createShader(GLenum type, const char * shaderSrc) {
        GLuint shader;
        GLint compiled;
        
        shader = glCreateShader(type);
        
        if (shader == 0) {
            return 0;
        }
        
        glShaderSource(shader, 1, &shaderSrc, NULL);
        
        glCompileShader(shader);
        
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen > 1) {
                char * infoLog = (char *)malloc(sizeof(char) * infoLen);
                glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
                
                std::cout << "Error compiling shader: " << infoLog << std::endl;
                
                free(infoLog);
            }
            glDeleteShader(shader);
            return 0;
        }
        
        return shader;
    }
    
    GLuint programObject;
    
    bool init() {
        //todo 读文件
        char * vShaderStr =
        "attribute vec4 vPositon;  \n"
        "attribute vec4 aColor;    \n"
        "varying vec4 vertexColor; \n"
        "void main() {             \n"
        "   gl_Position = gl_ModelViewProjectionMatrix * vPositon; \n"
        "   vertexColor = aColor; \n"
        "}"
        ;
        
        char * fShaderStr =
        "varying vec4 vertexColor;"
        "void main() {"
        "   gl_FragColor = vertexColor;"
        "}"
        ;
        
        GLuint vertexShader;
        GLuint fragmentShader;
    
        GLint linked;
        
        vertexShader = createShader(GL_VERTEX_SHADER, vShaderStr);
        fragmentShader = createShader(GL_FRAGMENT_SHADER, fShaderStr);
        
        programObject = glCreateProgram();
        
        if (programObject == 0) {
            return false;
        }
        
        glAttachShader(programObject, vertexShader);
        glAttachShader(programObject, fragmentShader);
        
        glLinkProgram(programObject);
        
        glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
        
        if (!linked) {
            GLint infoLen = 0;
            glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
            
            if (infoLen > 1) {
                char * infoLog =(char *)malloc(sizeof(char) * infoLen);
                
                glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
                
                std::cout << "Error linking program: " << infoLog << std::endl;
                free(infoLog);
            }
            glDeleteProgram(programObject);
            return false;
        }
        glClearColor(0, 0, 0, 0);
        
        return true;
    }
    
    void RenderScene(void) {
        GLfloat vVerties[] = {
            0, 200, 0,
            200, -70, 0,
            -200, -70, 0
        };
        
        GLfloat vertexColor[] = {
            1,0,0,1,
            0,1,0,1,
            0,0,1,1
        };
        
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(programObject);
        
        GLint attributePos = glGetAttribLocation(programObject, "vPositon");
        glVertexAttribPointer(attributePos, 3, GL_FLOAT, GL_FALSE, 0, vVerties);
        glEnableVertexAttribArray(attributePos);
        
        GLint colorPos = glGetAttribLocation(programObject, "aColor");
        glVertexAttribPointer(colorPos, 4, GL_FLOAT, GL_FALSE, 0, vertexColor);
        glEnableVertexAttribArray(colorPos);
        
        glDrawArrays(GL_TRIANGLES, 0, 3);
        
        glutSwapBuffers();
    }
    
    void changeSize(int w, int h) {
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        
        GLfloat windowHeight, windowWidth;
        
        windowHeight = windowWidth = 250;
        glOrtho(-windowHeight, windowHeight, -windowWidth, windowWidth, -1, 1);
        
    }
    
    int main(int argc, char * argv[]) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    
        glutInitWindowSize(600, 600);
        
        glutCreateWindow("Simple");
        
        glutReshapeFunc(changeSize);
        glutDisplayFunc(RenderScene);
        
        init();
        
        glutMainLoop();
        
        return 0;
    }
     
    我来评几句
    登录后评论

    已发表评论数(0)

    展开全文
  • OpenGL基本流程

    千次阅读 2018-03-02 10:41:33
    记录下自己画的一个OpenGL的基本流程

    记录下自己画的一个OpenGL的基本流程图OpenGL流程图

    展开全文
  • OpenGL工作流程

    2018-02-27 15:37:44
    转载自:http://blog.csdn.net/yqxx/article/details/382551通过上面的介绍,对OpenGL是有了一个总体的印象。下面来阐述在OpenGL中处理数据的三个阶段和这些阶段中OpenGL函数如何使用。 图1 ...
  • OpenGL入门详解(3.OpenGL基本流程)

    千次阅读 2019-01-06 20:54:35
    本系列文章主要从入门的角度总结OpenGL的基本流程概念和所使用的语言,尽量避免学的糊涂。 OpenGL宏观流程 先列一下整体处理流程: 读取顶点 顶点着色器 组装图元 光栅化图元 片段着色器 写入帧缓冲 显示在屏幕上 ...
  • OpenGL: OpenGL渲染流程

    千次阅读 2014-07-23 09:09:17
    物体坐标系:物体位于坐标系原点位置。视点坐标系:视点位于坐标系原点位置。 模型视图变换物体坐标系 ------------- 视点坐标系最近不怎么看ogl了,但是总有一些东西是需要记忆的:add 2012/12/11 - dizuo / ...
  • 《高效学习OpenGL》之 openGL工作流程

    千次阅读 2014-01-21 14:54:54
    OpenGl工作流程的输入端可以是图像或集合图元,但最终的结果都是光栅化后的对象这些对象进入帧缓冲区后,由硬件显示在输出设备上。 整个OpenGL的基本工作流程如下图: 其中几何顶点数据包括模型的顶点集、线...
  • OpenGL编程流程(简化版)

    千次阅读 2018-05-22 11:42:05
    OpenGL渲染流程 OpenGL渲染流程(管线)其实就是OpenGL执行将用户程序(CPU)定义的三维顶点数据,颜色数据,经过一系列转换最终渲染到计算机屏幕上的过程。 程序开发人员想要实现自己的OpenGL程序需要实现几部: ...
  • 20分钟让你了解OpenGL——OpenGL流程详细解读

    千次阅读 多人点赞 2021-01-31 09:45:24
    即使是一些对OpenGL有一些经验的开发者,往往也未必对OpenGL有完整、全面的理解。市面上的OpenGL文章往往零碎不成体系,而教材又十分庞大、晦涩难懂还穿插着各种API的介绍。 因此笔者希望通过多年的图形开发经验,...
  • OpenGL 渲染流程图解析

    2020-07-02 18:38:42
    OpenGL 渲染使用客户端<——>服务端的形式实现,客户端是我们编写的代码,服务端是计算机图形硬件厂商所提供的OpenGL实现。 由上图可见,渲染管线分为上下两个部分,上面一部分是客户端,下面一部分是服务端...
  • OpenGL渲染流程图示 按照上图简单分析一下: CPU的工作:通过读取模型数据(.Obj文件存储模型顶点信息,模型UV信息,模型顶点索引信息)传递给GPU。 GPU的工作:顶点着色器 -->>光栅化 -->> 片段着色器...
  • Android OpenGL开发流程(三)

    千次阅读 2017-03-29 16:05:35
    我们重点讲解开发OpenGL ES的流程 1.定义顶点着色器和片段着色器 第一节我们讲解的已经很细致了,为了便于理解在这里在详细的说明一下。并且换一种方式定义着色器。 我们知道第一篇定义...
  • 《高效学习OpenGL》之 openGL绘图流程

    千次阅读 2014-01-21 15:02:56
    1.设置像素格式 包括绘图风格、颜色模式、颜色位数 2.建立景物模型 根据基本图形单元创建 3.舞台布景 设置视点 4.效果处理 设置物体的材质,加入光照条件 5.光栅化 把模型信息转化为可在计算机上显示的像素信息
  • OpenGL工作流程 翻译自蓝宝书

    千次阅读 2008-10-07 17:35:00
    OpenGL工作流程通过上面的介绍,对OpenGL是有了一个总体的印象。下面来阐述在OpenGL中处理数据的三个阶段和这些阶段中OpenGL函数如何使用。 图1详细给出了OpenGL处理流水线(pipe line)的框图。图中左边有三条竖向...
  • OpenGL ES绘制流程理解

    2019-06-04 23:55:20
    OpenGL ES绘制流程理解
  • VS2019+win10x64+OpenGL安装流程

    千次阅读 2020-09-16 22:12:39
    课程要求安装OpenGL,老师给的教程是这个https://heavenkong.blogspot.com/2018/03/opengl-installation-of-opengl-with.html 有亿、、麻烦 写在前面: x64操作系统一定复制64位的lib和dll文件!!!! 步骤...
  • opengles 简要流程

    2016-06-06 18:38:25
    ref card : https://www.khronos.org/files/opengles20-reference-card.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,204
精华内容 9,281
关键字:

opengl的主要流程