Vulkan渲染引擎开发教程 一、开发环境搭建

一 安装 Vulkan SDK

Vulkan SDK 就是我们要搞的图形接口
首先到官网下载SDK并安装 https://vulkan.lunarg.com/sdk/home
在这里插入图片描述

二 安装 GLFW 窗口库

GLFW是个跨平台的小型窗口库,也就是显示窗口,图形的载体
去主页下载并安装,https://www.glfw.org/download.html
根据你的平台选择包,我是Windows64位系统,所以选择64-bit Windows binaries
在这里插入图片描述

三 安装 GLM算法库

我们还需要一些算法库来减少我们的开发代价
https://github.com/g-truc/glm/releases

四 配置VS 2022

GLFW 和GLM解压放好后亲一口
在这里插入图片描述
打开VS 2022,依次点击 VS -> 项目 -> 属性 进入属性面板
在属性面板中,点击C/C++ -> 常规 -> 附加包含目录
依次填入Vulkan SDK下的include目录、glm下的glm目录、glfw下的include目录后点确定按钮
在这里插入图片描述
再点击连接器->常规->附加库目录
填写glfw下的lib–vs2022目录、vulkan下的Lib目录,
点确定

在这里插入图片描述
再切换到 连接器下的输入->附加依赖项
在窗口中填入vulkan-1.lib、glfw3.lib
写完后 点击确定就完成了配置
在这里插入图片描述

五 测试

在vs中创建新的项目
在这里插入图片描述
在脚本中填入以下代码

#define GLFW_INCLUDE_VULKAN // GLFW_INCLUDE_VULKAN: include the vulkan header
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <vector>

const int WINDOW_WIDTH = 800; // 窗口宽度
const int WINDOW_HEIGHT = 600; // 窗口高度

class VulkanApp {
public:
    GLFWwindow* window; // 窗口指针
    VkInstance instance; // vulkan实例

    void run() {
        initWindow(); // 初始化窗口
        createInstance(); // 创建vulkan实例
        loop(); // 主循环
        closeWindow(); // 清理窗口
    }

    // 初始化窗口
    void initWindow() {
        glfwInit(); // 初始化窗口
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);// 设置不使用OpenGL
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);// 禁止窗口大小改变
        // 创建窗口
        window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Vulkan测试", nullptr, nullptr); 
    }

    // 主循环
    void loop() {
        while (!glfwWindowShouldClose(window)) {// 如果窗口没有关闭
            glfwPollEvents();
        }
    }

    // 清理vulkan实例 和窗口
    void closeWindow() {
        vkDestroyInstance(instance, nullptr);// 清理vulkan实例
        glfwDestroyWindow(window);// 清理窗口
        glfwTerminate();// 清理控制台
    }

    //  创建vulkan实例
    void createInstance() {
        VkApplicationInfo appInfo = {}; // 用于向vulkan驱动程序传递信息
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; // 指定结构体类型
        appInfo.pApplicationName = "vulkan test"; // 指定应用程序名称
        appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); // 指定应用程序版本
        appInfo.pEngineName = "No Engine"; // 指定引擎名称
        appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); // 指定引擎版本
        appInfo.apiVersion = VK_API_VERSION_1_0; // 指定vulkan版
        VkInstanceCreateInfo createInfo = {}; // 用于指定vulkan实例的扩展和验证层
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // 指定结构体类型
        createInfo.pApplicationInfo = &appInfo; // 指定应用程序信息
        uint32_t glfwExtensionCount = 0; // glfw扩展数量
        const char** glfwExtensions; // glfw扩展
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); // 获取glfw扩展
        createInfo.enabledExtensionCount = glfwExtensionCount; // 指定扩展数量
        createInfo.ppEnabledExtensionNames = glfwExtensions; // 指定扩展
        createInfo.enabledLayerCount = 0; // 指定验证层数量
        if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { // 创建vulkan实例
            throw std::runtime_error("create instance failed!"); // 创建失败
        } else {
            printf("create instance success!"); // 创建成功
        }
    }
};

int main() {
    VulkanApp app; // 创建vulkan实例

    try {
        app.run(); // 运行vulkan实例
    } catch (const std::exception& e) { // 捕获异常
        std::cerr << e.what() << std::endl; // 输出异常信息
        return EXIT_FAILURE; // 退出程序
    }

    return EXIT_SUCCESS; // 退出程序
}

// 用vulkan实现绘制三角形的类

运行成功会显示两个窗口,一个是用于显示调试信息的控制台,一个就是用于显示vukan实例的glfw窗口,长这样
在这里插入图片描述
在下一章中,将尝试在vulkan中绘制一个三角形。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
下面是一个简单的使用Vulkan API编写渲染管线的示例代码: ```c++ #include <vulkan/vulkan.h> #include <vector> #include <iostream> int main() { // 初始化Vulkan实例 VkInstance instance; VkInstanceCreateInfo instanceCreateInfo = {}; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; vkCreateInstance(&instanceCreateInfo, nullptr, &instance); // 获取Vulkan设备列表 uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); std::vector<VkPhysicalDevice> physicalDevices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data()); // 选择第一个物理设备 VkPhysicalDevice physicalDevice = physicalDevices[0]; // 获取设备属性 VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); // 创建设备 VkDevice device; VkDeviceCreateInfo deviceCreateInfo = {}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device); // 获取队列族索引 uint32_t queueFamilyIndex = 0; VkQueueFamilyProperties queueFamilyProperties; vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, &queueFamilyProperties); for (uint32_t i = 0; i < queueFamilyCount; i++) { if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { queueFamilyIndex = i; break; } } // 创建命令池 VkCommandPool commandPool; VkCommandPoolCreateInfo commandPoolCreateInfo = {}; commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; vkCreateCommandPool(device, &commandPoolCreateInfo, nullptr, &commandPool); // 创建渲染管线 VkShaderModule vertexShaderModule; VkShaderModuleCreateInfo vertexShaderCreateInfo = {}; // 加载顶点着色器GLSL代码 vertexShaderCreateInfo.codeSize = sizeof(vertexShaderCode); vertexShaderCreateInfo.pCode = vertexShaderCode; vkCreateShaderModule(device, &vertexShaderCreateInfo, nullptr, &vertexShaderModule); VkShaderModule fragmentShaderModule; VkShaderModuleCreateInfo fragmentShaderCreateInfo = {}; // 加载片段着色器GLSL代码 fragmentShaderCreateInfo.codeSize = sizeof(fragmentShaderCode); fragmentShaderCreateInfo.pCode = fragmentShaderCode; vkCreateShaderModule(device, &fragmentShaderCreateInfo, nullptr, &fragmentShaderModule); VkPipelineShaderStageCreateInfo shaderStages[2] = {}; shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; shaderStages[0].module = vertexShaderModule; shaderStages[0].pName = "main"; shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; shaderStages[1].module = fragmentShaderModule; shaderStages[1].pName = "main"; VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo = {}; vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo = {}; inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssemblyCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; VkViewport viewport = {}; viewport.x = 0.0f; viewport.y = 0.0f; viewport.width = WIDTH; viewport.height = HEIGHT; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor = {}; scissor.offset = {0, 0}; scissor.extent = {WIDTH, HEIGHT}; VkPipelineViewportStateCreateInfo viewportCreateInfo = {}; viewportCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportCreateInfo.viewportCount = 1; viewportCreateInfo.pViewports = &viewport; viewportCreateInfo.scissorCount = 1; viewportCreateInfo.pScissors = &scissor; VkPipelineRasterizationStateCreateInfo rasterizationCreateInfo = {}; rasterizationCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizationCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; rasterizationCreateInfo.cullMode = VK_CULL_MODE_BACK_BIT; rasterizationCreateInfo.frontFace = VK_FRONT_FACE_CLOCKWISE; rasterizationCreateInfo.lineWidth = 1.0f; VkPipelineMultisampleStateCreateInfo multisampleCreateInfo = {}; multisampleCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState colorBlendAttachment = {}; colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; colorBlendAttachment.blendEnable = VK_FALSE; VkPipelineColorBlendStateCreateInfo colorBlendCreateInfo = {}; colorBlendCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlendCreateInfo.attachmentCount = 1; colorBlendCreateInfo.pAttachments = &colorBlendAttachment; VkPipelineLayout pipelineLayout; VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout); VkGraphicsPipelineCreateInfo pipelineCreateInfo = {}; pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineCreateInfo.stageCount = 2; pipelineCreateInfo.pStages = shaderStages; pipelineCreateInfo.pVertexInputState = &vertexInputCreateInfo; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyCreateInfo; pipelineCreateInfo.pViewportState = &viewportCreateInfo; pipelineCreateInfo.pRasterizationState = &rasterizationCreateInfo; pipelineCreateInfo.pMultisampleState = &multisampleCreateInfo; pipelineCreateInfo.pColorBlendState = &colorBlendCreateInfo; pipelineCreateInfo.layout = pipelineLayout; pipelineCreateInfo.renderPass = renderPass; vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline); // 渲染 VkCommandBuffer commandBuffer; VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; commandBufferAllocateInfo.commandPool = commandPool; commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; commandBufferAllocateInfo.commandBufferCount = 1; vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer); VkCommandBufferBeginInfo commandBufferBeginInfo = {}; commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo); vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdDraw(commandBuffer, 3, 1, 0, 0); vkCmdEndRenderPass(commandBuffer); vkEndCommandBuffer(commandBuffer); // 释放资源 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyShaderModule(device, vertexShaderModule, nullptr); vkDestroyShaderModule(device, fragmentShaderModule, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipeline(device, pipeline, nullptr); vkDestroyDevice(device, nullptr); vkDestroyInstance(instance, nullptr); return 0; } ``` 需要注意的是,上述示例代码仅仅是一个简单的渲染管线,实际应用中还需要添加更多的细节和逻辑,例如纹理加载、深度测试、光照等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千年奇葩

从来没受过打赏,这玩意好吃吗?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值