Sign in to follow this  
TLAK1001

[SOLVED]Invalid call drawing vertex buffer

Recommended Posts

Hello, I am working on a simple engine for 2-D games. I have the infrastructure in place and am ready to try rendering using the code below:
void Engine::testrender()
{
	LPDIRECT3DTEXTURE9 texture;
	LPDIRECT3DVERTEXBUFFER9 g_pVB;

	if( FAILED( D3DXCreateTextureFromFile( m_d3dDevice, "C:/Documents and Settings/Tyler/My Documents/My Code/C++/Engine/Test/Assets/TPiece.bmp", &texture ) ) )
		MessageBox(NULL, "Failed to load texture", "Error", MB_OK);
	CUSTOMVERTEX g_Vertices[] =
	{
		{ 0.0f, 1.0f, 0.0f,		0.0f, 0.0f },
		{ 1.0f, 1.0f, 0.0f,		1.0f, 0.0f },
		{ 0.0f, 0.0f, 0.0f,		0.0f, 1.0f },
		{ 1.0f, 0.0f, 0.0f,		1.0f, 1.0f }
	};

	if( FAILED( m_d3dDevice->CreateVertexBuffer( sizeof(g_Vertices) * sizeof(CUSTOMVERTEX),
												 0, 
												 D3DFVF_CUSTOMVERTEX,
												 D3DPOOL_DEFAULT, 
												 &g_pVB, 
												 NULL ) ) )
		MessageBox(NULL, "Failed to create vb", "error", MB_OK);

    // Fill the vertex buffer.
    VOID* pVertices;
	
	if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) )
		MessageBox(NULL, "Failed to lock vb", "Error", MB_OK);

	// copy the vertices into the buffer
    memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );

	// unlock the vertex buffer
    g_pVB->Unlock();

	D3DXMATRIX matView;					// the view matrix
	D3DXMATRIX matProj;					// the projection matrix
	D3DXVECTOR3 cameraPosition;			// the position of the camera
	D3DXVECTOR3 cameraLook;
	
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 640/480, 0.1f, 50.0f);
    m_d3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
	cameraPosition = D3DXVECTOR3(0.0f, 0.0f, -3.0f);
	cameraLook = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

	m_d3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
    m_d3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

	/*D3DXMATRIX matRot;
	D3DXMatrixRotationY(&matRot, timeGetTime()/1000.0f);
	
	D3DXMATRIX matWorld;
	D3DXMatrixMultiply(&matWorld, &matRot, &matView);	
    pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );*/

	if(FAILED(m_d3dDevice->SetTexture( 0, texture )))
		MessageBox(NULL,"Couldn't set texture", "Error", MB_OK);
	if(FAILED(m_d3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) )))
		MessageBox(NULL,"Couldn't set stream source", "Error", MB_OK);
	if(FAILED(m_d3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX )))
		MessageBox(NULL,"Couldn't set FVF", "Error", MB_OK);
	if(D3DERR_INVALIDCALL == (m_d3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,  0, 2 )))
		MessageBox(NULL,"Error drawing","Error",MB_OK);
}



Here are the definitions for D3DFVF_CUSTOMVERTEX and CUSTOMVERTEX from a header file:
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)	//Custom vertex format
struct CUSTOMVERTEX										//Custom vertex structure
{
	FLOAT x, y, z;
	float tu, tv;
};



The application compiles perfectly, but when I run, I get the "Error Drawing" Message Box. I have tried just about everything I can think of. Can someone please help me figure out what's wrong here? Thanks, Tlak EDIT(S): changed title to reflect changes in discussion [Edited by - TLAK1001 on May 27, 2007 1:24:42 PM]

Share this post


Link to post
Share on other sites
I didn't look through it that thoroughly, but do you really want to be doing:

if( FAILED( m_d3dDevice->CreateVertexBuffer( sizeof(g_Vertices) * sizeof(CUSTOMVERTEX),
0,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,
&g_pVB,
NULL ) ) )



Shouldn't the size of the buffer be just sizeof(g_Vertices)?

Share this post


Link to post
Share on other sites
I don't think so; the directX documentation says

Parameters

Length
[in] Size of the vertex buffer, in bytes. For FVF vertex buffers, Length must be large enough to contain at least one vertex, but it need not be a multiple of the vertex size. Length is not validated for non-FVF buffers.

If it's in bytes, then the call should want the size of each vertex (sizeof(CUSTOMVERTEX)) for each vertex in the buffer ( * sizeof(g_Vertices))

I tried it, and still had the same problem. I also tried 4 * sizeof(CUSTOMVERTEX) (if it's a 2-D engine, it will never render anything other than textured quads),
but that didn't work either

Share this post


Link to post
Share on other sites
AH - HA!
I forgot to call BeginScene() and EndScene()! However, I am still greated with a blank black screen... Now what's wrong?!

Share this post


Link to post
Share on other sites
sizeof(g_Vertices) will return (number of elements) * sizeof(element) since it's a compile-time defined array.
Besides when you copy the memory you do:

if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) )
MessageBox(NULL, "Failed to lock vb", "Error", MB_OK);

// copy the vertices into the buffer
memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );


so unconsciously you know this ^_^

Only things I can think of now is:
* Try defining CUSTOMVERTEX* pVertices, instead of VOID* pVertices

* Try Locking with g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ), which locks the entire buffer

* Try setting the FVF first and then the stream source

* If all fails try setting values av pVertices explicitly instead of copying from g_pVertices, or debug to check the content of pVertices so that it is correct

Share this post


Link to post
Share on other sites
Hi there, I think that the sizeof(g_Vertices) will return the size of the whole array and that is all you need.
read up on sizeof function on arrays.

Share this post


Link to post
Share on other sites
Hey guys,

Thanks for your help, I was trying Omid's suggestions when I realized that something is actually being drawn, but incorrecly. In the center of the black screen is a very, very, very dark green (almost black, which is why I didn't see it with the sun shining on my monitor) rectangle in the middle of the screen. However, this is not my texture! I can't get pictures on the post or I would show you... It is almost the same color as the top left corner of the texture. However, when I change the color of the top left pixel in my texture the application renders a bizarre single color that seems to be some sort of mix between the colors of the changed pixel and the other colors. Just in case anything changed, I reposted my code:


void Engine::testrender()
{
LPDIRECT3DTEXTURE9 texture;
LPDIRECT3DVERTEXBUFFER9 g_pVB;

if( FAILED( D3DXCreateTextureFromFile( m_d3dDevice, "test.bmp", &texture ) ) )
MessageBox(NULL, "Failed to load texture", "Error", MB_OK);
m_d3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
m_d3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
CUSTOMVERTEX g_Vertices[] =
{
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }
/*{50.0f, 50.0f, 0.5f, 1.0f, 0.0f, 0.0f},
{250.0f, 50.0f, 0.5f, 1.0f, 16.0f, 0.0f},
{50.0f, 400.0f, 0.5f, 1.0f, 0.0f, 16.0f},
{250.0f, 400.0f, 0.5f, 1.0f, 16.0f, 16.0f}*/


};

if( FAILED( m_d3dDevice->CreateVertexBuffer( sizeof(g_Vertices) * sizeof(CUSTOMVERTEX),
0,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,
&g_pVB,
NULL ) ) )
MessageBox(NULL, "Failed to create vb", "error", MB_OK);

// Fill the vertex buffer.
CUSTOMVERTEX* pVertices;

if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
MessageBox(NULL, "Failed to lock vb", "Error", MB_OK);

// copy the vertices into the buffer
memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );

// unlock the vertex buffer
g_pVB->Unlock();

D3DXMATRIX matView; // the view matrix
D3DXMATRIX matProj; // the projection matrix
D3DXVECTOR3 cameraPosition; // the position of the camera
D3DXVECTOR3 cameraLook;

/*D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 640/480, 0.1f, 50.0f);
m_d3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);*/

cameraPosition = D3DXVECTOR3(0.0f, 0.0f, -10.0f);
cameraLook = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
D3DXMatrixLookAtLH(&matView,
&cameraPosition, //Camera Position
&cameraLook, //Look At Position
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //Up Direction

m_d3dDevice->SetTransform(D3DTS_VIEW, &matView);

m_d3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_d3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
m_d3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

/*D3DXMATRIX matRot;
D3DXMatrixRotationY(&matRot, timeGetTime()/1000.0f);

D3DXMATRIX matWorld;
D3DXMatrixMultiply(&matWorld, &matRot, &matView);
pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );*/


if(FAILED(m_d3dDevice->SetTexture( 0, texture )))
MessageBox(NULL,"Couldn't set texture", "Error", MB_OK);
if(FAILED(m_d3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX )))
MessageBox(NULL,"Couldn't set FVF", "Error", MB_OK);
if(FAILED(m_d3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) )))
MessageBox(NULL,"Couldn't set stream source", "Error", MB_OK);
if(D3DERR_INVALIDCALL == (m_d3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 )))
MessageBox(NULL,"Error drawing","Error",MB_OK);
}



Thanks for your help,
tlak

Share this post


Link to post
Share on other sites
You didn't enable D3DRS_WRAP0 did you? It would cause your image to be a mix of all 4 corners of your texture. It's a bizarre wrapping mode that's not at all what anyone would expect. It causes the card to take the shortest path to the new texture coordinate.

Both 0.0 and 1.0 are actually the same point on the top left corner of the top left texel. The shortest path is to not move, rather than traverse the entire texture from 0 to 1. That plus, bilinear filtering will cause a mix between the neighbouring texels (all 4 corners of your texture) because you're not at the center of the top-left texel, you're at the corner of it.

Share this post


Link to post
Share on other sites
no, wrap0 has not been enabled. I specifically turned it off, and continue to recieve the same results. I am considering scrapping the engine and restarting from scratch. You guys think that this would be easier / solve the problem?

Share this post


Link to post
Share on other sites
I won't suggest that you restart from scratch. Not that it's a bad idea, but you should do it after you know a bit more about what you're doing, so you'll be able to make better decisions when designing it.

One problem I see is that you're not setting any texture stage states (or pixel shader). The default pixel pipeline state is to multiply diffuse by texture, but you don't have lighting or a diffuse colour in your vertex.

BTW, to better see if the problem is with the rectangle not being transformed correctly, or its shading, you can render it with a single colour, by setting the texture stage states to select the texture factor, and setting that to a distinctive colour.

Share this post


Link to post
Share on other sites
YEAH!

I GOT IT! I did restart from scratch, but re-built everything just about the same. I did move all of the rendering functions into one single wrapper class. I had the same exact results, but I noticed that I had changed
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1 )
to
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX0 )

I changed it back, and was greated with a nice, square, properly - colored texture

Thank you everyone for your assistance

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