Vulkan开发实战详解 学习笔记 - 绘制方式,点绘制、线段绘制和三角形绘制

el/2024/5/23 2:00:01

三角形条带与扇面

三角形条带

BeltData.h

#ifndef VULKANEXBASE_BELTDATA_H
#define VULKANEXBASE_BELTDATA_Hclass BeltData
{
public:static float* vdata;static int dataByteCount;static int vCount;static double toRadians(double d);static void  genVertexData();
};
#endif

BeltData.cpp

#include <../main_task/BeltData.h>
#include <vector>
#include <math.h>
#include <string.h>
#include "BeltData.h"const double PI=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170680;float* BeltData::vdata;
int BeltData::dataByteCount;
int BeltData::vCount;double BeltData::toRadians(double d)
{double e=d*PI/180;return e;
}
void  BeltData::genVertexData(){								//生成顶点数据的方法int n = 6;                              						//条带切割份数//始化了计算三角形条带顶点数据所需的各个辅助变量并创建了顶点数据存储数组。vCount=2*(n+1);                							//计算顶点数量dataByteCount=vCount*6* sizeof(float);						//计算顶点数据所占总字节数float angdegBegin = -90;									//设置条带起始度数float angdegEnd = 90;     								//设置条带结束度数float angdegSpan = (angdegEnd-angdegBegin)/n;				//计算条带每份度数vdata=new float[vCount*6];									//创建顶点数据数组int count=0;											//辅助索引//行为生成三角形条带顶点位置及顶点颜色数据的代码for(float angdeg=angdegBegin; angdeg<=angdegEnd; angdeg+=angdegSpan) {double angrad=toRadians(angdeg);						//计算当前弧度vdata[count++]=(float) (-0.6f*50*sin(angrad));			//此切割角度第1个顶点的x坐标vdata[count++]=(float) (0.6f*50*cos(angrad));			//此切割角度第1个顶点的y坐标vdata[count++]=0;								//此切割角度第1个顶点的z坐标vdata[count++]=1;								//此切割角度第1个顶点颜色R分量vdata[count++]=1;								//此切割角度第1个顶点颜色G分量vdata[count++]=1;								//此切割角度第1个顶点颜色B分量vdata[count++]=(float) (-50*sin(angrad));				//此切割角度第2个顶点的x坐标vdata[count++]=(float) (50*cos(angrad));				//此切割角度第2个顶点的y坐标vdata[count++]=0;								//此切割角度第2个顶点的z坐标vdata[count++]=0;								//此切割角度第2个顶点颜色R分量vdata[count++]=1;								//此切割角度第2个顶点颜色G分量vdata[count++]=1;								//此切割角度第2个顶点颜色B分量
}}

在这里插入图片描述

CircleData.cpp

#include "CircleData.h"
#include "BeltData.h"
#include <vector>
#include <math.h>
#include <string.h>float* CircleData::vdata;
int CircleData::dataByteCount;
int CircleData::vCount;
void  CircleData::genVertexData(){//初始化了计算扇面顶点数据所需的各个辅助变量并创建了顶点数据存储数组int n = 10;												//扇形切割份数vCount=n+2;											//顶点数量dataByteCount=vCount*6* sizeof(float);						//顶点数据所占总字节数vdata=new float[vCount*6];									//创建顶点数据数组float angdegSpan=360.0f/n;								//扇形每份度数int count=0;											//辅助索引//给出了扇面中心点的坐标及颜色数据vdata[count++] = 0;										//第一个顶点X坐标vdata[count++] = 0;										//第一个顶点Y坐标vdata[count++] = 0;										//第一个顶点Z坐标vdata[count++] = 1;										//第一个顶点颜色R分量vdata[count++] = 1;										//第一个顶点颜色G分量vdata[count++] = 1;										//第一个顶点颜色B分量//循环生成了扇面周围一圈顶点的坐标及颜色数据for(float angdeg=0; ceil(angdeg)<=360; angdeg+=angdegSpan) {	//循环生成周围其他顶点的数据double angrad=BeltData::toRadians(angdeg);				//当前弧度vdata[count++]=(float) (-50*sin(angrad));					//当前顶点x坐标vdata[count++]=(float) (50*cos(angrad));					//当前顶点y坐标vdata[count++]=0;									//当前顶点z坐标vdata[count++] = 0;									//当前顶点颜色R分量vdata[count++] = 1;									//当前顶点颜色G分量vdata[count++] = 0;									//当前顶点颜色B分量
}}

在这里插入图片描述

shade

#version 400
#extension GL_ARB_separate_shader_objects : enable//启动GL_ARB_separate_shader_objects
#extension GL_ARB_shading_language_420pack : enable//启动GL_ARB_shading_language_420pack
layout (push_constant) uniform constantVals 
{			 //推送常量块mat4 mvp;//总变换矩阵
} myConstantVals;
layout (location = 0) in vec3 pos;//传入的物体坐标系顶点位置
layout (location = 1) in vec3 color;//传入的顶点颜色
layout (location = 0) out vec3 vcolor;//传到片元着色器的顶点颜色
out gl_PerVertex { vec4 gl_Position;};				//输出接口块
void main() 
{									//主函数gl_Position = myConstantVals.mvp * vec4(pos,1.0);	//计算顶点最终位置vcolor=color;//传递顶点颜色给片元着色器
}

在这里插入图片描述

BeltData2.cpp

#include <../main_task/BeltData.h>
#include <vector>
#include <math.h>
#include <string.h>
#include "BeltData.h"const double PI=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170680;float* BeltData::vdata;
int BeltData::dataByteCount;
int BeltData::vCount;double BeltData::toRadians(double d)
{double e=d*PI/180;return e;
}void  BeltData::genVertexData(){								//生成顶点数据的方法int n1 = 3;                                                     //第一个条带切割份数int n2 = 5;                                                     //第二个条带切割份数vCount = 2 * (n1 + n2 + 2) + 2;                                 //计算总顶点数dataByteCount=vCount*6* sizeof(float);						//计算顶点数据所占总字节数			//计算条带每份度数vdata=new float[vCount*6];									//创建顶点数据数组float angdegBegin1 = 0;                                         //第一个条带起始度数float angdegEnd1 = 90;                                          //第一个条带结束度数float angdegSpan1 = (angdegEnd1 - angdegBegin1) / n1;            //第一个条带每份度数float angdegBegin2 = 180;                                           //第二个条带起始度数float angdegEnd2 = 270;                                         //第二个条带结束度数float angdegSpan2 = (angdegEnd2 - angdegBegin2) / n2;            //第二个条带每份度数int count=0;											//辅助索引for (float angdeg = angdegBegin1; angdeg <= angdegEnd1; angdeg += angdegSpan1) {double angrad=toRadians(angdeg);						//计算当前弧度vdata[count++] = (float)(-0.6f * 80 * sin(angrad));                //外围大圆上的点X坐标vdata[count++] = (float)(0.6f * 80 * cos(angrad));                //外围大圆上的点Y坐标vdata[count++]=0;								//此切割角度第1个顶点的z坐标vdata[count++]=1;								//此切割角度第1个顶点颜色R分量vdata[count++]=1;								//此切割角度第1个顶点颜色G分量vdata[count++]=1;								//此切割角度第1个顶点颜色B分量vdata[count++] = (float)(-80 * sin(angrad));                    //内圈小圆上的点X坐标vdata[count++] = (float)(80 * cos(angrad));                    //内圈小圆上的点Y坐标vdata[count++]=0;								//此切割角度第2个顶点的z坐标vdata[count++]=0;								//此切割角度第2个顶点颜色R分量vdata[count++]=1;								//此切割角度第2个顶点颜色G分量vdata[count++]=1;								//此切割角度第2个顶点颜色B分量}vdata[count++] = vdata[count - 6];            //重复第一批三角形的最后一个顶点数据vdata[count++] = vdata[count - 6];vdata[count++] = 0;vdata[count++] = 1;vdata[count++] = 0;vdata[count++] = 0;//第2个条带数据的生成与第一个条带相似//初始化了计算条带顶点数据的辅助变量,包括顶点数量、顶点数据总字节数、两个条带度数范围以及条带分割的每份度数等,同时还创建了顶点数据数组。for (float angdeg = angdegBegin2; angdeg <= angdegEnd2; angdeg += angdegSpan2) {double angrad = toRadians(angdeg);                    //当前弧度if (angdeg == angdegBegin2) {            //重复第二批三角形的第一个顶点数据vdata[count++] = (float)(-0.6f * 80 * sin(angrad));            //顶点X坐标vdata[count++] = (float)(0.6f * 80 * cos(angrad));            //顶点Y坐标vdata[count++] = 0;                                //顶点Z坐标vdata[count++] = 0;vdata[count++] = 1;vdata[count++] = 0;    //顶点颜色}//大圆上的点vdata[count++] = (float)(-0.6f * 80 * sin(angrad));//顶点坐标vdata[count++] = (float)(0.6f * 80 * cos(angrad));vdata[count++] = 0;vdata[count++] = 1;vdata[count++] = 1;vdata[count++] = 1;//小圆上的点vdata[count++] = (float)(-80 * sin(angrad));//顶点坐标vdata[count++] = (float)(80 * cos(angrad));vdata[count++] = 0;vdata[count++] = 0;vdata[count++] = 1;vdata[count++] = 1;}
}

相比于上一个案例主要是改变了顶点的位置。物体不再是整体由一批连续三角形组成,而是分两批连续三角形组成。第一批的最后一个顶点和第二批的第一个顶点在顶点序列中重复了

在这里插入图片描述

在这里插入图片描述

索引法绘制

vkCmdDraw前面的案例中都是调用vkCmdDraw方法来执行物体的绘制,此方法是按照传入渲染管线的顶点本身的顺序及选用的绘制方式将顶点组织成图元进行绘制的,也可以称之为顶点法。

vkCmdDrawIndexed方法在绘制时不但要将顶点序列传入渲染管线,还需要将索引序列传入渲染管线。绘制时管线根据索引序列中的索引值从顶点序列中取出对应的顶点,并根据当前选用的绘制方式组织成图元进行绘制,图4-33很好地说明了这个问题。

采用索引法(vkCmdDrawIndexed)进行绘制时可以有效地减少重复顶点数据,有重复时只需要提供重复的索引号即可。。而每个索引值只需要一个整数,相比一个顶点数据需要3个(也可能是更多的)整数或浮点数可以节省不少空间。

CircleData.h

#ifndef VULKANEXBASE_BELTDATA_H
#define VULKANEXBASE_BELTDATA_H#include <cstdint>
//代码为在CircleData类头文件中添加的服务于索引数据的相关变量,包括索引数据指针、总字节数和索引数量。
class CircleData
{
public:static float* vdata;static int dataByteCount;static int vCount;static uint16_t* idata; //索引数据指针static int indexByteCount; //索引数据所占总字节数static int iCount; //索引数量static double toRadians(double d);static void  genVertexData();
};#endif //TRIANGLESTRIP_CIRCLEDATA_H
#include <../main_task/CircleData.h>
#include <vector>
#include <math.h>
#include <string.h>
const double PI=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170680;float* CircleData::vdata;
int CircleData::dataByteCount;
int CircleData::vCount;
uint16_t* CircleData::idata;
int CircleData::indexByteCount;
int CircleData::iCount;double CircleData::toRadians(double d)
{double e=d*PI/180;return e;
}
//主要功能为生成要绘制的物体的顶点位置、颜色数据及绘制所需的索引数据。
void  CircleData::genVertexData(){int n = 10;												//扇形切割份数vCount=n+2;											//顶点数量dataByteCount=vCount*6* sizeof(float);						//顶点数据所占总字节数vdata=new float[vCount*6];									//创建顶点数据数组float angdegSpan=360.0f/n;								//扇形每份度数int count=0;											//辅助索引vdata[count++] = 0; vdata[count++] = 0; vdata[count++] = 0; //第一个顶点的坐标vdata[count++] = 1; vdata[count++] = 1; vdata[count++] = 1; //第一个顶点的颜色for(float angdeg=0; ceil(angdeg)<=360; angdeg+=angdegSpan) {	//循环生成周围其他顶点的数据double angrad = toRadians(angdeg); //当前弧度vdata[count++] = (float)(-30 * sin(angrad)); //顶点x 坐标vdata[count++] = (float)(30 * cos(angrad)); //顶点y 坐标vdata[count++]=0;									//当前顶点z坐标vdata[count++] = 0; vdata[count++] = 1; vdata[count++] = 0; //顶点颜色}iCount = 12; //索引数量indexByteCount = iCount * sizeof(uint16_t); //索引数据所占总字节数idata = new uint16_t[iCount]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1 }; //索引数据数组
}

用于生成物体数据的CircleData类后,还需要对物体绘制类DrawableObjectCommon进行修改,使其能够创建索引缓冲。首先要介绍的是对DrawableObjectCommon类声明的修改,主要是添加了与创建索引缓冲相关的变量和方法,并对drawSelf方法签名进行了修改,具体代码如下。

DrawableObjectCommonLight函数

//创建顶点数据缓冲、索引数据缓冲所需的诸多变量,对构造函数和绘制方法的签名进行了修改
//,添加了索引数据相关的入口参数,并提供了用于创建顶点数据缓冲、索引数据缓冲的两个方法。//行用于接收逻辑设备指针、顶点数据数组首地址指针、顶点数量、索引数据数组首地址指针、索引数量等,并保存到对应成员变量中。
DrawableObjectCommonLight::DrawableObjectCommonLight( //构造函数float* vdataIn, int dataByteCount, int vCountIn, //传入的顶点数据相关参数uint16_t* idataIn, int indexByteCount, int iCountIn, //传入的索引数据相关参数VkDevice& device, VkPhysicalDeviceMemoryProperties& memoryroperties)
{pushConstantData = new float[16];					//推送常量数据数组的初始化//用于接收逻辑设备指针、顶点数据数组首地址指针、顶点数量、索引数据数组首地址指针、索引数量等,并保存到对应成员变量中。this->devicePointer = &device;this->vdata = vdataIn;this->vCount = vCountIn;this->idata = idataIn; //接收索引数据数组首地址指针并保存this->iCount = iCountIn; //接收索引数量并保存//调用相关方法分别创建顶点数据缓冲和索引数据缓冲,其中createVertexBuffer方法就是将之前创建顶点数据缓冲的过程封装而来。//createIndexBuffer方法基本也是如此,需要注意的是创建索引缓冲时需要将缓冲创建信息结构体中的index_buf_info.usage设置为VK_BUFFER_USAGE_INDEX_BUFFER_BIT。//用相关方法分别创建顶点数据缓冲和索引数据缓冲,其中createVertexBuffer方法就是将之前创建顶点数据缓冲的过程封装而来。//createIndexBuffer方法基本也是如此,需要注意的是创建索引缓冲时需要将缓冲创建信息结构体中的index_buf_info.usage设置为VK_BUFFER_USAGE_INDEX_BUFFER_BIT。createVertexBuffer(dataByteCount, device, memoryroperties); //调用方法创建顶点数据缓冲createIndexBuffer(indexByteCount, device, memoryroperties); //调用方法创建索引数据缓冲
}

​ createVertexBuffer(dataByteCount, device, memoryroperties); //调用方法创建顶点数据缓冲

void DrawableObjectCommonLight::createVertexBuffer(int dataByteCount, VkDevice& device, VkPhysicalDeviceMemoryProperties& memoryroperties)
{VkBufferCreateInfo buf_info = {};//构建缓冲创建信息结构体实例buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;//设置结构体类型buf_info.pNext = NULL;//自定义数据的指针buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//缓冲的用途为顶点数据buf_info.size = dataByteCount;//设置数据总字节数buf_info.queueFamilyIndexCount = 0;//队列家族数量buf_info.pQueueFamilyIndices = NULL;//队列家族索引列表buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;//共享模式buf_info.flags = 0;//标志VkResult result = vkCreateBuffer(device, &buf_info, NULL, &vertexDatabuf);//创建缓冲assert(result == VK_SUCCESS);//检查缓冲创建是否成功VkMemoryRequirements mem_reqs;//缓冲内存需求vkGetBufferMemoryRequirements(device, vertexDatabuf, &mem_reqs);//获取缓冲内存需求assert(dataByteCount <= mem_reqs.size);//检查内存需求获取是否正确VkMemoryAllocateInfo alloc_info = {};//构建内存分配信息结构体实例alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;//结构体类型alloc_info.pNext = NULL;//自定义数据的指针alloc_info.memoryTypeIndex = 0;//内存类型索引alloc_info.allocationSize = mem_reqs.size;//内存总字节数VkFlags requirements_mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;//需要的内存类型掩码bool flag = memoryTypeFromProperties(memoryroperties, mem_reqs.memoryTypeBits, requirements_mask, &alloc_info.memoryTypeIndex);//获取所需内存类型索引if (flag){printf("确定内存类型成功 类型索引为%d\n", alloc_info.memoryTypeIndex);}else{printf("确定内存类型失败!\n");}result = vkAllocateMemory(device, &alloc_info, NULL, &vertexDataMem);//为顶点数据缓冲分配内存assert(result == VK_SUCCESS);uint8_t *pData;//CPU访问时的辅助指针result = vkMapMemory(device, vertexDataMem, 0, mem_reqs.size, 0, (void **)&pData);//将设备内存映射为CPU可访问assert(result == VK_SUCCESS);//检查映射是否成功memcpy(pData, vdata, dataByteCount);//将顶点数据拷贝进设备内存vkUnmapMemory(device, vertexDataMem);//解除内存映射result = vkBindBufferMemory(device, vertexDatabuf, vertexDataMem, 0);//绑定内存与缓冲assert(result == VK_SUCCESS);vertexDataBufferInfo.buffer = vertexDatabuf;//指定数据缓冲vertexDataBufferInfo.offset = 0;//数据缓冲起始偏移量vertexDataBufferInfo.range = mem_reqs.size;//数据缓冲所占字节数
}

DrawableObjectCommonLight::createIndexBuffer

void DrawableObjectCommonLight::createIndexBuffer(int indexByteCount, VkDevice& device, VkPhysicalDeviceMemoryProperties& memoryroperties)
{//创建Buffer创建信息实例,为创建索引数据Buffer服务VkBufferCreateInfo index_buf_info = {};index_buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;index_buf_info.pNext = NULL;index_buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;index_buf_info.size = indexByteCount;index_buf_info.queueFamilyIndexCount = 0;index_buf_info.pQueueFamilyIndices = NULL;index_buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;index_buf_info.flags = 0;VkResult result = vkCreateBuffer(device, &index_buf_info, NULL, &indexDatabuf);assert(result == VK_SUCCESS);//获取内存需求VkMemoryRequirements index_mem_reqs;vkGetBufferMemoryRequirements(device, indexDatabuf, &index_mem_reqs);assert(indexByteCount <= index_mem_reqs.size);//内存分配信息VkMemoryAllocateInfo index_alloc_info = {};index_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;index_alloc_info.pNext = NULL;index_alloc_info.memoryTypeIndex = 0;index_alloc_info.allocationSize = index_mem_reqs.size;VkFlags index_requirements_mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;//获取所需内存类型索引bool index_flag = memoryTypeFromProperties(memoryroperties, index_mem_reqs.memoryTypeBits, index_requirements_mask, &index_alloc_info.memoryTypeIndex);if (index_flag){printf("确定内存类型成功 类型索引为%d\n", index_alloc_info.memoryTypeIndex);}else{printf("确定内存类型失败!\n");}//为顶点数据缓冲分配内存result = vkAllocateMemory(device, &index_alloc_info, NULL, &indexDataMem);assert(result == VK_SUCCESS);uint8_t *index_pData;//将显存映射为CPU可访问result = vkMapMemory(device, indexDataMem, 0, index_mem_reqs.size, 0, (void **)&index_pData);assert(result == VK_SUCCESS);//将顶点数据拷贝进显存memcpy(index_pData, idata, indexByteCount);//解除内存映射vkUnmapMemory(device, indexDataMem);//绑定内存与缓冲result = vkBindBufferMemory(device, indexDatabuf, indexDataMem, 0);assert(result == VK_SUCCESS);//记录Buffer InfoindexDataBufferInfo.buffer = indexDatabuf;indexDataBufferInfo.offset = 0;indexDataBufferInfo.range = index_mem_reqs.size;
}

接下来介绍物体的绘制方法——drawSelf,其主要功能为将命令缓冲与管线、管线布局、描述集、顶点数据、索引数据进行绑定并执行绘制,具体代码如下。

void DrawableObjectCommonLight::drawSelf(VkCommandBuffer& cmd, VkPipelineLayout& pipelineLayout, VkPipeline& pipeline, VkDescriptorSet* desSetPointer, uint32_t sIndex, uint32_t eIndex)
{vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);//将当前使用的命令缓冲与指定管线绑定vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, desSetPointer, 0, NULL);//将命令缓冲、管线布局、描述集绑定const VkDeviceSize offsetsVertex[1] = { 0 };//顶点数据偏移量数组vkCmdBindVertexBuffers(//将顶点数据与当前使用的命令缓冲绑定cmd,				//当前使用的命令缓冲0,					//顶点数据缓冲在列表中的首索引1,					//绑定顶点缓冲的数量&(vertexDatabuf),	//绑定的顶点数据缓冲列表offsetsVertex		//各个顶点数据缓冲的内部偏移量);float* mvp = MatrixState3D::getFinalMatrix();					//获取总变换矩阵memcpy(pushConstantData, mvp, sizeof(float) * 16);				//将总变换矩阵拷贝入内存vkCmdPushConstants(cmd, pipelineLayout, 				//将常量数据送入管线VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 16, pushConstantData);// 调用vkCmdBindIndexBuffer方法将索引数据缓冲与使用的命令缓冲绑定。//调用vkCmdDrawIndexed方法执行索引绘制,由sIndex与eIndex确定了实际参与绘制的索引数量和范围。vkCmdBindIndexBuffer( //将顶点数据与当前使用的命令缓冲绑定cmd, //当前使用的命令缓冲indexDatabuf, //索引数据缓冲0, //索引数据缓冲首索引VK_INDEX_TYPE_UINT16); //索引数据类型//调用vkCmdDrawIndexed方法执行索引绘制,vkCmdDrawIndexed( //执行索引绘制 //cmd, //当前使用的命令缓冲eIndex - sIndex, //索引数量 //由sIndex与eIndex确定了实际参与绘制的索引数量和范围。1, //需要绘制的实例数量sIndex, //绘制用起始索引0, //顶点数据偏移量0); //需要绘制的第1 个实例的索引
}

绘制方法

void MyVulkanManager::drawObject()
{FPSUtil::init();//初始化FPS计算while (MyVulkanManager::loopDrawFlag)//每循环一次绘制一帧画面{FPSUtil::calFPS();//计算FPSFPSUtil::before();//一帧开始//获取交换链中的当前帧索引VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &currentBuffer);//为渲染通道设置当前帧缓冲rp_begin.framebuffer = framebuffers[currentBuffer];vkResetCommandBuffer(cmdBuffer, 0);//恢复命令缓冲到初始状态result = vkBeginCommandBuffer(cmdBuffer, &cmd_buf_info);//启动命令缓冲MyVulkanManager::flushUniformBuffer();//将当前帧相关数据送入一致变量缓冲MyVulkanManager::flushTexToDesSet();//更新绘制用描述集vkCmdBeginRenderPass(cmdBuffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);//启动渲染通道MatrixState3D::pushMatrix();										//保护现场MatrixState3D::rotate(xAngle, 1, 0, 0);								//绕X轴旋转xAngleMatrixState3D::rotate(yAngle, 0, 1, 0);								//绕Y轴旋转yAngleMatrixState3D::pushMatrix();									//保护现场MatrixState3D::translate(0, 50, 0); //沿Y 轴正方向平移50cirForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout, //绘制正十边形sqsCL->pipeline, &(sqsCL->descSet[0]), 0, CircleData::iCount);MatrixState3D::popMatrix();									//恢复现场MatrixState3D::pushMatrix();									//保护现场MatrixState3D::translate(0, -50, 0); //沿Y 轴负方向平移50cirForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout,				//绘制扇形sqsCL->pipeline, &(sqsCL->descSet[0]), 0, CircleData::iCount / 2 + 1);MatrixState3D::popMatrix();									//恢复现场MatrixState3D::popMatrix();vkCmdEndRenderPass(cmdBuffer);//结束渲染通道result = vkEndCommandBuffer(cmdBuffer);//结束命令缓冲submit_info[0].waitSemaphoreCount = 1;//等待的信号量数量submit_info[0].pWaitSemaphores = &imageAcquiredSemaphore;//等待的信号量列表result = vkQueueSubmit(queueGraphics, 1, submit_info, taskFinishFence);//提交命令缓冲do {	//等待渲染完毕result =vkWaitForFences(device, 1, &taskFinishFence, VK_TRUE, FENCE_TIMEOUT);} while (result == VK_TIMEOUT);vkResetFences(device, 1, &taskFinishFence);//重置栅栏present.pImageIndices = &currentBuffer;//指定此次呈现的交换链图像索引result =vkQueuePresentKHR(queueGraphics, &present);//执行呈现FPSUtil::after(60);//限制FPS不超过指定的值}
}

在这里插入图片描述


http://www.ngui.cc/el/5239825.html

相关文章

Vulkan开发实战详解 学习笔记 - 设置合理的视角

设置合理的视角 使用过照相机的读者都知道&#xff0c;拍摄时根据不同的情况应当选用不同焦距的镜头&#xff0c;这些不同焦距镜头的一大区别就是视角不同。在同样的位置&#xff0c;视角大可以观察到更宽范围内的景物&#xff0c;但投影到照片里的景物较小&#xff1b;视角小…

Vulkan开发实战详解 学习笔记 - 背面剔除,间接绘制

首先对生成正方形面绘制用数据的ColorRect类进行修改&#xff0c;下面先给出修改后的类声明&#xff0c;具体内容如下 ColorRect.h #ifndef VULKANEXBASE_COLORRECT_H #define VULKANEXBASE_COLORRECT_H //防止重复定义 class ColorRect { public:static float* vdataG; //青…

Vulkan开发实战详解 学习笔记 - 构建一个球体对象

构建一个球体对象 BallData.h #ifndef VULKANEXBASE_BALLDATA_H #define VULKANEXBASE_BALLDATA_H//防止重复引用 class BallData { public:static float* vdata;//顶点数据数组首地址指针static int dataByteCount;//顶点数据所占总字节数static int vCount;//顶点数量stat…

Vulkan开发实战详解 学习笔记 - 环境光 散射光 镜面光 定向光

环境光 添加LightManagerLightManager类&#xff0c;此类的主要功能为管理光照的相关参数。首先给出此类的声明&#xff0c;具体代码如下&#xff1a; #ifndef VULKANEXBASE_LIGHTMANAGER_H #define VULKANEXBASE_LIGHTMANAGER_H //防止重复引用 class LightManager { publi…

Qt 小例子学习1 pdf浏览器

qt pdf浏览器 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #include <QDir> #include <QWebEngineView>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->s…

Qt 小例子学习2 TabBar

Qt小例子 TabBar #ifndef TABWIDGET_H #define TABWIDGET_H#include <QTabWidget> #include <QStylePainter> #include <QStyleOption>class TabBar : public QTabBar { public:TabBar(const QHash<QString, QColor>& colors, QWidget* parent …

Qt 小例子学习5 日志过滤

日志过滤 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFile> #include <QTextStream> #define FORMAT "hh:mm:ss"MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui…

Qt 小例子学习7 - QListWidget 更改文本的部分颜色

QListWidget 更改文本的部分颜色 MainWindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "HtmlDelegate.h"MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(t…

Qt 小例子学习9 - 代码编辑器

Qt 小例子学习9 - 代码编辑器 CodeEditor.h #ifndef CODEEDITOR_H #define CODEEDITOR_H#include <QObject> #include <QPlainTextEdit>QT_BEGIN_NAMESPACE class QPaintEvent; class QResizeEvent; class QSize; class QWidget; QT_END_NAMESPACEclass LineNumb…

Qt 小例子学习12 - MemoryViewer

Qt 小例子学习12 - MemoryViewer #ifndef MEMORYVIEWER_H #define MEMORYVIEWER_H#include <QAbstractScrollArea> #include <QBuffer>class MemoryViewer : public QAbstractScrollArea {Q_OBJECT public:MemoryViewer(QWidget* parent 0);~MemoryViewer();void…