操作系统:Windows8.1

显卡:Nivida GTX965M

开发工具:Visual Studio 2017


Introduction

在接下来几个章节中,我们将会使用内存顶点缓冲区来替换之前硬编码到vertex shader中的顶点数据。我们将从最简单的方法开始创建一个CPU可见的缓冲区,并使用memcpy直接将顶点数据直接复制到缓冲区,之后将会使用暂存缓冲区将顶点数据赋值到高性能的内存。

Vertex shader


首先要修改的是顶点着色器,不再包含顶点数据。顶点着色器接受顶点缓冲区的输入使用in关键字。

#version
#extension GL_ARB_separate_shader_objects : enable layout(location = ) in vec2 inPosition;
layout(location = ) in vec3 inColor; layout(location = ) out vec3 fragColor; out gl_PerVertex {
vec4 gl_Position;
}; void main() {
gl_Position = vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
}

inPositioninColor变量是顶点属性。它们被顶点缓冲区中的每一个顶点指定,就像我们使用两个数组手动指定每个顶点的position和color一样。现在确保着色器被正确编译!

Vertex data


我们将顶点数组从着色器代码移到我们程序自定义的数组中。首先我们需要引入GLM库,它提供了像向量和矩阵之类的线性代数数据结构。我们使用这些类型指定position和颜色。

#include <glm/glm.hpp>

建立新的数据结构Vertex并定义两个属性,我们将会在顶点着色器内部使用:

struct Vertex {
glm::vec2 pos;
glm::vec3 color;
};

GLM很方便的提供了与C++类型匹配的可以在着色器中使用的矢量类型。

const std::vector<Vertex> vertices = {
{{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}},
{{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
{{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}
};

现在使用Vertex结构体作为顶点数组的元素类型。我们使用与之前完全相同的position和color值,但是现在它们被组合成一个顶点数组。这被称为 interleaving 顶点属性。

Binding descriptions


一旦数据被提交到GPU的显存中,就需要告诉Vulkan传递到顶点着色器中数据的格式。有两个结构体用于描述这部分信息。

第一个结构体VkVertexInputBingdingDescriptionVertex结构体中新增一个成员函数,并使用正确的数值填充它。

struct Vertex {
glm::vec2 pos;
glm::vec3 color; static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription bindingDescription = {}; return bindingDescription;
}
};

顶点绑定描述了在整个顶点数据从内存加载的速率。换句话说,它指定数据条目之间的间隔字节数以及是否每个顶点之后或者每个instance之后移动到下一个条目。

VkVertexInputBindingDescription bindingDescription = {};
bindingDescription.binding = ;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

我们所有的顶点数据都被打包在一个数组中,所以我们需要一个绑定。binding的参数指定了数组中对应的绑定索引。stride参数指定一个条目到下一个条目的字节数,inputRate参数可以具备一下值之一:

  • VK_VERTEX_INPUT_RATE_VERTEX: 移动到每个顶点后的下一个数据条目
  • VK_VERTEX_INPUT_RATE_INSTANCE: 在每个instance之后移动到下一个数据条目

我们不会使用instancing渲染,所以坚持使用per-vertex data方式。

Attribute descriptions


第二个结构体描VkVertexInputAttributeDescription述如何处理顶点的输入。我们需要在Vertex中增加一个新的辅助函数。

#include <array>

...

static std::array<VkVertexInputAttributeDescription, > getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, > attributeDescriptions = {}; return attributeDescriptions;
}

如函数圆形所示,该结构体为两个。一个属性描述结构体最终描述了顶点属性如何从对应的绑定描述过的顶点数据来解析数据。我们有两个属性,position和color,所以我们需要两个属性描述结构体。

attributeDescriptions[].binding = ;
attributeDescriptions[].location = ;
attributeDescriptions[].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[].offset = offsetof(Vertex, pos);

binding参数告诉了Vulkan每个顶点数据的来源。location参数引用了vertex shader作为输入的location指令。顶点着色器中,location0代表position,它是32bit单精度数据。

format参数描述了属性的类型。该格式使用与颜色格式一样的枚举,看起来有点乱。下列的着色器类型和格式是比较常用的搭配。

  • float: VK_FORMAT_R32_SFLOAT
  • vec2: VK_FORMAT_R32G32_SFLOAT
  • vec3: VK_FORMAT_R32G32B32_SFLOAT
  • vec4: V_FORMAT_R32G32B32A32_SFLOAT

如你所见,你应该使用颜色数量与着色器数据类型中的分量个数匹配的格式。允许使用比着色器中的分量个数更大的范围,但是它将会被默认丢弃。如果低于着色器分量的数量,则BGA组件将使用默认值(0, 0, 1)。颜色类型(SFLOAT, UINT, SINT) 和位宽度应该与着色器输入的类型对应匹配。如下示例:

  • ivec2: VK_FORMAT_R32G32_SINT,由两个32位有符号整数分量组成的向量
  • uvec4: VK_FORMAT_R32G32B32A32_UINT, 由四个32位无符号正式分量组成的向量
  • double: VK_FORMAT_R64_SFLOAT, 双精度浮点数(64-bit)

format参数在属性数据中被隐式的定义为字节单位大小,并且offset参数指定了每个顶点数据读取的字节宽度偏移量。绑定一次加载一个Vertex,position属性(pos)的偏移量在字节数据中为0字节。这是使用offsetof macro宏自动计算的。

attributeDescriptions[].binding = ;
attributeDescriptions[].location = ;
attributeDescriptions[].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[].offset = offsetof(Vertex, color);

color颜色属性与position位置属性的描述基本一致。

Pipeline vertex input


我们现在需要在createGraphicsPipeline函数中,配置图形管线可以接受重新定义的顶点数据的格式。找到vertexInputInfo结构体,修改引用之前定义的两个有关输入顶点的description结构体:

auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions(); vertexInputInfo.vertexBindingDescriptionCount = ;
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();

图形管线现在准备接受vertices容器封装后的顶点数据,并将该格式的顶点数据传递到vertex shader。如果开启了validation layers运行程序,我们将会看到无顶点缓冲区绑定的提示。所以下一章节我们将会创建顶点缓冲区vertex buffer并把顶点数据存储在里面,最终GPU通过顶点缓冲区读取到顶点数据。

项目代码 GitHub 地址。

Vulkan Tutorial 19 Vertex input description的更多相关文章

  1. Vulkan Tutorial 20 Vertex buffer creation

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在Vulkan中,缓冲区是内存的一块区域,该区域用于向显卡 ...

  2. [译]Vulkan教程(21)顶点input描述

    [译]Vulkan教程(21)顶点input描述 Vertex input description 顶点input描述 Introduction 入门 In the next few chapters ...

  3. [译]Vulkan教程(19)渲染和呈现

    [译]Vulkan教程(19)渲染和呈现 Rendering and presentation 渲染和呈现 Setup 设置 This is the chapter where everything ...

  4. Vulkan Tutorial 12 Fixed functions

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 早起的图形API在图形渲染管线的许多阶段提供了默认的状态.在Vulkan中,从vie ...

  5. Vulkan Tutorial 10 图形管线

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 通过接下来的章节,我们将会开启有关图形管线的话题,通过对图 ...

  6. Vulkan Tutorial 11 Shader modules

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 与之前的图像API不同,Vulkan中的着色器代码必须以二进制字节码的格式使用,而不 ...

  7. Vulkan Tutorial 13 Render passes

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Setup 在我们完成管线的创建工作,我们接下来需要告诉Vulkan渲染时候使用的f ...

  8. Vulkan Tutorial 18 重构交换链

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 现在我们已经成功的在屏幕上绘制出三角形,但是在某些情况下, ...

  9. Vulkan Tutorial 22 Index buffer

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在实际产品的运行环境中3D模型的数据往往共享多个三角形之间 ...

随机推荐

  1. 浅谈JavaScript时间与正则表达式

    时间函数:var box = new Date() 函数       Demo:         alert(Date.parse('4/12/2007'));    //返回的是一个毫秒数11763 ...

  2. hdu1054最小顶点覆盖

    最小定点覆盖是指这样一种情况: 图G的顶点覆盖是一个顶点集合V,使得G中的每一条边都接触V中的至少一个顶点.我们称集合V覆盖了G的边.最小顶点覆盖是用最少的顶点来覆盖所有的边.顶点覆盖数是最小顶点覆盖 ...

  3. Debian 8 下安装持续集成的工具Jenkins

    前情提示:Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 第一种方法: 1.1 配置java环境变量    解压java到相应目录,我一般习惯把安装的软件 ...

  4. 我的Cocos2dx开发模式

    编程环境: 1.window 7 32bit 2.cocos2dx 3.0 3.python 2.7 (注意不要使用3.0以上版本,除非cocos2dx推荐使用) 4.apache-ant-1.9.3 ...

  5. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

    EF使用ExecuteSqlCommand(db.Database.ExecuteSqlCommand("exec proc_DeleteCaseInfo_Output @caseID&qu ...

  6. 使用java API操作hdfs--读取hdfs文件并打印

    在myclass之中创建类文件,这个myclass目录是自己创建的. 编译的时候会报如下的错误: 很明显就是没有导入包的结果 见这个API网站,则可以找到响应的包,当然还有java的api文档 htt ...

  7. 设计一个神经网络记住Or运算(日志一)

    由于公式书写太过麻烦,所以上传设计的手稿过程,为如下:

  8. kobo阅读器安装koreader

    动机 kobo阅读器是加拿大的电子阅读器品牌,与kindle类似.问题是这个阅读器在中国无法连接电子书商店,即使是用SS翻出去也不行.一气之下花了一个下午折腾,安装一个开源的阅读器. 安装 代码仓库在 ...

  9. 使用crontab,让linux定时执行shell脚本

    阅读目录 1. cron服务[Ubuntu环境] 2. crontab用法 3. 编辑crontab文件 4. 流程举例 5. 几个例子 Linux中,周期执行的任务一般由cron这个守护进程来处理. ...

  10. 【less和sass的区别,你了解多少?】

    在介绍less和sass的区别之前,我们先来了解一下他们的定义: 一.Less.Sass/Scss是什么? 1.Less: 是一种动态样式语言. 对CSS赋予了动态语言的特性,如变量.继承.运算.函数 ...