2013-03-07 51 views
0

我将此内容提交给gamedev,但它们看起来相当慢,所以我希望我能在这里找到答案。通过原始缓冲区数据缩放和旋转纹理到另一个纹理上

我一直在乱搞C++ AMP和OGRE,试图以我的名义写作/更改我喜欢的纹理。在这个我一直试图画一个纹理到我的“动态”纹理与奇怪的结果。看起来,我的图像3/4的固体被裁剪掉了,它让我发疯,因为我似乎找不到修复。

这里的问题的视频:http://www.youtube.com/watch?v=uFWxHtHtqAI

而这里的一切为便于理解必要的代码,即使内核是真的,其中在手的问题在于:

DynamicTexture.h

#define ValidTexCoord(x, y, width, height) ((x) >= 0 && (x) < (width) && (y) >= 0 && (y) < (height)) 

void TextureKernel(array<uint32, 2> &buffer, array_view<uint32, 2> texture, uint32 x, uint32 y, Real rot, Real scale, bool alpha) 
{ 
    Real 
     c = cos(-rot)/scale, 
     s = sin(-rot)/scale; 
    int32 
     //e = int32(sqrt((texture.extent[1] * texture.extent[1]) + (texture.extent[0] * texture.extent[0])) * scale * 0.5F), 
     dx = texture.extent[1]/2, 
     dy = texture.extent[0]/2; 

    parallel_for_each(buffer.extent, [=, &buffer](index<2> idx) restrict(amp) 
    { 
     int32 
      tex_x = int32((Real(idx[1] - x) * c) - (Real(idx[0] - y) * s)) + dx, 
      tex_y = int32((Real(idx[1] - x) * s) + (Real(idx[0] - y) * c)) + dy; 

     if(ValidTexCoord(tex_x, tex_y, texture.extent[1], texture.extent[0])) 
     { 
      if(!alpha || (alpha && texture(tex_y, tex_x) != 0)) 
      { 
       buffer(idx) = texture(tex_y, tex_x); 
      } 
     } 
     else 
     { 
      buffer(idx) = 0x336699FF; 
     } 
    }); 
} 

template<typename T, int32 Rank> 
void SetKernel(array<T, Rank> &arr, T val) 
{ 
    parallel_for_each(arr.extent, [&arr, val](index<Rank> idx) restrict(amp) 
    { 
     arr(idx) = val; 
    }); 
} 

class DynamicTexture 
{ 
    static int32 
     id; 

    array<uint32, 2> 
     buffer; 

public: 
    const int32 
     width, 
     height; 

    TexturePtr 
     textureptr; 

    DynamicTexture(const int32 width, const int32 height, uint32 color = 0) : 
     width(width), 
     height(height), 
     buffer(extent<2>(height, width)) 
    { 
     SetKernel(buffer, color); 

     textureptr = TextureManager::getSingleton().createManual("DynamicTexture" + StringConverter::toString(++id), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TextureType::TEX_TYPE_2D, width, height, 0, PixelFormat::PF_A8R8G8B8); 
    } 

    ~DynamicTexture() 
    { 
    } 

    void Texture(TexturePtr texture, uint32 x, uint32 y, Real rot = 0.F, Real scale = 1.F, bool alpha = false) 
    { 
     HardwarePixelBufferSharedPtr 
      pixelbuffer = texture->getBuffer(); 

     TextureKernel(buffer, array_view<uint32, 2>(texture->getHeight(), texture->getWidth(), (uint32 *)pixelbuffer->lock(HardwareBuffer::HBL_READ_ONLY)), x, y, rot, scale, alpha); 

     pixelbuffer->unlock(); 
    } 

    void CopyToBuffer() 
    { 
     HardwarePixelBufferSharedPtr 
      pixelbuffer = textureptr->getBuffer(); 

     copy(buffer, stdext::make_checked_array_iterator<uint32 *>((uint32 *)pixelbuffer->lock(HardwareBuffer::HBL_DISCARD), width * height)); 

     pixelbuffer->unlock(); 
    } 

    void Reset(uint32 color) 
    { 
     SetKernel(buffer, color); 
    } 
}; 

int32 
    DynamicTexture::id = 0; 

的main.cpp

void initScene() 
{ 
    dynamictexture = new DynamicTexture(window->getWidth(), window->getHeight()); 

    TextureManager::getSingleton().load("minotaur.jpg", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TextureType::TEX_TYPE_2D, 0); 
} 

bool frameStarted(const FrameEvent &evt) 
{ 
    static Real 
     ang = 0.F; 

    ang += 0.05F; 

    if(ang > Math::TWO_PI) 
    { 
     ang = 0.F; 
    } 

    dynamictexture->Reset(0); 
    dynamictexture->Texture(TextureManager::getSingleton().getByName("minotaur.jpg"), dynamictexture->width/2, dynamictexture->height/2, ang, 4.F, true); 
    dynamictexture->CopyToBuffer(); 

    return true; 
} 

如您所见,动态纹理是窗口的大小(在本例中为800x600),minotaur.jpg为84x84。我只是把它放在宽度和高度的一半(中心),用ang(弧度)旋转它,并将它缩放到4倍。

在内核本身,我简单跟着一个2D旋转矩阵(其中x和y是由参数 'x' 和 'y' 的偏移量):

x' = x cosθ - y sinθ 
y' = x sinθ + y cosθ 

还要注意,IDX [1]表示数组中的x值和idx [0]表示y,因为它的排列方式为value = buffer[y + (x * height)](或沿着这些行的东西,但只知道它的格式正确)。

感谢您的帮助!

问候, Tannz0rz

回答

0

我找到了解决办法感谢这个家伙:https://sites.google.com/site/ofauckland/examples/rotating-pixels

const Real 
    HALF_PI = Math::HALF_PI; 
const int32 
    cx = texture.extent[1]/2, 
    cy = texture.extent[0]/2; 

parallel_for_each(buffer.extent, [=, &buffer](index<2> idx) restrict(amp) 
{ 
    int32 
     tex_x = idx[1] - x, 
     tex_y = idx[0] - y; 
    Real 
     dist = sqrt(Real((tex_x * tex_x) + (tex_y * tex_y)))/scale, 
     theta = atan2(Real(tex_y), Real(tex_x)) - angle - HALF_PI; 

    tex_x = int32(dist * sin(theta)) + cx; 
    tex_y = int32(dist * cos(theta)) + cy; 

    if(ValidTexCoord(tex_x, tex_y, texture.extent[1], texture.extent[0])) 
    { 
     buffer(idx) = texture(tex_y, tex_x); 
    } 
});