3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader

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

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

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

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

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

 1     GLfloat verts[] =
 2     {
 3         +0.0f, +0.0f,        //Vertex 0
 4         +1.0,  +0.0, +0.0f,    //Color  0
 5         +1.0f, +1.0f,        //Vertex 1
 6         +0.0,  +1.0, +0.0f,    //Color  1
 7         -1.0f, +1.0f,        //Vertex 2
 8         +0.0,  +0.0, +1.0f,    //Color  2
 9         -1.0f, -1.0f,        //Vertex 3
10         +0.5f, +0.3f, +0.1f,//Color  3
11         +1.0f, -1.0f,        //Vertex 4
12         +0.1f, +0.4f, +0.2f,//Color  4
13     };

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

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

修改sendDataToOpenGL()函数:

 1 void MyGlWindow::sendDataToOpenGL()
 2 {
 3     GLfloat verts[] =
 4     {
 5         +0.0f, +0.0f,        //Vertex 0
 6         +1.0,  +0.0, +0.0f,    //Color  0
 7         +1.0f, +1.0f,        //Vertex 1
 8         +0.0,  +1.0, +0.0f,    //Color  1
 9         -1.0f, +1.0f,        //Vertex 2
10         +0.0,  +0.0, +1.0f,    //Color  2
11         -1.0f, -1.0f,        //Vertex 3
12         +1.0f, +1.0f, +0.0f,//Color  3
13         +1.0f, -1.0f,        //Vertex 4
14         +0.0f, +1.0f, +1.0f,//Color  4
15     };
16
17     GLuint vertexBufferID;
18     glGenBuffers(1, &vertexBufferID);
19     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
20     glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
21
22     GLushort indices[] =
23     {
24         0,1,2,
25         0,3,4,
26     };
27     GLuint indexBufferID;
28     glGenBuffers(1, &indexBufferID);
29     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
30     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
31
32     glEnableVertexAttribArray(0);
33     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
34
35     glEnableVertexAttribArray(1);
36     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (char*)(sizeof(GLfloat) * 2));
37 }

注意第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

 1 const char* vertexShaderCode =
 2 "    #version 430                            \r\n"
 3 "                                            \r\n"
 4 "    in layout(location=0) vec2 position;    \r\n"
 5 "    in layout(location=1) vec3 vertexColor; \r\n"
 6 "                                            \r\n"
 7 "    out vec3 passingColor;                  \r\n"
 8 "                                            \r\n"
 9 "    void main()                             \r\n"
10 "    {                                       \r\n"
11 "      gl_Position= vec4(position,0.0,1.0);  \r\n"
12 "      passingColor= vertexColor;            \r\n"
13 "    }                                       \r\n"
14 "                                            \r\n"
15 "                                            \r\n";
16
17 const char* fragmentShaderCode =
18 "    #version 430                            \r\n"
19 "                                            \r\n"
20 "    in vec3 passingColor;                   \r\n"
21 "    out vec4 finalColor;                    \r\n"
22 "                                            \r\n"
23 "                                            \r\n"
24 "    void main()                             \r\n"
25 "    {                                       \r\n"
26 "      finalColor = vec4(passingColor,1.0);  \r\n"
27 "    }                                       \r\n"
28 "                                            \r\n"
29 "                                            \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中,最终输出成顶点的颜色。

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

原文地址:https://www.cnblogs.com/AnKen/p/8337825.html

时间: 2024-10-15 06:29:13

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

3D Computer Grapihcs Using OpenGL - 05 EBO

本节将采用两种方法绘制两个三角形. 先看第一种方法的代码 MyGlWindow.cpp 1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 4 void MyGlWindow::initializeGL() 5 { 6 glewInit(); 7 8 GLfloat verts[] = 9 { 10 +0.0f, +0.0f, 11 +1.0f, +1.0f, 12 -1.0f, +1.0f, 13 14 +0.0f, +0

3D Computer Grapihcs Using OpenGL - 10 Color Buffer

本节我们将尝试利用三角形制作一个"走马灯"效果. 一个三角形如图示方式,从左向右依次移动. 先看一下代码: MyGlWindow.cpp 1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 #include <iostream> 4 #include <fstream> 5 6 float triangleWidth = 0.1f; 7 float bytesPerTriangle

3D Computer Grapihcs Using OpenGL - 08 Text File Shaders

使用之前的方法写Shader是一件很痛苦的事情,把Shader代码直接卸载C++文件中,需要使用很多引号来包裹,既不美观也不方便. 我们这节的目的是使用纯文本文件保存Shader. 首先在工程中创建两个文件,分别命名为VertexShaderCode.glsl 和 FragmentShaderCode.glsl,后缀名可以自己随意指定,不一定非要是glsl. 然后把上节的Shader代码拷贝到两个文件中去. VertexShaderCode.glsl 1 #version 430 2 3 in

3D Computer Grapihcs Using OpenGL - 20 结合Buffer

在上一节的案例中,我们使用了四个Buffer Object,立方体的VertexBuffer,立方体的索引Buffer,四面体的VertexBuffer,四面体的索引Buffer. 我们这节尝试把两个图形的Vertex Buffer结合,两个图形的索引Buffer结合,形成两个Buffer,让程序更加简化. 先看最终代码: MyGlWindow.cpp: 1 #include <gl\glew.h> 2 #include "MyGlWindow.h" 3 #include

[Angular 2] Passing data to components with &#39;properties&#39;

Besides @Input(), we can also use properties on the @Component, to pass the data. import {Component, View, NgFor, Input} from 'angular2/angular2'; @Component({ selector: 'reddit-article' }) @View({ directives: [], template: ` <article> <div class

最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)

本文记录OpenGL播放视频的技术.上一篇文章中,介绍了一种简单的使用OpenGL显示视频的方式.但是那还不是OpenGL显示视频技术的精髓.和Direct3D一样,OpenGL更好的显示视频的方式也是通过纹理(Texture).本文介绍OpenGL通过纹理的方式显示视频的技术. OpenGL中坐标和Direct3D坐标的不同 OpenGL中的纹理的坐标和Direct3D中的坐标是不一样的. 在Direct3D中.纹理坐标如下图所示.取值是0到1.坐标系原点在左上角. 物体表面坐标如下图所示.取

基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)

在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时,我们还会介绍VBO(顶点缓冲区对象)和VAO(顶点数组对象)的基本用法. 在编写自己的shader之前,我觉得有必要提一下OpenGL渲染管线. 理解OpenGL渲染管线,对于学习OpenGL非常重要.下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段) 此图是从wiki中拿过来的

AngularJS - Passing data between pages

You need to create a service to be able to share data between controllers. app.factory('myService', function() { var savedData = {} function set(data) { savedData = data; } function get() { return savedData; } return { set: set, get: get } }); In you

[React Native] Passing data when changing routes

The way you make HTTP requests in React Native is with the Fetch API. In this video we'll talk about Fetch and how to work with promises. As we build application components, we will need to pass data along as we change routes and bring them into view