C++ & DirectX Plugin API problem

Started by Calin Leafshade, Sat 07/08/2010 00:57:45

Previous topic - Next topic

Calin Leafshade

I'm not sure if anyone can help me here and this may be one of those 'CJ issues' that only CJ can fix but it can't hurt asking in case we have any advanced DirectX coders here.

The plugin API exposes the D3D device via a pointer passed by an engine hook. ('data' in the below function)

So this is the code I attempted to use


Code: ags

int AGS_EngineOnEvent (int event, int data) {
  if (event == AGSE_PREGUIDRAW) {
    
	IDirect3DDevice9 *dev = (IDirect3DDevice9 *)data;
	
	
	HRESULT hRes;
				
	IDirect3DPixelShader9* lpPixelShader = NULL;
	LPD3DXBUFFER pCode = NULL;
	LPD3DXBUFFER pErrorMsgs = NULL;

	hRes = D3DXAssembleShaderFromFile(L"simple_texture_map.ps",  
						NULL,		    
						NULL, 
						0,
						&pCode, 
						&pErrorMsgs);
	
	hRes = dev->CreatePixelShader((DWORD*)pCode->GetBufferPointer(), 
                                         &lpPixelShader); //the problem line
	
	hRes = dev->SetPixelShader(lpPixelShader);
	

  }
  return 0;
}



However the CreatePixelShader routine throws an access violation exception and i'm not entirely sure why, the code looks fine to me.

Anyone see my error?

Wyz

#1
Well, could be a lot, but just to be certain check that your game is set to use DX9 and not DirectDraw.

And you've beaten me to this, it was next on my list of plugins I wanted to make (still working on the joystick plugin, when I have some time ;))
Life is like an adventure without the pixel hunts.

Kweepa

#2
The functions return a HRESULT for a reason... :=
Perhaps checking the return values will give you some clues.
It could be the pixel shader didn't compile correctly and pCode is NULL.
Or, it could be that the function didn't find the .ps file at all... how does D3D know where to look for the file?
Still waiting for Purity of the Surf II

Calin Leafshade

#3
Quote from: Wyz on Sat 07/08/2010 01:27:02
Well, could be a lot, but just to be certain check that your game is set to use DX9 and not DirectDraw.

I am such an idiot...

EDIT:
I feel like I am going in circles.. I want to do something very very simple.

1. Copy what has already been drawn by AGS to a texture
2. Set a pixel shader.
3. Draw that texture back to the screen with the pixel shader applied..

Surely this should be like 2 dozen lines of code?

Shane 'ProgZmax' Stevens

It shouldn't require massive work, no, but that's provided the D3D hook for shaders is accessible.  Did you check the HRESULT value as Steve suggested?  That should give you a pretty big clue as to whether or not the function is being blocked.  I haven't done any directx/d3d coding in awhile, sadly (I used to work on it daily) so I'm a bit rusty and cannot currently provide more detailed feedback than this.  You may or may not have already read this or something similar, but it covers the process of applying pixel or vertex shaders in some detail and might be of use (this is all provided these calls are accessible through the ags plugin api heh).



Calin Leafshade

Ok well let me tell you where I've got to thus far.

I can init the device and draw to it.
however the vertices that I draw to seem to draw in relation to the last thing draw by the engine (the player character in this case)

For example when I set the vertices to floats (0.0f, 0.0f -> 1.0f, 1.0f) it draws the textures to a shape the same size as the character (although it draws it above the character which is weird)

This is I think because AGS doesnt give me the vertex format that it's using so i'm having to guess.. (although I have managed to grab the D3DFVF flags and set mine to match)

I am pretty confident I can grab the backbuffer and make it into a texture and therefore be able to run the shader on it but it's immaterial until i can solve the vertex issues.

So i'm pretty sure this is possible, but the API could certainly make it easier.

Shane 'ProgZmax' Stevens

Quote(although it draws it above the character which is weird)

This could just be a guess, but the problem you describe could come from AGS rendering its characters to the screen with the origin at the bottom middle of the sprite rather than the top left of the sprite as is standard?

Calin Leafshade

That is a possibility although I would imagine that in terms of the vertices use to *render* the sprites they are all the same and compliant with the D3D default (i.e top left)

even if that were the problem though it wouldnt cause *all* the coords to be relative to character

JJS

Just a guess: Do you reset the worlview and modelview matrix before drawing? If not, every coordinate is interpreted relative to the last used matrix, which in this case seems to be the one the character is drawn with.
Ask me about AGS on PSP, Android and iOS! Source, Daily builds

Calin Leafshade

No I havent... How would I do that?

JJS

I actually only have experience with OpenGL, but you probably want to set your world matrix to the unity matrix.

I cannot find anything quickly, but this explains some basics:
http://www.toymaker.info/Games/html/matrices.html
Ask me about AGS on PSP, Android and iOS! Source, Daily builds

Calin Leafshade

Thanks for the help.

After much fiddling I now have shaders working and drawing to the screen  :=

GarageGothic

Awesome! I look forward to the first demo. Did you ever figure out how to use shaders in a way that doesn't affect the GUI or are they always applied on top of everything else?

Calin Leafshade

Yeah the api has a pre gui draw event. Just draw in that event and the gui will be drawn on top.

Kweepa

So, what were your solutions to the problems above? Help out the future forum searchers of America (and other countries, why not?).
Still waiting for Purity of the Surf II

Ryan Timothy B

QuoteYeah the api has a pre gui draw event.
Oh really?

That confuses me why CJ wouldn't have an extra DynamicSprite.CreateFromScreenShot function that doesn't take pictures of the GUI and mouse.  It would be very useful to me and others.

Kweepa

It's obviously because he's lazy as shuch water.
Still waiting for Purity of the Surf II

Calin Leafshade

#17
You can infer the solutions from the thread

Quote from: Calin Leafshade on Sat 07/08/2010 11:27:20
Quote from: Wyz on Sat 07/08/2010 01:27:02
Well, could be a lot, but just to be certain check that your game is set to use DX9 and not DirectDraw.

I am such an idiot...

Yes i was..

and

Quote
Insert Quote
Just a guess: Do you reset the worlview and modelview matrix before drawing? If not, every coordinate is interpreted relative to the last used matrix, which in this case seems to be the one the character is drawn with.

No i hadnt reset it..

EDIT:

Ok! You've helped me before oh mystical forum entity that talks to me, let's see if you can do it again.

The plugin API doesn't expose the texture that the engine is drawing to (although I imagine it draws straight to the backbuffer) So I'm finding it difficult to redraw whatever is on the screen.

Basically I need to dump the rendertarget to a texture.

LoadSurfacefromSurface is way too slow for this since it needs to be done every frame so I thought I'd need to do it with LockRect but I'm not exactly sure how.

Any ideas?

JJS

This sounds like a pretty big problem because you cannot lock surfaces that are created with D3DPOOL_DEFAULT such as the back buffer, only those in main memory (D3DPOOL_SYSTEMMEM).

Just speculating, but do you really need to lock it? I mean you don't ever need CPU access to the texture because you only want to apply a shader to it. If the destination surface of LoadSurfacefromSurface is also in the graphics card memory, the operation should actually be quite fast. But if you already create the surface with D3DPOOL_DEFAULT and it is still slow, then I don't know.

I guess this whole scenario is quite rare because you either use render to texture for this or want the image in main memory (for a screenshot).
Ask me about AGS on PSP, Android and iOS! Source, Daily builds

Calin Leafshade

Hmm it seems this isnt possible to do (not at full speed anyway).

The only way this could be realistically done is if CJ started rendering to a texture instead in the engine.

Then if he provides a pointer in the API to that texture then the texture can be fiddled with.

and then the engine renders the texture to the screen right at the very end.

I dont think it would be a big deal to change. CJ would just need to clear the texture at the start of the render loop and then set it as the render target and then, at the end of the cycle set the render target back again and render the texture.

It shouldnt be more than like 5 extra lines of code.

SMF spam blocked by CleanTalk