Jump to content
  • Advertisement
Sign in to follow this  

drawing pixels ok this way?

This topic is 4719 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I didn't like using the Direct3D sprite device because I didn't really know what is going on. I like to know what I'm doing. So I thought, I'll write my own class. So I went through the articles and found an interesting one on writing directly into video memory with direct draw. This would give me a few extra advantages too. What I do is the following: 1. Create Direct3D Device 2. Get the Device's backbuffer (GetBackBuffer()) 3. Start loop 3.1 LockRect() 3.2 write into video memory 3.3 UnlockRect() 3.4 Present() Now my questions: 1. Is this a good way to do this? if not, how IS a good way? 2. Does pitch / 4 work on all video cards? because I saw somewhere saying that the pitch can be different on some video cards. Something about a few more bytes per line. Maybe this new pitch thing is to solve that problem. ow yeah, I'm using DirectX 9 SDK.

Share this post


Link to post
Share on other sites
Advertisement
LockRect and UnlockRect tends to be bad (so ive heard) you can do that though I guess. Im not sure of a good way to do it but this will at least give you an idea. Perhaps surface offscreen rendering?

Share this post


Link to post
Share on other sites
You can draw pixels directly to the backbuffer surface (or use surfaces directly), as you suggest, but you won't be doing much more than directdraw, (not as good either), there probably are uses for it (i'm trying to use surfaces myself at the moment to "concatenate" letters to save as words for my own text/font thing).

Try using quads instead, a quad is just two triangles togather, also use the rhw setting, this means the lighting etc, for the quad is taken care of.


struct Vertex
{
float x, y, z;
float rhw;
D3DCOLOR color; // The color
float tu, tv; //use to adjust the textures position on the quad/triangle
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)

//Globals
//You need most of the ordinary stuff including a texture;
LPDIRECT3DTEXTURE9 m_pTexture;
char *filename;


Vertex *vertices;


TuStart = 0.0f;//this gets whole texture to show properly
TuEnd = 1.0f;
TvStart = 0.0f;
TvEnd = 1.0f;

float x, y, cx, cy;//how ever big you want the quad

void InitVertices(TuStart,TuEnd,TvStart,TvEnd,x,y,cx,cy)
{
Vertices = new Vertex[4];
//top left
Vertices[2].x = x; //x start size/position onscreen
Vertices[2].y = y; //y start size/position onscreen
Vertices[2].z = 0.5f;
Vertices[2].rhw = 1.0f;
Vertices[2].color = D3DCOLOR_XRGB(250,250,250);
Vertices[2].tu = TuStart;
Vertices[2].tv = TvStart;

//bottom left
Vertices[0].x = x;
Vertices[0].y = y+cy; //y start size + endsize -how big its going to be.
Vertices[0].z = 0.5f;
Vertices[0].rhw = 1.0f;
Vertices[0].color = D3DCOLOR_XRGB(250,250,250);
Vertices[0].tu = TuStart;
Vertices[0].tv = TvEnd;

//bottom right
Vertices[1].x = x+cx;
Vertices[1].y = y+cy;
Vertices[1].z = 0.5f;
Vertices[1].rhw = 1.0f;
Vertices[1].color = D3DCOLOR_XRGB(250,250,250);
Vertices[1].tu = TuEnd;
Vertices[1].tv = TvEnd;

//top right
Vertices[3].x = x+cx;
Vertices[3].y = y;
Vertices[3].z = 0.5f;
Vertices[3].rhw = 1.0f;
Vertices[3].color = D3DCOLOR_XRGB(250,250,250);
Vertices[3].tu = TuEnd;
Vertices[3].tv = TvStart;

}


void LoadTexture(LPDIRECT3DDEVICE9 mp_d3dDevice, char *texturename)
{
filename = texturename;
p_d3dDevice = mp_d3dDevice;
D3DXCreateTextureFromFile( p_d3dDevice, filename, &m_pTexture );
}


void FillInTehVB()
{
p_d3dDevice->CreateVertexBuffer( 4*sizeof(Vertex),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &p_VertexBuffer, NULL );

VOID* pVertices;
p_VertexBuffer->Lock( 0, 4*sizeof(Vertex), (void**)&pVertices, 0 );

memcpy( pVertices, Vertices, 4*sizeof(Vertex));
p_VertexBuffer->Unlock();

}

void SetSomeTextureStages()
{
p_d3dDevice->SetTextureStageState(0, D3DTSS_CONSTANT, D3DTEXF_LINEAR );
p_d3dDevice->SetTextureStageState(0, D3DTSS_CONSTANT, D3DTEXF_LINEAR );

)

void DrawVB
{

p_d3dDevice->SetTexture( 0, m_pTexture );

// Render the vertex buffer contents
p_d3dDevice->SetStreamSource( 0, p_VertexBuffer, 0, sizeof(Vertex) );
p_d3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
p_d3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2);

}

Most of this won't copy & paste, you have to set it up your self properly, but this is the idea, most of the functions would go before the game loop, (after InitD3D), then the DrawVB can be called during the Render loop.
(p_d3ddevice is the same as g_pd3dDevice, mine has just come from my own texture class, thats why its different.)

Share this post


Link to post
Share on other sites
Quote:
Original post by DevLiquidKnight
LockRect and UnlockRect tends to be bad (so ive heard) you can do that though I guess. Im not sure of a good way to do it but this will at least give you an idea. Perhaps surface offscreen rendering?


Right - locking textures at runtime is very, very bad. It is incredibly slow, because all of the data must be transferred over the AGP bus (and back again, if you are updating). If at all, you should only be doing it at loadtime.

If you want a slight idea of how ID3DXSprite works, check out Stevie's post. It *does not* lock the backbuffer and plot the pixels right onto it. Instead, it creates 2 triangles, forming a quad, and renders it. Actually, it's a bit more complicated than that, since ID3DXSprite batches all of the drawing calls to improve performance.

It is undoubetdly a great thing to understand how the underlying interfaces work. Not only does it increase your knowledge of graphics programming, but it also allows you to utilize the interfaces in questions at a higher level. However, this does not mean that you should be recreating the wheel. ID3DXSprite is a very efficient sprite renderer and does a lot more than simply push textured quads to the GPU. If you have the means, you should be using it.

Share this post


Link to post
Share on other sites
Quote:
It is undoubetdly a great thing to understand how the underlying interfaces work. Not only does it increase your knowledge of graphics programming, but it also allows you to utilize the interfaces in questions at a higher level.

I'll check it out.

Quote:
Most of this won't copy & paste

I never copy, paste things I don't understand. ;)
Waaay to much trouble getting something to work that way, and definitly anoying not knowing what you're actually doing.

// Edit: checked it
I allready did this once. I thought it was nice for textures, but I also want to draw things like ovals and lines. For lines and circles I would need to draw 1 pixel, that's why I started the whole draw 1 pixel thing. Is creating a vertex that is 1 pixel high and 1 pixel wide still faster than locking and unlocking every time? Or is there a better way to draw circles and lines?

thx for hanging on with me here :)

Share this post


Link to post
Share on other sites
It might be useful if you can say exactly what it is you need to do.
Sounds to me like you'd be better served with GDI than DirectX. Sure, it's slow, but not as slow as trying to plot each individual pixel.

Share this post


Link to post
Share on other sites
Hi,
As long as you only lock and unlock the buffer once every frame, there shouldn't be any problems - where you "write into video memory" make sure you do everything you need, there should be no problems.

As for the vertical pitch of the screen, it all gets very complicated with bytes per pixel and, as you say, extra bytes on each row but if you're using Direct3D, it should take care of everything for you. If it doesn't, I think the information about the 'memory pitch' is in the Surface Description (SurfaceDesc), although I can't remember specifically how to get at it in Direct3D.

Have Fun!

-indirectX-

Share this post


Link to post
Share on other sites
Instead of just writing your own class with a new method I would have just done research to figure out what directX is doing. Maybe you wouldn't have a problem with it once you knew what the internals were up to. You never know what you might have learned along the way either. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by mikeschuld
Instead of just writing your own class with a new method I would have just done research to figure out what directX is doing. Maybe you wouldn't have a problem with it once you knew what the internals were up to. You never know what you might have learned along the way either. :)

Yeah I know, but DirectX doesn't have a way of drawing ovals or lines.

// edit: ok, it has lines, now I feel ashamed of myself :D, but still, how do I do ovals? Ovals aren't really necesary, but still ...

Share this post


Link to post
Share on other sites
Maybe you could try getting the surface's graphic context (in managed languages) or hwnd (in native ones) and use GDI functions to draw ellipses. Horribly slow but is a way :D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!