3

嗨,我在尝试创建动态纹理以在我的食人魔窗口中指定为背景时遇到问题。我想为纹理的每个像素动态分配值,然后将此纹理用作背景。我使用此代码创建动态纹理。

Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("BackgroundTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 800, 600, 0, Ogre::PF_R8G8B8, Ogre:: TU_DYNAMIC);

Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("BackgroundMat",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
material->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTex");
material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_COLOUR);

Ogre::Rectangle2D* rect = new Ogre::Rectangle2D(true);
rect->setCorners(-1.0, 1.0, 1.0, -1.0);

rect->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND);
rect->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE, 100000.0 * Ogre::Vector3::UNIT_SCALE));

Ogre::SceneNode* node = sceneManager->getRootSceneNode()->createChildSceneNode("BackgroundMat");
node->attachObject(rect);
node->setVisible(true);
rect->setMaterial("BackgroundMat");
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);

for(size_t i=0; i < 600; i++)
{    
   for(size_t j=0; j < 800; j++)
   {    
      *pDest++ = 0;
      *pDest++ = 0;
      *pDest++ = 255;

   }
}

pixelBuffer->unlock();

在这段代码中,我为每个值分配了蓝色( R:0 G:0 B:255 )。我希望获得完整的蓝色窗口,但我获得的不是蓝色背景,而是图片中看到的这个背景。 在此处输入图像描述

在我获得的纹理中,不是蓝色背景,而是有 3 种不同的颜色类型,它们总是依次重复。蓝色像素是真实的,但其他 2 种颜色也是蓝色的。我找不到导致此问题的原因。我能做些什么?什么是错误的部分?

4

2 回答 2

2

根据克里斯托弗的评论:

我没有使用 Ogre3D 的经验,但它是否真的可以为您提供 RGBA(或 BGRA 或 ARGB)的图像数据,而不仅仅是 RGB。所以你错过了一个额外的pDest++(或者可能*pDest++ = 255),因此在第一个循环交互中你得到蓝色,然后是绿色,然后是红色,然后是蓝色,......,这将与你显示的图像重合。

编辑:++pDest在您的评论中,您说(如果我理解正确的话)当您在循环中添加附加图像时,您会得到一个完全红色的图像。这至少告诉我们,您确实从 Ogre3D 获得了 4 分量图像,因为我们现在不再与颜色不同步并且只有单一颜色。但由于这种颜色是红色的,Ogre3D 似乎将图像数据作为 BGRA 提供给您。所以只需将第一个组件设置为 255 而不是第三个(当然还要++pDest在其中保留这个附加值)。

您可能已将纹理指定为PF_R8G8B8,但似乎 Ogre3D 在缓冲区中图像数据的布局方面有一些自由度,实际上图形驱动程序在纹理的内存布局方面也有一些自由度,通常是 32 位 RGBA 或 BGRA图像比 24 位 RGB 有一些优势。

它还可能取决于 Ogre3D 使用的底层图形 API(D3D 或 GL)以及那里的标准。例如,在 GL 中,您不能直接映射纹理内存,需要为此使用 PBO,其内存布局又可以与纹理不同。我不了解 D3D,但我认为 D3D 特别喜欢 BGRA 布局。

编辑:您还可以查看pixelBox.format数据的格式。

于 2011-11-18T13:44:28.573 回答
1

我遇到了同样的问题。

您创建的纹理格式为Ogre::PF_R8G8B8,但 Ogre 使用的实际硬件缓冲区仍然是Ogre::PF_R8G8B8A8,这意味着它是 4 位而不是 3 位。

您可以在循环中添加另一行:

pDest++;
于 2012-10-07T12:22:21.043 回答