要在 OpenGL 中创建统一的缓冲区对象,为什么我必须同时调用glBindBuffer和glBindBufferRange?根据文件,
\n\n\n将 glBindBufferRange 视为将缓冲区绑定到两个位置:特定索引和目标\xe2\x80\x8b。glBindBuffer 仅绑定到目标\xe2\x80\x8b,而不是索引。
\n
因此,glBindBuffer如果您已经使用将缓冲区绑定到同一目标,那么对我来说似乎是多余的glBindBufferRange。
我正在阅读学习现代 3D 图形编程,第 7 章展示了如何制作统一的缓冲区对象。书中使用的代码:
\n\nglGenBuffers(1, &g_GlobalMatricesUBO);\nglBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);\nglBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, NULL, GL_STREAM_DRAW);\nglBindBuffer(GL_UNIFORM_BUFFER, 0);\n\nglBindBufferRange(GL_UNIFORM_BUFFER, g_iGlobalMatricesBindingIndex, g_GlobalMatricesUBO, 0, sizeof(glm::mat4) * 2);\nRun Code Online (Sandbox Code Playgroud)\n\n这段代码一直有效,直到我注释掉对 glBufferData 的调用,在这种情况下我会得到黑屏。这让我感到惊讶,因为之后我们无论如何都会绑定g_GlobalMatricesUBO到GL_UNIFORM_BUFFER绑定目标。之前链接的文档还说:
\n\n\n请注意,这不会用 glBindBuffer 取代标准缓冲区绑定。事实上,它确实将缓冲区绑定到 target\xe2\x80\x8b 参数,从而解除绑定到该目标的任何内容。但通常当你使用 glBindBufferRange 时,你是认真想要使用缓冲区而不是仅仅修改它。
\n
这似乎触及了我的困惑,但我不明白这个解释。它说它会解除之前绑定到目标的任何内容的绑定,这似乎强化了我的(错误)想法,即事先将缓冲区绑定到目标是不必要的。
\n我正在关注 Vulkan 教程,窗口表面部分表示在 Windows 上VkSurfaceKHR使用以下代码创建对象:
VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.hwnd = glfwGetWin32Window(window);
createInfo.hinstance = GetModuleHandle(nullptr);
if (vkCreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create window surface!");
}
Run Code Online (Sandbox Code Playgroud)
但我们从不指定对象表面的范围createInfo。
然而,调用该vkGetPhysicalDeviceSurfaceCapabilitiesKHR函数会返回一个VkSurfaceCapabilitiesKHR对象,该对象具有一个currentExtent字段,根据文档该字段是
表面的当前宽度和高度,或特殊值(0xFFFFFFFF、0xFFFFFFFF),表示表面大小将由针对该表面的交换链的范围确定。
因此,在等于 (0xFFFFFFFF, 0xFFFFFFFF) 的特殊情况下,currentExtent我们知道表面的大小是由针对该表面的交换链决定的,但在所有其他情况下,表面似乎已经具有源自其他地方的大小,我们是期望将交换链的范围与该大小相匹配。
那么,当表面的大小不是由交换链确定时,它从何而来呢?