为什么OpenSceneGraph将所有Sampler2D映射到第一个纹理
Why does OpenSceneGraph map all Sampler2D to the first texture
我目前正在用OpenSceneGraph(3.4.0(和我自己的glsl(330(着色器编写一个程序。 它使用多个纹理进行输入,然后使用预渲染相机执行多渲染目标渲染,并使用第二个相机读取这些多个渲染目标纹理以进行延迟着色。因此,两个相机都有自己的着色器(此处称为geometry_pass和lighting_pass(。 我的问题是:两种着色器在阅读时sampler2D
所有制服中使用相同的纹理。
//in geometry_pass.frag
uniform sampler2D uAlbedoMap;
uniform sampler2D uHeightMap;
uniform sampler2D uNormalMap;
uniform sampler2D uRoughnessMap;
uniform sampler2D uSpecularMap;
[...]
layout (location = 0) out vec4 albedo;
layout (location = 1) out vec4 height;
layout (location = 2) out vec4 normal;
layout (location = 3) out vec4 position;
layout (location = 4) out vec4 roughness;
layout (location = 5) out vec4 specular;
[...]
albedo = vec4(texture(uAlbedoMap, vTexCoords).rgb, 1.0);
height = vec4(texture(uHeightMap, vTexCoords).rgb, 1.0);
normal = vec4(texture(uNormalMap, vTexCoords).rgb, 1.0);
position = vec4(vPosition_WorldSpace, 1.0);
roughness = vec4(texture(uRoughnessMap, vTexCoords).rgb, 1.0);
specular = vec4(texture(uSpecularMap, vTexCoords).rgb, 1.0);
在这里,输出始终是uAlbedoMap
的颜色,但位置除外,位置会正确导出。
在光照通道中,当我读取几何通道的纹理时,所有输入纹理都是一样的
//in lighting_pass.frag
uniform sampler2D uAlbedoMap;
uniform sampler2D uHeightMap;
uniform sampler2D uNormalMap;
uniform sampler2D uPositionMap;
uniform sampler2D uRoughnessMap;
uniform sampler2D uSpecularMap;
[...]
vec3 albedo = texture(uAlbedoMap, vTexCoord).rgb;
vec3 height = texture(uHeightMap, vTexCoord).rgb;
vec3 normal_TangentSpace = texture(uNormalMap, vTexCoord).rgb;
vec3 position_WorldSpace = texture(uPositionMap, vTexCoord).rgb;
vec3 roughness = texture(uRoughnessMap, vTexCoord).rgb;
vec3 specular = texture(uSpecularMap, vTexCoord).rgb;
即正确导出的位置贴图在光照通道中也具有反照率的颜色。
因此,似乎正常工作的是纹理输出,但显然不起作用的是输入。 我尝试使用 CodeXL 对其进行调试,在那里我可以看到geometry_pass的所有图像(至少在某些时候(都已正确绑定,它们都是可见的。帧缓冲对象的输出纹理确认geometry_pass的位置纹理正确。 据我所知,在逐步完成此操作时,纹理已正确绑定(即统一位置正确(。
现在显而易见的问题是:如何才能在着色器中正确使用这些纹理?
方案的构建
查看器是一个osgViewer::Viewer
,所以只有一个视图。 场景图如下:displayCamera
是来自查看器的相机。由于我使用的是Qt(5.9.1(,因此在对场景图执行任何其他操作之前,我会重置GraphicsContext。
osg::ref_ptr<osg::Camera> camera = viewer.getCamera();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowDecoration = false;
traits->x = 0;
traits->y = 0;
traits->width = 640;
traits->height = 480;
traits->doubleBuffer = true;
camera->setGraphicsContext(new osgQt::GraphicsWindowQt(traits.get()));
camera->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
camera->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.6f, 1.0f));
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
camera->setViewMatrix(osg::Matrix::identity());
然后,我将displayCamera
设置到此查看器摄像机,创建第二个摄像机以渲染到纹理(因此称为rttCamera
(,并将其作为子项添加到displayCamera
中。我将场景(由包含包含硬编码几何体的geode的组节点组成(添加到rttCamera,最后创建一个屏幕四边形几何体(在geode下方,它又是矩阵变换的子级;此矩阵变换是作为子项添加到displayCamera
(。
因此,displayCamera
具有两个子rttCamera
和矩阵变换>屏幕四边形。rttCamera
具有子场景>geode。 两个摄像机都有自己的渲染蒙版,屏幕四边形使用displayCamera
s 渲染蒙版,场景使用rttCamera
s 渲染蒙版。
使用场景节点,我从文件中读取 5 个纹理(所有位图(,然后将rttCamera
渲染到具有多个渲染目标的帧缓冲对象中(用于延迟着色(。
//model is the geode in the scene group node
osg::ref_ptr<osg::StateSet> ss = model->getOrCreateStateSet();
ss->addUniform(new osg::Uniform(name.toStdString().c_str(), counter));
ss->setTextureAttributeAndModes(counter, pairNameTexture.second, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
.
//camera is the rttCamera
//bufferComponent is constructed by osg::Camera::COLOR_BUFFER0+counter
//(where counter is just an integer that gets incremented)
//texture is an osg::Texture2D that is newly created
camera->attach(bufferComponent, texture);
//the textures get stored to assign them later on
gBufferTextures[name] = texture;
这些 mrt 纹理作为纹理绑定到屏幕四边形
//ssQuad is the stateset of the screen quad geode
QString uniformName = "u" + name + "Map";
uniformName[1] = uniformName[1].toUpper();
ssQuad->addUniform(new osg::Uniform(uniformName.toStdString().c_str(), counter));
osg::ref_ptr<osg::Texture2D> tex = gBufferTextures[name];
ssQuad->setTextureAttributeAndModes(counter, gBufferTextures[name], osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
其他设置包括渲染目标(rttCamera的FBO,displayCamera的Framebuffer(,照明(在两个摄像机中关闭(。 rttCamera 获取的图形上下文与为 DisplayCamera 创建的图形上下文相同(即图形上下文对象被传递给 rttCamera 并设置为其自己的图形上下文(。
纹理附件的创建方式如下(其中使用宽度和高度或大小的 2 次方值没有区别(
osg::ref_ptr<osg::Texture2D> Utils::createTextureAttachment(int width, int height)
{
osg::Texture2D* texture = new osg::Texture2D();
//texture->setTextureSize(width, height);
texture->setTextureSize(512, 512);
texture->setInternalFormat(GL_RGBA);
texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
return texture;
}
让我知道是否缺少更多关键的解决代码或信息。
所以我终于找到了错误。我的柜台是一个显然不允许的unsigned int
。由于osg对我隐藏了如此多的错误,因此我没有看到这是一个问题......
将其更改为普通int
后,我现在在着色器中获得了不同的纹理。
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 如何仅读取文本文件中的第一个值
- 在C++中,如何在第一个"system()"结束后执行第二个"system()"?
- 查找不在标准中的第一个值::设置<int>最小-最大值
- C++:忽略第一个 cin.ignore 之后的输入
- 在C++中打印多个矢量的第一个值
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- C++第一个cout将不会打印
- 我们可以在第一个else-if条件结束后使用另一个else-if条件吗
- 将一个向量对放在一个无序映射与一个映射中
- OpenGL:第二个VBO破坏了第一个VBO
- 为什么第一个Dynamic_cast没有投射到基类?
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- C++ 为什么程序只读取第一个值
- 在我的第一个C++程序中需要一些帮助(简单)
- 为什么我的代码在第一个 if 语句处中断?
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 如何将std ::映射的第一个N元素复制到另一个地图
- 使用 STL 映射/集合/多重集/多重映射,如何查找大于或等于搜索键的第一个值