3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader
上节的最后我们实现了两个绿色的三角形,而绿色是直接在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的更多相关文章
- 3D Computer Grapihcs Using OpenGL - 11 Model View Projection Matrices
本节我们将绘制一个3维物体,立方体. 如果要渲染3D物体,我们需要了解MVP(Model View Projection),它表示三个转换矩阵.实际上这个名字不够明确,更加确切的释义如下: Model ...
- 3D Computer Grapihcs Using OpenGL - 06 Vertex and Fragment Shaders
从这里就接触到了可编程图形渲染管线. 下面介绍使用Vertex Shader (顶点着色器)和 Fragment Shader(像素着色器)的方法. 我们的目标是使用这两个着色器给三角形填充绿色. 添 ...
- 3D Computer Grapihcs Using OpenGL - 03 OpenGL Buffer Data
本节绘制一个三角形,并讲解Buffer Object-缓冲对象 OpenGL的窗口坐标 屏幕中心为坐标原点,横向朝右为x正方向,纵向朝上为y正方向,最大值最小值分别为1,-1. Buffer Obje ...
- 3D Computer Grapihcs Using OpenGL - 09 Enable Depth Test
启用Depth Test OpenGL是个3D绘图API,也就是说不只有xy坐标轴,还有第三个坐标轴z,z轴的方向是垂直于屏幕,指向屏幕内. 靠近人眼的方向是负方向,标准化设备坐标的最小值是-1, 最 ...
- 3D Computer Grapihcs Using OpenGL - 19 Vertex Array Object(顶点数组对象)
大部分OpenGL教程都会在一开始就讲解VAO,但是该教程的作者认为这是很不合理的,因为要理解它的作用需要建立在我们此前学过的知识基础上.因此直到教程已经进行了一大半,作者才引入VAO这个概念.在我看 ...
- 3D Computer Grapihcs Using OpenGL - 16 使用DrawElementsInstanced绘制立方体
我们使用15节学到的知识来绘制14节的立方体. 在第14节我们使用了两次glDrawElements实现了OpenGL实例化,发现这样仍然不太方便,如果需要绘制成千上万的立方体,就需要手写成千上万次的 ...
- 3D Computer Grapihcs Using OpenGL - 15 Draw Element Instanced
友情提示:继续本节之前,需要保存此前的代码,本节为了试验,会对代码做一些修改,但后续的修改需要我们把代码返回之前的进度. OpenGL内置支持Instancing,有专门的函数来处理这件事情. 为了方 ...
- 3D Computer Grapihcs Using OpenGL - 14 OpenGL Instancing
如果我们需要绘制两个(或者多个)一样的立方体(或者物体),只是位置.缩放.旋转不一样,那么我们可以不需要多次将这个物体的顶点信息.颜色信息等发送到显卡,而是发送一次,绘制多次,仅仅是每次绘制之前应用不 ...
- 3D Computer Grapihcs Using OpenGL - 10 Color Buffer
本节我们将尝试利用三角形制作一个“走马灯”效果. 一个三角形如图示方式,从左向右依次移动. 先看一下代码: MyGlWindow.cpp #include <gl\glew.h> #inc ...
随机推荐
- CentOS7配置NFS网络文件系统
NFS,是Network File System的简写,即网络文件系统.网络文件系统是FreeBSD支持的文件系统中的一种,也被称为NFS. NFS允许一个系统在网络上与他人共享目录和文件.通过使用N ...
- 关于this与e.target区别以及data-*属性
1 this与event.target 在编写事件函数时可以传入一个event参数,even参数可以使用一个target属性如even.target用以调用,其作用是指向返回事件的目标节点(触发该事件 ...
- 概率与期望dp相关
概率与期望dp 概率 某个事件A发生的可能性的大小,称之为事件A的概率,记作P(A). 假设某事的所有可能结果有n种,每种结果都是等概率,事件A涵盖其中的m种,那么P(A)=m/n. 例如投掷一枚骰子 ...
- 【7.10校内test】T3经营与开发
[题目链接luogu] 它……又是个DP 我……我讨厌DP!? 然后又是读入,显然用快读啊:(数据范围还是很大的)(习惯) 然后我们发现,不论是损耗值维修值,还是采矿所得,维修花费,都带着个p,因此我 ...
- [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)
[Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理) 题面 一个\(n \times n\)的格子,每个格子里可以填\([1,k]\)内的整数. ...
- [集合]Map的 entrySet() 详解以及用法(四种遍历map的方式)
Entry 由于Map中存放的元素均为键值对,故每一个键值对必然存在一个映射关系. Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value (我们总说键值对键值对, 每一个键值对也 ...
- Java——BufferedImage操作实例
通过鼠标位置改变图像ColorModel对象索引,从而实现图像像素自动变化 BufferedImage 由图像数据的 ColorModel 和 Raster 组成.Raster 的 SampleMod ...
- go 关键字之 defer
我是谁 defer - 顾名思义翻译过来叫 延迟, 所以我们通常称呼 defer func() 这样 defer 后面紧跟的函数为 延迟函数. 作者注: 不过从实际应用来讲, 延迟函数通常用来做一些函 ...
- 剑指offer-栈的压入、弹出序列-栈和队列-python
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- JS 页面跳转,参数的传递
当我们通过location.replace()进行页面的跳转时,我们想进行参数的传递,当时学习的时候,以前在网上找过获取方法,已经忘记出处在哪里了.获取方法大概是这样的: 1.将参数通过拼接的方式拼接 ...