绘制方式,点绘制、线段绘制和三角形绘制
准备绘制的数据ObjectData.h ObjectData.cpp
#ifndef VULKANEXBASE_OBJECTDATA_H
#define VULKANEXBASE_OBJECTDATA_H
class ObjectData
{
public:
static float* vdata;
static int dataByteCount;
static int vCount;
static void genVertexData();
};
#endif
ObjectData.cpp
#include <../main_task/ObjectData.h>
#include <vector>
#include <math.h>
#include <string.h>
float* ObjectData::vdata;
int ObjectData::dataByteCount;
int ObjectData::vCount;
void ObjectData::genVertexData()
{
vCount = 5;
dataByteCount = vCount * 6 * sizeof(float);
vdata = new float[vCount * 6]
{
0,0,0, /*坐标*/ 1,1,0, /*颜色*/
60,60,0, 1,1,1,
-60,60,0, 0,1,0,
-60,-60,0, 1,1,1,
50,-60,0, 1,1,0
};
}
MyVulkanManager.h下面添加绘制方式的变量
//绘制用对象
static DrawableObjectCommon* objectForDraw;
static int topologyWay;//绘制方式
MyVulkanManager.cpp下初始化
int MyVulkanManager::topologyWay = 0;
void MyVulkanManager::create_vulkan_devices()下添加
VkPhysicalDeviceFeatures pdf; //存储设备所支持特性的结构体实例
vkGetPhysicalDeviceFeatures(gpus[0], &pdf); //获取指定设备支持的特性
if (pdf.wideLines == VK_TRUE) //判断是否支持wideLines特性
{
printf("支持wideLines特性!\n");
} //打印调试信息
else { printf("不支持wideLines特性!\n"); }
//获取后给deviceInfo.pEnabledFeatures传入获取的参数
deviceInfo.pEnabledFeatures = &pdf;//启用的设备特性
重新初始化摄像头参数和setProjectFrustum
void MyVulkanManager::initMatrix()
{
MatrixState3D::setCamera(0, 0, 200, 0, 0, 0, 0, 1, 0);
MatrixState3D::setInitStack();
float ratio = (float)screenWidth / (float)screenHeight;
MatrixState3D::setProjectFrustum(-ratio, ratio, -1, 1, 1.5f, 1000);
}
修改
ShaderQueueSuit_Common.h
添加公有成员
/*绘制方式总数*/
static const int topologyCount = 3;
修改pipeline为一个数组
//管线
VkPipeline pipeline[topologyCount];
修改
ShaderQueueSuit_Common.cpp
VkPipelineInputAssemblyStateCreateInfo ia;//管线图元组装状态创建信息
ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia.pNext = NULL;//自定义数据的指针
ia.flags = 0;//供将来使用的标志
ia.primitiveRestartEnable = VK_FALSE;//关闭图元重启
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; //采用三角形图元列表模式
//声明了一个长度为topologyCount的管线图元组装状态创建信息结构体实例数组,topologyCount的值为3,对应本案例中的3种绘制方式。
VkPipelineInputAssemblyStateCreateInfo ia[topologyCount]; //管线图元组装状态创建信息数组
//遍历了前面声明的数组中的每个元素,对各个元素的属性进行设置。最主要的是根据元素索引的不同,设置了不同的绘制方式(即图元组装方式)
for (int i = 0; i < topologyCount; ++i)
{ //遍历数组中每个元素进行初始化
ia[i].sType = //指定结构体类型
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia[i].pNext = NULL; //自定义数据的指针
ia[i].flags = 0; //供将来使用的标志位
ia[i].primitiveRestartEnable = VK_FALSE; //关闭图元重启
switch (i) { //数组中的每个元素设置不同的图元组装方式
case 0:ia[i].topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; break; //点列表方式
case 1:ia[i].topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; break; //线段列表方式
case 2:ia[i].topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; break; //折线方式
}
}
删掉
pipelineInfo.pInputAssemblyState = &ia;//管线的图元组装状态信息
函数结尾修改
result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineInfo, NULL, &pipeline);
assert(result == VK_SUCCESS);
为
//创建了topologyCount个管线,每个管线对应一种绘制方式。同时将创建的管线依次存储在pipeline数组中,以备后面绘制时使用。
for (int i = 0; i<topologyCount; i++)
{ //为每种图元组装方式创建管线
pipelineInfo.pInputAssemblyState = &ia[i]; //指定管线的图元组装状态信息
result = vkCreateGraphicsPipelines //创建管线
(device, pipelineCache, 1, &pipelineInfo, NULL, &pipeline[i]);
assert(result == VK_SUCCESS); //检查管线创建是否成功
}
采用点、线段等绘制方式时,默认情况下点的大小仅有一个像素,线段的粗细也是一个像素。如果需要更大的点或更粗的线段,就需要修改点的大小、线段的粗细设置。首先介绍线段粗细的设置
rs.lineWidth = 15.0f;//线宽度(仅在线绘制模式起作用)
销毁管线
void ShaderQueueSuit_Common::destroy_pipe_line(VkDevice& device){ //销毁管线 for (int i = 0; i<topologyCount; i++) { vkDestroyPipeline(device, pipeline[i], NULL); } //销毁管线缓冲 vkDestroyPipelineCache(device, pipelineCache, NULL);}
接下来在
void MyVulkanManager::drawObject()中的
MatrixState3D::pushMatrix(); //保护现场
MatrixState3D::rotate(xAngle, 1, 0, 0); //绕X轴旋转xAngle
MatrixState3D::rotate(yAngle, 0, 1, 0); //绕Y轴旋转yAngle
MatrixState3D::pushMatrix();//保护现场
objForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout, sqsCL->pipeline,
&(sqsCL->descSet[0]));//绘制第一个立方体
MatrixState3D::popMatrix();//恢复现场
MatrixState3D::pushMatrix();//保护现场
MatrixState3D::translate(3.5f, 0, 0);//沿x方向平移3.5
MatrixState3D::rotate(30, 0, 0, 1); //绕z轴旋转30°
MatrixState3D::scale(0.4f, 2.0f, 0.6f); //x、y、z 3个方向按各自的缩放因子进行缩放
objForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout, sqsCL->pipeline,
&(sqsCL->descSet[0]));//绘制变换后的立方体
MatrixState3D::popMatrix();//恢复现场
改为
vkCmdBeginRenderPass(cmdBuffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
//添加
objForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout, sqsCL->pipeline[topologyWay], &(sqsCL->descSet[0]));
vkCmdEndRenderPass(cmdBuffer);//结束渲染通道
修改void MyVulkanManager::createDrawableObject()
//创建绘制用物体
ObjectData::genVertexData();
//objForDraw = new DrawableObjectCommonLight(CubeData::vdata, CubeData::dataByteCount, CubeData::vCount, device, memoryroperties);
objForDraw = new DrawableObjectCommonLight(ObjectData::vdata, ObjectData::dataByteCount, ObjectData::vCount, device, memoryroperties);
最后运行发现每有显示,查找代码原来是
void ShaderQueueSuit_Common::create_pipeline_layout(VkDevice& device)
创建管线中下列代码
const unsigned push_constant_range_count = 1; //推送常量块数量
VkPushConstantRange push_constant_ranges[push_constant_range_count] = {};
push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; //指定结构体类型
push_constant_ranges[0].offset = 0; //推送常量数据起始偏移量
push_constant_ranges[0].size = sizeof(float) * 16; //推送常量数据字节总数
没有删掉
推送常量(push constants)不为空
添加单击屏幕切换
之前
objForDraw->drawSelf(cmdBuffer, sqsCL->pipelineLayout, sqsCL->pipeline[topologyWay], &(sqsCL->descSet[0]));
中有一个topologyWay 标志
case XCB_BUTTON_RELEASE:
{
xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
print_modifiers(ev->state);
switch (ev->detail)
{
case 3:
if (isClick)
{
//添加3种绘制方式之间进行切换
MyVulkanManager::topologyWay = (++MyVulkanManager::topologyWay%ShaderQueueSuit_Common::topologyCount);
}
isClick = true;
mouseLeftDown = false;
printf("mouseLeftDown\n");
break;
default:
break;
}
break;
}