I submitted this to gamedev, but they seem rather slow so I hope I could find an answer here.
I've been messing with C++ AMP and OGRE in attempt to make writing to/altering textures to my liking easier on my behalf. In this I've been trying to draw a texture onto my "dynamic" texture with strange results. It appears that a solid 3/4 of my image is cropped off and it's driving me mad as I cannot seem to find the fix.
Here's a video of the problem: http://www.youtube.com/watch?v=uFWxHtHtqAI
And here's all of the necessary code for the sake of understanding even though the kernel is really where the issue at hand rests:
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;
}
As you can see, the dynamic texture is the size of the window (which in this case is 800x600) and the minotaur.jpg is 84x84. I'm simply placing it at half the width and height (center), rotating it by ang (radians), and scaling it to 4x.
In the kernel itself, I simply followed a 2D rotation matrix (where x and y are offset by the parameters 'x' and 'y'):
x' = x cosθ - y sinθ
y' = x sinθ + y cosθ
Also note that idx[1] represents the x value in the array and idx[0] represents the y because it's arranged in the manner that value = buffer[y + (x * height)]
(or something along those lines, but just know it's in the correct format).
Thanks for any and all help!
Regards,
Tannz0rz