上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的。

这节我们将为这两个三角形进行更加自由的着色——五个顶点各自使用不同的颜色。

要实现这个目的,我们分两步进行,首先

在顶点数组里增加数据用来表示颜色

修改sendDataToOpenGL()函数中的verts数组:

     GLfloat verts[] =
{
+0.0f, +0.0f, //Vertex 0
+1.0, +0.0, +0.0f, //Color 0
+1.0f, +1.0f, //Vertex 1
+0.0, +1.0, +0.0f, //Color 1
-1.0f, +1.0f, //Vertex 2
+0.0, +0.0, +1.0f, //Color 2
-1.0f, -1.0f, //Vertex 3
+0.5f, +0.3f, +0.1f,//Color 3
+1.0f, -1.0f, //Vertex 4
+0.1f, +0.4f, +0.2f,//Color 4
};

增加了5*3=15个元素,穿插在每个顶点位置后,表示颜色的r,g,b值。现在每5个数据描述一个顶点,前两个表示顶点位置,后三个表示颜色。

为了把这些数据输入到GPU,我们还需要启用第二个通道。(我们之前只启用了一个通道0)

修改sendDataToOpenGL()函数:

 void MyGlWindow::sendDataToOpenGL()
{
GLfloat verts[] =
{
+0.0f, +0.0f, //Vertex 0
+1.0, +0.0, +0.0f, //Color 0
+1.0f, +1.0f, //Vertex 1
+0.0, +1.0, +0.0f, //Color 1
-1.0f, +1.0f, //Vertex 2
+0.0, +0.0, +1.0f, //Color 2
-1.0f, -1.0f, //Vertex 3
+1.0f, +1.0f, +0.0f,//Color 3
+1.0f, -1.0f, //Vertex 4
+0.0f, +1.0f, +1.0f,//Color 4
}; GLuint vertexBufferID;
glGenBuffers(, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); GLushort indices[] =
{
,,,
,,,
};
GLuint indexBufferID;
glGenBuffers(, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, sizeof(GLfloat) * , ); glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, sizeof(GLfloat) * , (char*)(sizeof(GLfloat) * ));
}

注意第33行,函数glVertexAttribPointer函数第三个参数变成了sizeof(GLfloat)*5,原因是Stride变成了5个float,如前所述,5个元素描述一个顶点。

另外增加了第35和36行,35行开启了通道1,这个1和前面的0是和Shader中的layout (location = x)对应的,稍后进行详解。

第36行glVertexAttribPoint函数的第一个参数对应35行的1, 第二个参数表示三个元素为一组。

需要特别注意的是最后一个参数,它表示本组数据的起始偏移值,本组数据的第一个位置在代码中的第六行,它前面有2个元素,所以这里是sizeof(GLfloat)*2,但是由于该函数第四个参数的类型是char*类型,我们只能强制转换为char * 。

然后我们需要

修改Shader

 const char* vertexShaderCode =
" #version 430 \r\n"
" \r\n"
" in layout(location=0) vec2 position; \r\n"
" in layout(location=1) vec3 vertexColor; \r\n"
" \r\n"
" out vec3 passingColor; \r\n"
" \r\n"
" void main() \r\n"
" { \r\n"
" gl_Position= vec4(position,0.0,1.0); \r\n"
" passingColor= vertexColor; \r\n"
" } \r\n"
" \r\n"
" \r\n"; const char* fragmentShaderCode =
" #version 430 \r\n"
" \r\n"
" in vec3 passingColor; \r\n"
" out vec4 finalColor; \r\n"
" \r\n"
" \r\n"
" void main() \r\n"
" { \r\n"
" finalColor = vec4(passingColor,1.0); \r\n"
" } \r\n"
" \r\n"
" \r\n";

先看Vertex Shader。

增加了第5行。

仔细看一下第4行和第5行,对比sendDataToOpenGL()函数的33和36行, location=0指定了通道0, vec2说明了需要二维向量(2个float),33行函数的前两个参数也分别是0(表示通道0),2(表示两个元素),两者是相对应的。

ShaderCode的第5行和sendDataToOpenGL()的36行也是对应的。

再对应verts[]数组对比着看,就会发现其工作原理。verts数组每五个元素为一组,每组的前两个元素将被发送到通道0,后三个元素将被发送到通道1。

另外Vertex Shader还增加了第7行,这里使用了out关键字定义了一个三维向量passingColor,说明这个参数将被发送出去,传递到渲染管线的下一个环节。而在main中,我们把刚刚从通道2接受到的数据(存在vertexColor里)传递给passingColor。所以说相当于我们没有对通道2传递进来的数据做任何处理,直接发送到下一个环节。

观察Fragment Shader,我们增加了20行,注意看这行和Vertex Shader的第7行非常相似,除了第一个关键字改成了in。

这种匹配是GLSL的一种固定模式,上游的out 变量会传递给下游的in变量,只要两者保持一致性。

在Fragment Shader的main中,我们把最终的颜色输出改成了 vec4(passingColor,1.0),也就是我们把这个颜色表现了出来。

纵观全局,我们这次做的修改将把verts数组中新增的一些信息传递先传递到Vertex Shader中,然后传递到FragmentShader中,最终输出成顶点的颜色。

编译运行我们看到两个彩色的三角形:

3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader的更多相关文章

  1. 3D Computer Grapihcs Using OpenGL - 11 Model View Projection Matrices

    本节我们将绘制一个3维物体,立方体. 如果要渲染3D物体,我们需要了解MVP(Model View Projection),它表示三个转换矩阵.实际上这个名字不够明确,更加确切的释义如下: Model ...

  2. 3D Computer Grapihcs Using OpenGL - 06 Vertex and Fragment Shaders

    从这里就接触到了可编程图形渲染管线. 下面介绍使用Vertex Shader (顶点着色器)和 Fragment Shader(像素着色器)的方法. 我们的目标是使用这两个着色器给三角形填充绿色. 添 ...

  3. 3D Computer Grapihcs Using OpenGL - 03 OpenGL Buffer Data

    本节绘制一个三角形,并讲解Buffer Object-缓冲对象 OpenGL的窗口坐标 屏幕中心为坐标原点,横向朝右为x正方向,纵向朝上为y正方向,最大值最小值分别为1,-1. Buffer Obje ...

  4. 3D Computer Grapihcs Using OpenGL - 09 Enable Depth Test

    启用Depth Test OpenGL是个3D绘图API,也就是说不只有xy坐标轴,还有第三个坐标轴z,z轴的方向是垂直于屏幕,指向屏幕内. 靠近人眼的方向是负方向,标准化设备坐标的最小值是-1, 最 ...

  5. 3D Computer Grapihcs Using OpenGL - 19 Vertex Array Object(顶点数组对象)

    大部分OpenGL教程都会在一开始就讲解VAO,但是该教程的作者认为这是很不合理的,因为要理解它的作用需要建立在我们此前学过的知识基础上.因此直到教程已经进行了一大半,作者才引入VAO这个概念.在我看 ...

  6. 3D Computer Grapihcs Using OpenGL - 16 使用DrawElementsInstanced绘制立方体

    我们使用15节学到的知识来绘制14节的立方体. 在第14节我们使用了两次glDrawElements实现了OpenGL实例化,发现这样仍然不太方便,如果需要绘制成千上万的立方体,就需要手写成千上万次的 ...

  7. 3D Computer Grapihcs Using OpenGL - 15 Draw Element Instanced

    友情提示:继续本节之前,需要保存此前的代码,本节为了试验,会对代码做一些修改,但后续的修改需要我们把代码返回之前的进度. OpenGL内置支持Instancing,有专门的函数来处理这件事情. 为了方 ...

  8. 3D Computer Grapihcs Using OpenGL - 14 OpenGL Instancing

    如果我们需要绘制两个(或者多个)一样的立方体(或者物体),只是位置.缩放.旋转不一样,那么我们可以不需要多次将这个物体的顶点信息.颜色信息等发送到显卡,而是发送一次,绘制多次,仅仅是每次绘制之前应用不 ...

  9. 3D Computer Grapihcs Using OpenGL - 10 Color Buffer

    本节我们将尝试利用三角形制作一个“走马灯”效果. 一个三角形如图示方式,从左向右依次移动. 先看一下代码: MyGlWindow.cpp #include <gl\glew.h> #inc ...

随机推荐

  1. 深入理解java:2.3.1. 并发编程concurrent包 之Atomic原子操作(循环CAS)

    java中,可能有一些场景,操作非常简单,但是容易存在并发问题,比如i++, 此时,如果依赖锁机制,可能带来性能损耗等问题, 于是,如何更加简单的实现原子性操作,就成为java中需要面对的一个问题. ...

  2. vps国外节点ubuntu修改时区重启不失效

    使用了tzselect方法,但是重启后时区又恢复到初始情况了,不得行. 使用下面的方法成功了: 1.将时区修改成上海时区 cp /usr/share/zoneinfo/Asia/Shanghai /e ...

  3. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  4. Nginx工作机制

    Nginx分为单工作进程和多工作进程两种模式.通常采用1个master+多个worker进程配合异步非阻塞的工作机制.master进程主要负责管理自身和下属的worker进程,worker负责处理请求 ...

  5. (Windows)Python第三方库手动安装教程(以lxml库为例)

    案例前提:已安装Python 已安装pip 1.进入官网https://www.lfd.uci.edu/~gohlke/pythonlibs/,搜索lxml库,下载到本地(放到Python目录下的Sc ...

  6. Hangfire

    参考 开源分布式Job系统,调度与业务分离-如何创建一个计划HttpJob任务

  7. 剑指offer-动态规划-贪心算法--剪绳子-python

    题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能 ...

  8. 【学习总结】快速上手Linux玩转典型应用-第2章-linux简介

    课程目录链接 快速上手Linux玩转典型应用-目录 目录 1. 什么是Linux 2. Linux能够做什么事情 3. Linux的学习方法 4. 忘掉Windows的所有东西 1. 什么是Linux ...

  9. 四、绑定SignaIR的用户管理

    一.用户分组(第一个默认我的好友,禁删和更改) 没有分组id,更改layim代码: 更改id即可. layui.define('jquery', function (exports) { " ...

  10. 最小可观(Minimal Observability Problem in Conjunctive Boolean Networks)

    论文链接 1. 什么是 conjunctive Boolean network (CBN) 仅仅包含and运算. 下面这个式子为恒定更新函数 2. 什么是可观 定义在时刻k是CBN的状态为 X(k) ...