Sign in to follow this  
MrDoomMaster

Textured Quads

Recommended Posts

MrDoomMaster    103
I've been reviewing the most efficient method of using D3D to do 2D stuff. On terms of blittering bitmaps, (surface to surface copying) I found that textured quads are the best and fastest method of blittering (Direct3D version 9). The thing is, even though I read the tutorial named "2D in Direct3D using Textured Quads" by Eamonn Doherty, I still don't understand this. I have a load of confusion and would like some help... So here we go: 1) My first question lies in the content in the custom vertex structure. Is it really required to have a color value AND a texture coordinate? I have no idea what the texture coordinate is for, nor do I have any idea why the vertices would have a color. They are just coordinate specifications for the location of the bitmap, I don't want lines to be drawn or colored pixels to be shown... just the bitmap pixels!! Can I leave these out? 2) What is RHW for? I've been through many websites and I have also asked a few math professors at my college and I have learned nothing about its usefulness. I just don't get it, that's all I can say. 3) When you are filling in the vertex buffer, how does it know how large to make the buffer? For example, ::Lock() returns a BYTE pointer to the beginning of the vertex buffer, yet it doesn't tell you how large the buffer is. How do I know if I'm going to create a buffer overflow? 4) The set of custom vertices I create are the DESTINATION of the bitmap to be blittered? I have no idea where these verticies will go. I'm assuming they will be placed on the backbuffer so that it will display when flipped. 5) IDirect3DDevice9::SetTexture() asks for the texture to which my sprite sheet is located. This texture contains a loaded bitmap with several sprites bunched together. How do I tell it ONLY to blitter a specific area of the texture, rather than the whole thing? 6) IDirect3DDevice9::DrawPrimitive() is also confusing in terms of its second and third parameters. Could someone emphasize the purpose of these parameters? I have reviewed MSDN yet I still remain clueless. As you can see, I am uselessly stuck on the concept of textured quads. I am actually getting quite frustrated because this shouldn't be so hard for me, yet it is anyway. Below I'm going to paste the code I have used to test out my blitter. The code assumes a valid device and texture, which I do have. My code fails at ::DrawPrimitive(). custom vertex structure:
struct BitmapVertex
{
    float x;
    float y;
    float z;
    float rhw;
    D3DCOLOR Color;
    float tu;
    float tv;
};
Blitter function:

// Vertex Buffer, Texture, and Device are all located externally

int Blitter(int dest_x, int dest_y, RECT* source)
{
    //--Variables---------------------------------------------------
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    BitmapVertex*               Quad                            = 0;
    //--------------------------------------------------------------

    if(m_VertexBuffer->Lock(0, 0, (void**)&Quad, 0) != D3D_OK)
        return 0;

    Quad[0].x       = (float)dest_x;
    Quad[0].y       = (float)dest_y;
    Quad[0].rhw     = 1.0;
    Quad[0].tu      = 0.0;
    Quad[0].tv      = 0.0;

    Quad[1].x       = (float)dest_x + (source->right - source->left);
    Quad[1].y       = (float)dest_y;
    Quad[1].rhw     = 1.0;
    Quad[1].tu      = 1.0;
    Quad[1].tv      = 0.0;

    Quad[2].x       = (float)dest_x + (source->right - source->left);
    Quad[2].y       = (float)dest_y + (source->bottom - source->top);
    Quad[2].rhw     = 1.0;
    Quad[2].tu      = 1.0;
    Quad[2].tv      = 1.0;

    Quad[3].x       = (float)dest_x;
    Quad[3].y       = (float)dest_y + (source->bottom - source->top);
    Quad[3].rhw     = 1.0;
    Quad[3].tu      = 0.0;
    Quad[3].tv      = 1.0;

    m_VertexBuffer->Unlock();

    if(m_Device->SetTexture(0, m_Texture) != D3D_OK)
        return 0;

    if(m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) != D3D_OK)
        return 0;

    return 1;
}

Share this post


Link to post
Share on other sites
Telastyn    3777
No expert myself, might be wrong... the standard caveats.

1) Yes. [I think]

The texture coordinate are 'pegs' to map the texture to the verteces. You can change the orientation of the bitmap by changing the texture coordinates. They're also used to render only a portion of a larger image. Since texture switches are very, very slow a common trick is to put multiple images on a single texture and then use the texture coordinates to specify what image to use.

The color value is a mask [for my setup anyways]. If you render a bitmap to a polygon with only blue set, then only the blue parts of the bitmap will be rendered. If you render it with 'black' nothing will show up. This might only be with diffuse set. Not sure.

2) Dunno. Always have it set to 1. I knew vaguely at one time...

3) Looking back at my code, you set the size in CreateVertexBuffer; first parameter. And msdn concurs.

4) Yes, for all purposes.

5) See above, the texture coordinates. I've not done this myself yet.

6) The second parameter is an index.
it is essentially vertexes[parameter_2] in your vertex_buffer.

the third parameter is the number of primitives [triangles, lines, points...] to make the vertexes into.

If you specify drawprimitive(...,0,1) it will start at index 0, and draw one primitive. If you're using triangle lists for example, it will make vertex 0,1, and 2 into a triangle.

Share this post


Link to post
Share on other sites
fuchiefck    166
Hi, I'm not too sure why the code fails at DrawPrimitive, but all I can see is, you haven't set any Z values for the quaternion... and also, did you specify the FVF format when you created the vertex buffer? your custom FVF should be: D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1. Also... before you call the DrawPrimitive function, did u call the SetStreamSource and SetFVF functions?

perhaps you can post here the errors you are getting....

hope I've helped...

-fuchiefck

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Quote:
Original post by Telastyn
No expert myself, might be wrong... the standard caveats.

1) Yes. [I think]

The texture coordinate are 'pegs' to map the texture to the verteces. You can change the orientation of the bitmap by changing the texture coordinates. They're also used to render only a portion of a larger image. Since texture switches are very, very slow a common trick is to put multiple images on a single texture and then use the texture coordinates to specify what image to use.

The color value is a mask [for my setup anyways]. If you render a bitmap to a polygon with only blue set, then only the blue parts of the bitmap will be rendered. If you render it with 'black' nothing will show up. This might only be with diffuse set. Not sure.

2) Dunno. Always have it set to 1. I knew vaguely at one time...

3) Looking back at my code, you set the size in CreateVertexBuffer; first parameter. And msdn concurs.

4) Yes, for all purposes.

5) See above, the texture coordinates. I've not done this myself yet.

6) The second parameter is an index.
it is essentially vertexes[parameter_2] in your vertex_buffer.

the third parameter is the number of primitives [triangles, lines, points...] to make the vertexes into.

If you specify drawprimitive(...,0,1) it will start at index 0, and draw one primitive. If you're using triangle lists for example, it will make vertex 0,1, and 2 into a triangle.


Cool so how do I use the texture coordinates? The tutorial says specifically that u and v may only be between 0 and 1. What are the mathematics behind the texture coordinates? Could you explain, in detail, how they work? I need to know how to use them.

Thanks!

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Quote:
Original post by fuchiefck
Hi, I'm not too sure why the code fails at DrawPrimitive, but all I can see is, you haven't set any Z values for the quaternion... and also, did you specify the FVF format when you created the vertex buffer? your custom FVF should be: D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1. Also... before you call the DrawPrimitive function, did u call the SetStreamSource and SetFVF functions?

perhaps you can post here the errors you are getting....

hope I've helped...

-fuchiefck


Yes, I apologize. You just mentioned a lot of code that I left out. I'll provide more examples of code I have below:


// My DWORD
DWORD m_VertexFormat = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;


// Initialize the VertexBuffer, etc
if(m_Device->CreateVertexBuffer(sizeof(BitmapVertex) * 4, 0,
m_VertexFormat, D3DPOOL_DEFAULT, &m_VertexBuffer, 0) != D3D_OK)
{
return 0;
}


This is all the code I have involved with Textured Quads.

The other things you speak of I obviously haven't done, because I have no idea what they do / mean. I also have no idea how to set that stuff up.

Mind telling me what else I need to do?

Also, I receive no "errors", I force my application to terminate when one of the functions fail, this is how I debug. All I can tell you is that DrawPrimitive does *not* return D3D_OK.

Thank you greatly!

Share this post


Link to post
Share on other sites
Telastyn    3777
This might be completely wrong, as I've never used them really, and it's been maybe 9 months since I've done much DX work...

The UV coordinates are percentages. If you have 4 images on a sheet for example, the UV coords to place the lower right image onto a TQ would be [clockwise from UpLeft](.5,.5),(1,.5),(.5,1),(1,1). It's trying to map the entire sheet to the polygon, but the UV coords keep it confined to the image you want.

[edit below]:

As for the setup stuff....

This is code I have for 'render image' in my old system:

rtn=guiroot->d3ddev->SetStreamSource(0,vb,0,sizeof(d3d_vertex));
rtn=guiroot->d3ddev->SetFVF(vb_format);
rtn=guiroot->d3ddev->SetTexture(0,tptr);

(DrawPrimitive is the next line).
vb is the vertex buffer.
vb_format is the vertex format.
tptr is ... IDirect3DTexture9 *tptr;

That is most likely mucho overkill. I don't remember what the 0 parameters are, I've never changed them.

As for the one time initialization:

d3dif=Direct3DCreate9(D3D_SDK_VERSION);
if (!d3dif){
//die or something;
}
bzero(&d3dprops,sizeof(d3dprops));
d3dprops.Windowed=TRUE;
d3dprops.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dprops.BackBufferFormat = D3DFMT_UNKNOWN;
//d3dprops.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

d3dif->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winobj, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dprops, &d3ddev);
d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
d3ddev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_MODULATE);



This sort of stuff sets up alpha blending and other translucency. I don't know exactly how or why, but it works; and I remember what a pain it was to find just the right mix.... Hope that helps.

Share this post


Link to post
Share on other sites
setaglib    122
I'm no expert at this but in your code what I think you should be doing is first assign all the vertices... so:


Quad[0].x = (float)dest_x;

Quad[0].y = (float)dest_y;

Quad[0].rhw = 1.0;

Quad[0].tu = 0.0;

Quad[0].tv = 0.0;



Quad[1].x = (float)dest_x + (source->right - source->left);

Quad[1].y = (float)dest_y;

Quad[1].rhw = 1.0;

Quad[1].tu = 1.0;

Quad[1].tv = 0.0;



Quad[2].x = (float)dest_x + (source->right - source->left);

Quad[2].y = (float)dest_y + (source->bottom - source->top);

Quad[2].rhw = 1.0;

Quad[2].tu = 1.0;

Quad[2].tv = 1.0;



Quad[3].x = (float)dest_x;

Quad[3].y = (float)dest_y + (source->bottom - source->top);

Quad[3].rhw = 1.0;

Quad[3].tu = 0.0;

Quad[3].tv = 1.0;


THEN you lock the vertex buffer


VOID* myVertices;
m_VertexBuffer->Lock(0, sizeof(Quad), (void**)&Quad, 0);
memcpy( myVertices, Quad, sizeof(Quad) ); //copy into myVertices
m_VertexBuffer->Unlock();


As for the texture coordinates take a look at the sdk documentation its explained very well in there...

This is the code I'm using to draw a textured rectangle in my tetris clone
if that helps...

void TexRectangle(IDirect3DDevice9* dev,IDirect3DTexture9* texture,float x,float y,float sx,float sy)
{
Vertex v[4];

v[0].point[0] = x;
v[0].point[1] = y;
v[0].point[2] = 0.0f;
v[0].u = 0.0f; v[0].v = 0.0f;

v[1].point[0] = x+sx;
v[1].point[1] = y;
v[1].point[2] = 0.0f;
v[1].u = 1.0f; v[1].v = 0.0f;


v[2].point[0] = x;
v[2].point[1]= y+sy;
v[2].point[2] = 0.0f;
v[2].u = 0.0f;v[2].v = 1.0f;

v[3].point[0] = x+sx;
v[3].point[1] = y+sy;
v[3].point[2] = 0.0f;
v[3].u = 1.0f;
v[3].v = 1.0f;

dev->SetFVF(TEXVERTEXFORMAT);
dev->SetTexture(0,texture);


dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,(void*)v,sizeof(Vertex));
}




[Edited by - setaglib on June 29, 2005 12:50:12 AM]

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Let me set up a scenario.

Say I have a bitmap 512x512, and it has 32x32 sprites in it, for a total of 256 sprites.

Now lets say I want to get a sprite located in the middle somewhere, how would I set up the texture coordinates to blitter only this little 32x32 square?

To my understanding, texture coordinates are a percentage which determines how much of the *WHOLE* texture to blitter. So that means a sprite of mine could be located at 128,128,160,160 (RECT format), I would need to blitter only this small square.

I have read MSDN on texture coordinates, yet it still does not discuss how to achieve the above. Any help?


I'm honestly starting to conclude that Textured Quads suck for basic bitmap blittering for 2D space. It is far too complicated. I liked ID3DXSprite, it was very simple. Too bad the Sprite interface distorts the bitmaps when you blitter them :(

I'm not quite as lost as I was, I understand everything except for texture coordinates.

By the way, I added SetFVF() before my SetTexture() function, and DrawPrimitive() still fails :(

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Hey, I *finally* got it working, and I see bitmaps on my screen. I really thank everyone for taking me this far, but there are still just a few more questions I have, if you don't mind.

1) What exactly do all of the SetRenderState() functions do? I read MSDN on a few of the constants you can set, particularly the Alphablend state, for SRCBLEND, etc. The alpha blending modes are very confusing, I don't understand. Here is some code:


m_Device->SetRenderState(D3DRS_LIGHTING, FALSE);
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);


2) My bitmaps seem to be a little bit off on measurements. First thing I notice is that my bitmaps are blittered in a "blurry" state, or anti-aliased. For example, pixels in the bitmap are blurred, I don't know why this is happening. They shouldn't be filtered like that.

3) the RIGHT and BOTTOM edges of my bitmaps seem to be a few pixels short. It seems like these pixels aren't even being copied. Why is this so?

I'm sure most of this has to do with the way I set up my vertex structure. If you could look at my math and possibly lead me in the right direction, I would be much appreciative. Below you will find an updated version of my blitter function.

Take note that this is a method inside an interface of mine. Most of the declarations are hidden from you, yet most of this should be very evident. This function returns 0 on failure, or 1 for success:


int CBitmap::Blitter(int dest_x, int dest_y, RECT* source)
{
//--Variables---------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BitmapVertex* Quad = 0;
//--------------------------------------------------------------

if(!m_Display->IsInitialized())
return 0;

if(!m_Loaded)
return 0;

if(m_VertexBuffer->Lock(0, 0, (void**)&Quad, 0) != D3D_OK)
return 0;

Quad[0].x = (float)dest_x;
Quad[0].y = (float)dest_y;
Quad[0].z = 0.0;
Quad[0].rhw = 1.0;
Quad[0].Color = 0xffffffff;
Quad[0].tu = (float)source->left / m_TexInfo.Width;
Quad[0].tv = (float)source->top / m_TexInfo.Height;

Quad[1].x = (float)dest_x + (source->right - source->left);
Quad[1].y = (float)dest_y;
Quad[1].z = 0.0;
Quad[1].rhw = 1.0;
Quad[1].Color = 0xffffffff;
Quad[1].tu = (float)(source->left + (source->right - source->left)) / m_TexInfo.Width;
Quad[1].tv = (float)source->top / m_TexInfo.Height;

Quad[2].x = (float)dest_x + (source->right - source->left);
Quad[2].y = (float)dest_y + (source->bottom - source->top);
Quad[2].z = 0.0;
Quad[2].rhw = 1.0;
Quad[2].Color = 0xffffffff;
Quad[2].tu = (float)(source->left + (source->right - source->left)) / m_TexInfo.Width;
Quad[2].tv = (float)(source->top + (source->bottom - source->top)) / m_TexInfo.Height;

Quad[3].x = (float)dest_x;
Quad[3].y = (float)dest_y + (source->bottom - source->top);
Quad[3].z = 0.0;
Quad[3].rhw = 1.0;
Quad[3].Color = 0xffffffff;
Quad[3].tu = (float)source->left / m_TexInfo.Width;
Quad[3].tv = (float)(source->top + (source->bottom - source->top)) / m_TexInfo.Height;

m_VertexBuffer->Unlock();

if(m_Display->GetDevice()->SetStreamSource(0, m_VertexBuffer, 0, sizeof(BitmapVertex)) != D3D_OK)
return 0;

if(m_Display->GetDevice()->SetFVF(m_VertexFormat) != D3D_OK)
return 0;

if(m_Display->GetDevice()->SetTexture(0, m_Texture) != D3D_OK)
return 0;

if(m_Display->GetDevice()->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) != D3D_OK)
return 0;

return 1;
}

Share this post


Link to post
Share on other sites
Programmer16    2321
Quote:
Original post by setaglib
I'm no expert at this but in your code what I think you should be doing is first assign all the vertices... so:


Quad[0].x = (float)dest_x;

Quad[0].y = (float)dest_y;

Quad[0].rhw = 1.0;

Quad[0].tu = 0.0;

Quad[0].tv = 0.0;



Quad[1].x = (float)dest_x + (source->right - source->left);

Quad[1].y = (float)dest_y;

Quad[1].rhw = 1.0;

Quad[1].tu = 1.0;

Quad[1].tv = 0.0;



Quad[2].x = (float)dest_x + (source->right - source->left);

Quad[2].y = (float)dest_y + (source->bottom - source->top);

Quad[2].rhw = 1.0;

Quad[2].tu = 1.0;

Quad[2].tv = 1.0;



Quad[3].x = (float)dest_x;

Quad[3].y = (float)dest_y + (source->bottom - source->top);

Quad[3].rhw = 1.0;

Quad[3].tu = 0.0;

Quad[3].tv = 1.0;


THEN you lock the vertex buffer


VOID* myVertices;
m_VertexBuffer->Lock(0, sizeof(Quad), (void**)&Quad, 0);
memcpy( myVertices, Quad, sizeof(Quad) ); //copy into myVertices
m_VertexBuffer->Unlock();


This is incorrect, because the vertexbuffer allocates the memory for you with the call to Lock(). If you try to set them before this, you'll get access violations.

Also, the aforementioned comment on the diffuse element is also incorrect. if doesn't choose which color is rendered, it tints the color. So if you specified blue, it would render the bitmap with a blue tint. (Edit: Ok, he said for his setup, but I don't know how he's doing it.)

@MrDoomMaster: I believe that your algorithm is off, which is causing your texture to be stretched (thus the blurryness.) Try adding +1 to the part that you're getting the width/height:
((source->right - source->left) + 1) / m_TexInfo.Width;

I'm not positive about this though. Also, you don't seem to be calling SetStreamSource(), so AFAIK, this shouldn't be rendering anything.

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Quote:
Original post by Programmer16Also, you don't seem to be calling SetStreamSource(), so AFAIK, this shouldn't be rendering anything.


If you'll take a look at my last post, you will see that I actually do call SetStreamSource() in my new version of the function. Take a look.

Also, I added the +1 to the algorithm and it still looks blurry. The bitmaps seem "whole" now, but why would it still be blurry?

Thanks!

Share this post


Link to post
Share on other sites
Telastyn    3777
Quote:

Also, the aforementioned comment on the diffuse element is also incorrect. if doesn't choose which color is rendered, it tints the color. So if you specified blue, it would render the bitmap with a blue tint.


What I said does not counteract this. How do you think the tint is mathematically applied?

And I'm not sure about the blurry problems. I've never had such problems.

Share this post


Link to post
Share on other sites
Programmer16    2321
My apologies Telastyn, I misread what you said.

@MrDoomMaster: Are you loading the texture with filtering on? If you're using just D3DXCreateTextureFromFile() then the filter is set to D3DX_DEFAULT (D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER). This would cause the texture to become blurry. AFAIK anti-aliasing would also cause this. I somehow missed the call to SetStreamSource() (I think I need to get my eyes checked.)

Share this post


Link to post
Share on other sites
gtdelarosa    128
The RHW coord make the vertices into 4D vertices. This allows them to be multiplied by the projection matrix which converts the vertices into homogeneous coordinates. If RHW is set to 1.0 before the multiply, it will equal the z-coordinate after the multiply. Then all of the vertex coords are divided by the RHW coord. This is know as the homogeneous divide and it transforms the vertex into 2D viewport space where z = 1.

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Wow my algorithm finally works, I'm getting perfect blitter.

Now, just a few more questions! I know you're getting tired of me, but I hope you'll hang in there! I'm learning so much!

1) If you'll look in my above Blitter function, are there any function calls I can remove and put somewhere else? I have a function I call 1 time to load the bitmap into the texture pointer, if I can place some of these function calls there it would help reduce the processing time required when calling my blitter function.

2) Is 'textured quads' the most efficient method of blittering bitmaps from surface to surface in 2D games?

3) How do I use a color key? I realize you can set the color key when you call CreateTextureFromFile(), but I don't like this because I want to change the color key at any time via another function, so I will need to be able to set the transparent color AFTER the texture has been created and loaded.

Any idea how to do this?



Thank you guys so much, I am going to rate everyone here that helped me. I really appreciate everything guys, you've helped me get this under control

Share this post


Link to post
Share on other sites
Programmer16    2321
1) If you're worried about speed, then calling SetTexture() for every bitmap is going to be a problem. AFAIK this call is very slow. You could try a couple of checks or something to fix this. Maybe storing a static filename and checking against that:

static std::string m_LastTexture;
// And then in your blitter function
int CBitmap::Blitter(int dest_x, int dest_y, RECT* source)

{

//--Variables---------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BitmapVertex* Quad = 0;

//--------------------------------------------------------------



if(!m_Display->IsInitialized())

return 0;



if(!m_Loaded)

return 0;



if(m_VertexBuffer->Lock(0, 0, (void**)&Quad, 0) != D3D_OK)

return 0;



Quad[0].x = (float)dest_x;

Quad[0].y = (float)dest_y;

Quad[0].z = 0.0;

Quad[0].rhw = 1.0;

Quad[0].Color = 0xffffffff;

Quad[0].tu = (float)source->left / m_TexInfo.Width;

Quad[0].tv = (float)source->top / m_TexInfo.Height;



Quad[1].x = (float)dest_x + (source->right - source->left);

Quad[1].y = (float)dest_y;

Quad[1].z = 0.0;

Quad[1].rhw = 1.0;

Quad[1].Color = 0xffffffff;

Quad[1].tu = (float)(source->left + (source->right - source->left)) / m_TexInfo.Width;

Quad[1].tv = (float)source->top / m_TexInfo.Height;



Quad[2].x = (float)dest_x + (source->right - source->left);

Quad[2].y = (float)dest_y + (source->bottom - source->top);

Quad[2].z = 0.0;

Quad[2].rhw = 1.0;

Quad[2].Color = 0xffffffff;

Quad[2].tu = (float)(source->left + (source->right - source->left)) / m_TexInfo.Width;

Quad[2].tv = (float)(source->top + (source->bottom - source->top)) / m_TexInfo.Height;



Quad[3].x = (float)dest_x;

Quad[3].y = (float)dest_y + (source->bottom - source->top);

Quad[3].z = 0.0;

Quad[3].rhw = 1.0;

Quad[3].Color = 0xffffffff;

Quad[3].tu = (float)source->left / m_TexInfo.Width;

Quad[3].tv = (float)(source->top + (source->bottom - source->top)) / m_TexInfo.Height;



m_VertexBuffer->Unlock();



if(m_Display->GetDevice()->SetStreamSource(0, m_VertexBuffer, 0, sizeof(BitmapVertex)) != D3D_OK)

return 0;



if(m_Display->GetDevice()->SetFVF(m_VertexFormat) != D3D_OK)

return 0;

if(m_FileName != m_LastTexture)
{
if(m_Display->GetDevice()->SetTexture(0, m_Texture) != D3D_OK)
return 0;
m_LastTexture = m_FileName;
}



if(m_Display->GetDevice()->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) != D3D_OK)

return 0;



return 1;

}



2) Textured quads are efficient enough as far as I am concerned. I use the same method and it works just fine. Again, if you're looking for speed there are 2 possibilities that I can think of. A)Batching calls or B)Using the ID3DXSprite interface. I believe that this automatically does batching for you (but I'm not certain.)

3) I'm not positive about this one, but I believe that it is possible. I'll do some research (since I am also interested in this) and tell you what I come up with.

Also, some of the users on here might recommend using the render-to-texture technique. If this might interest you, you can find a tutorial on TwoKings here (#16.)

PS: Just so you know, you can use the source tags ([ source ] [ / source ] for long code and [ code ] [ / code ] for short code (without the spaces of course.)) so that your code shows up in the nice text-box with keyword highlighting.

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