Sign in to follow this  
cache_hit

2d graphics in D3D 10

Recommended Posts

cache_hit    614
I'm just starting to become familiar with Direct3D 10. I'm trying to do a simple 2D app. To load the various images in the game, I use D3DX10CreateTextureFromFile(), which gives me an ID3D10Resource* which is ultimately an ID3D10Texture2D. I want to draw this texture at position (x,y) on the screen, but I'm not clear on the correct approach to do so. I've already created my shader resource views and filled in a D3DX10_SPRITE structure with the relevant info. I'm using the sequence of sprite->Begin() foreach (texture) sprite->DrawSpritesBuffered(texture) sprite->Flush() sprite->End() and this gets an image drawing on the screen, but the size is completely wrong, and it doesn't put it at the position x,y I want. Essentially I'd like a function:
void draw_texture(ID3D10Texture2D* texture, ID3DX10Sprite* sprite, D3DXVECTOR2 pos)
{
}

that I can invoke as follows:
sprite->Begin();
foreach (Entity e in entities)
    draw_texture(e.texture, sprite, e.pos);
sprite->Flush();
sprite->End();

and draws the sprite at device coordinates (e.pos.x, e.pos.y) with no scaling. Thanks

Share this post


Link to post
Share on other sites
MJP    19786
You don't have to manually create a shader resource view, if you don't want. You can just use D3DX10CreateShaderResourceViewFromFile.

Drawing it should just be as simple as this:

void draw_texture(ID3D10ShaderResourceView* texture, ID3DX10Sprite* sprite, D3DXVECTOR2 pos)
{
D3DX10_SPRITE spriteInfo;
D3DXMatrixTranslation(&spriteInfo.matWorld, pos.x, pos.y, 0.0f);
spriteInfo.TexCoord = D3DXVECTOR2(0, 0);
spriteInfo.TexSize = D3DXVECTOR2(1, 1);
spriteInfo.ColorModulate = D3DXCOLOR(1, 1, 1, 1);
spriteInfo.pTexture = texture;
spriteInfo.TextureIndex = 0;
sprite->DrawSpritesBuffered(&spriteInfo, 1);
}


You'll of course want to add error checking to that DrawSpritesBuffered call.

Share this post


Link to post
Share on other sites
cache_hit    614
Sorry for the late response, didn't have a chance to get back to looking at this until just now. Here's the code I use to actually do the draw.


void sprite_batch::draw(d3d_texture_resource& texture, const D3DXVECTOR2& pos, D3DXCOLOR modulate)
{
D3DX10_SPRITE sprite;
sprite.ColorModulate = modulate;
::D3DXMatrixTranslation(&sprite.matWorld, pos.x, pos.y, 0.0f);
sprite.pTexture = texture.gpu_resource();
sprite.TexCoord = D3DXVECTOR2(0.0f, 0.0f);
sprite.TexSize = D3DXVECTOR2(1.0f, 1.0f);
sprite.TextureIndex = 0;

BOOST_ASSERT(sprite.pTexture);

VERIFY_HR(sprite_->DrawSpritesBuffered(&sprite, 1));
}




If I run the code above, it draws in the seemingly the correct location but is *much* larger than the original image. In fact, it's being stretched to exactly one-fourth of the window area.

If I call ID3D10Texture2D::GetDesc() prior to the DrawSpritesBuffered just as a sanity check, it tells me that indeed the dimensions are 32x32.

I load the texture with


::D3DX10CreateTextureFromFile(app.graphics().device(), path.c_str(), nullptr, nullptr, &resource_, nullptr);



and the shader resource view with:


device_->CreateShaderResourceView(resource_, nullptr, &view_);



What am I missing?

Thanks

Share this post


Link to post
Share on other sites
cache_hit    614
Something else interesting... Basically the image I'm trying to render is a white background with a gray circle. Just for testing.

No matter what I set sprite.TexSize to, the actual rectangular area of the image that gets rendered does not change. The only thing that changes is what the inside of that rectangle looks like. If I set TexSize to D3DXVECTOR2(1,1) the circle fills the white rectangle as it should, the problem is just that the rectangle is way too big, not even close to the size of the actual .bmp file I'm loading it from. If I set TexSize larger than (1,1) then again the white rectangle is the same size, but the actual circle gets very small, and looks as if someone had coated it in paint and dragged it along the left and top of the white rectangle to make horizontal and vertical lines parallel to the respective edges.

Even if I set TexSize to D3DXVECTOR3(0,0) it's still drawing a large white rectangle with (length,width) exactly equal to half of the window I'm drawing in. But in that case the entire rectangle is solid white, no circle.

Share this post


Link to post
Share on other sites
cache_hit    614
Quote:
Original post by shultays
is your texture has the size of 2^n? if not it will be stretched to closest one


Yes it's 32x32. I found this post (http://www.gamedev.net/community/forums/topic.asp?topic_id=548684) and the author seems to have had the same problem. Later, in order to fix it, he did the following:


sprite.orientation.SetScaling(
(1/(engine->resolution.x/2))*file_info.Width,
(1/(engine->resolution.y/2))*file_info.Height,
1.0f);







This seems like a highly unusual thing to have to do though and I cannot make sense of it. I mean obviously it's solving the exact problem I seem to be having, which is reducing it down to 1 pixel by dividing by half the screen resolution, and then scaling up to the correct image size. But why is this necessary to begin with?

[Edited by - cache_hit on February 15, 2010 11:12:41 PM]

Share this post


Link to post
Share on other sites
cache_hit    614
Thought I would bump this one last time (won't bump it again if no responses) to see if anyone has an explanation for this behavior. I know not many people do 2D graphics in D3D though. In the meantime I'll just have to live with using the scaling, and propagating window resize events to my resource manager, but it'd be nice if I actually understood why all this was necessary.

Thanks!

Share this post


Link to post
Share on other sites
MJP    19786
Quote:
Original post by shultays
is your texture has the size of 2^n? if not it will be stretched to closest one


No it shouldn't do that. D3D10 requires support for non-power-of-2 textures, so there's no reason to scale on load.

Share this post


Link to post
Share on other sites
Ravyne    14300
How is your projection matrix set up (or is the sprite stuff supposed to take care of that for you)?

Does it behave any differently in fullscreen mode?

Share this post


Link to post
Share on other sites
cache_hit    614
Projection and view are both identity. Havent tried fullscreen mode, guess i could. I feel like anyone could probably repro this, just load a texture, create a view then do begin / draw / flush / end.

Share this post


Link to post
Share on other sites
DEVLiN    203
Quote:
Original post by cache_hit
Projection and view are both identity.

Wouldn't that explain it? Coordinates would range from -1, -1 to 1,1 no?

You're drawing from 0,0 (center) to 1,1, equaling one quarter of the screen?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this