c++ - 使用 INTEL 显卡在单通道整数纹理上的离屏渲染问题
问题描述
我有一个带有一些三角形网格的 3D 场景,我正在执行屏幕外渲染以将它们绘制到三个纹理上:
- 像往常一样渲染我的 3D 场景的 RGBA 颜色纹理。
- 一个单通道 INTEGER 纹理,用于用鼠标选择我渲染的项目。每个项目都有自己唯一的整数 id。当用户点击屏幕上的一个像素时,我可以检查在该位置写入了哪个值,以找出点击了哪个项目。
- 深度纹理。
我正在创建一个framebuffer,创建纹理,并按以下方式格式化它们:
glGenFramebuffers(1, &_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
glGenTextures(1, &_sceneTex );
glGenTextures(1, &_pickingTex );
glGenTextures(1, &_depthTex );
glBindTexture(GL_TEXTURE_2D, _sceneTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _sceneTex, 0);
glBindTexture(GL_TEXTURE_2D, _pickingTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, width, height, 0, GL_RED_INTEGER, GL_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _pickingTex, 0);
glBindTexture(GL_TEXTURE_2D, _depthTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTex, 0);
GLenum drawBuffers[2] = {GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, drawBuffers);
在片段着色器中,颜色和项目 ID 被写入布局:
...
uniform int itemID;
layout( location = 0 ) out vec4 fragmentColor;
layout( location = 1 ) out int pickingInfo;
...
void main()
{
//Compute the fragment color somehow and write to fragmentColor variable.
fragmentColor = vec4(color, 1.0f);
pickingInfo = itemID;
}
每次渲染调用后,场景纹理都会复制到屏幕上。
并且拾取纹理应该始终存在,当用户需要选择一个项目时可用。
在渲染场景中的所有项目之前,以这种方式清理纹理:
float backColor[4] = {_backgroundColor.red() / 255.f,
_backgroundColor.green() / 255.f,
_backgroundColor.blue() / 255.f,
_backgroundColor.alpha() / 255.f};
glClearBufferfv(GL_COLOR, GL_COLOR_ATTACHMENT0, backColor);
int invalidID = -1;
glClearBufferiv(GL_COLOR, GL_COLOR_ATTACHMENT1, &invalidID);
为了读取写在点击位置 (x, y)的 id ,我这样做:
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
glReadBuffer(GL_COLOR_ATTACHMENT1);
int value = -1;
int x = static_cast<int>(screenPoint.x());
int y = height() - static_cast<int>(screenPoint.y());
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, &value);
问题是:我的 NVIDIA GeForce MX250 一切正常。但是当我使用 Intel(R) UHD Graphics 时,我的行为最奇怪。
每个渲染的项目都有一个glDrawElements
调用。渲染项目 X 时,其唯一 ID 被传递给着色器,着色器将其写入项目所在片段中的拾取纹理上。
现在,我只能选择渲染的第一个项目。当我在屏幕上单击它时,我使用 glReadPixels 成功获取了它的 ID。对于我点击的其他任何地方(甚至在其他项目上),我都会得到我设置的“明确值”。
有人知道我可能做错了什么吗?我做了什么不标准的事情吗?
解决方案
推荐阅读
- android - Intellij IDEA 2019 中的离线 Android Gradle 插件 3.5.0
- alexa - 如何从传感器发送 Alexa 智能家居主动变更报告?
- algorithm - 求二叉树高度的递归关系和时间复杂度
- r - 如何根据结束日期和天数计算开始日期
- c# - 让 .net SqlConnection 无限期打开与 using 块
- xcode - 如何将 tensorflow-lite 模型转换为 coreml .mlmodel
- api - 除了 API 调用或套接字之外,还有其他从服务器获取实时数据的选项吗?
- android - 如何从 recyclerview 项目中打开活动?
- android - 适用于 Android 的类似 iOS 的导航抽屉?
- sql - 按两个条件分组