Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Calin Leafshade on Sat 07/08/2010 00:57:45

Title: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sat 07/08/2010 00:57:45
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



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?
Title: Re: C++ & DirectX Plugin API problem
Post by: 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.

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 ;))
Title: Re: C++ & DirectX Plugin API problem
Post by: Kweepa on Sat 07/08/2010 01:44:16
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?
Title: Re: C++ & DirectX Plugin API problem
Post by: 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...

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?
Title: Re: C++ & DirectX Plugin API problem
Post by: Shane 'ProgZmax' Stevens on Sat 07/08/2010 16:43:21
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 (http://www.two-kings.de/tutorials/dxgraphics/dxgraphics18.html).  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).


Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sat 07/08/2010 16:51:40
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.
Title: Re: C++ & DirectX Plugin API problem
Post by: Shane 'ProgZmax' Stevens on Sat 07/08/2010 17:16:59
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?
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sat 07/08/2010 17:41:00
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
Title: Re: C++ & DirectX Plugin API problem
Post by: JJS on Sat 07/08/2010 19:58:55
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.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sat 07/08/2010 20:01:02
No I havent... How would I do that?
Title: Re: C++ & DirectX Plugin API problem
Post by: JJS on Sat 07/08/2010 20:22:53
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 (http://www.toymaker.info/Games/html/matrices.html)
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 08/08/2010 00:00:20
Thanks for the help.

After much fiddling I now have shaders working and drawing to the screen  :=
Title: Re: C++ & DirectX Plugin API problem
Post by: GarageGothic on Sun 08/08/2010 00:54:10
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?
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 08/08/2010 00:58:08
Yeah the api has a pre gui draw event. Just draw in that event and the gui will be drawn on top.
Title: Re: C++ & DirectX Plugin API problem
Post by: Kweepa on Sun 08/08/2010 01:21:19
So, what were your solutions to the problems above? Help out the future forum searchers of America (and other countries, why not?).
Title: Re: C++ & DirectX Plugin API problem
Post by: Ryan Timothy B on Sun 08/08/2010 01:53:00
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.
Title: Re: C++ & DirectX Plugin API problem
Post by: Kweepa on Sun 08/08/2010 03:44:48
It's obviously because he's lazy as shuch water.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 08/08/2010 06:53:46
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?
Title: Re: C++ & DirectX Plugin API problem
Post by: JJS on Sun 08/08/2010 10:32:10
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).
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 08/08/2010 14:22:35
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.
Title: Re: C++ & DirectX Plugin API problem
Post by: Pumaman on Tue 10/08/2010 17:37:56
Quote from: Calin Leafshade on Sun 08/08/2010 06:53:46
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.

Correct, it does not. But it sounds like what you really want is to hook into the AGS rendering process where it selects which pixel shader to use for each sprite, and replace it with your own.

If that's the case, is that something you would use?
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Tue 10/08/2010 17:41:56
That is not really useful for the effects I am trying to achieve.

Certain pixel shaders (specifically things like blur and bloom and  other post-process fx) need to be applied to the whole screen after rendering. Applying these shaders to each individual sprite as it is drawn will not work since they are an effect on the world rather than the elements within the world, if that makes sense.
Title: Re: C++ & DirectX Plugin API problem
Post by: Pumaman on Tue 10/08/2010 17:51:53
Well, the AGS rendering loop basically looks like:

d3ddevice9->BeginScene();

For each sprite:
  direct3ddevice->SetPixelShader(...);
  direct3ddevice->SetTransform(...);
  direct3ddevice->SetTexture(...);
  direct3ddevice->DrawPrimitive(...);

direct3ddevice->EndScene();
direct3ddevice->Present(...);

The AGSE_PREGUIDRAW event is drawn in the middle of the rendering loop after all the non-GUI stuff has been drawn. So I'm not sure if it's possible at that point to get what has already been drawn and re-draw it, I can't remember enough about how D3D's back buffer works. In AGS the D3D backbuffer is not lockable so it can't be directly accessed.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Tue 10/08/2010 18:05:00
well just set the render target to something other than the back buffer.

create a texture
get the surface of that texture
set the current render target to that surface
draw the sprites to the surface

then allow the api a handle to that texture.
I can manipulate that texture in whatever way i like

draw the guis to the surface
set the render target to the back buffer again
draw the fully rendered texture to the back buffer.
done

This is generally how any engine with post processing shaders does it since you need the final result as a texture in order to perform them.

Does this sound possible?
Title: Re: C++ & DirectX Plugin API problem
Post by: JJS on Wed 11/08/2010 08:33:06
It would nicely tie in with this:
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=40132.msg533721#msg533721 (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=40132.msg533721#msg533721)
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Wed 11/08/2010 16:56:42
yup if the scaling was done to the entire texture afterwards it would make all the scaling look much prettier.

Edit: obviously also scaling the characters before they are drawn. Not *all* the scaling can be done at the end. but this means the scalings is done on a 1:1 pixel basis with the background
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 15/08/2010 22:49:18
sorry for the double post but:

Does the AGS API have a feature whereby I can create DX textures of existing sprites in the sprite cache?

That way it would fairly trivial to rebuild the scene from scratch just by getting the current sprites of all the objects and drawing them in the right place.

It's a ballache and a fairly messy work around since AGS does all that anyway but at least it would work.
Title: Re: C++ & DirectX Plugin API problem
Post by: Pumaman on Sun 15/08/2010 23:37:10
Quote from: Calin Leafshade on Tue 10/08/2010 18:05:00
well just set the render target to something other than the back buffer.
QuoteIt would nicely tie in with this:
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=40132.msg533721#msg533721

Thanks, yep that fits together nicely. So if that was done, your request would become quite easily possible.

QuoteDoes the AGS API have a feature whereby I can create DX textures of existing sprites in the sprite cache?

There are no D3D-specific AGS API functions at the moment.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sun 15/08/2010 23:55:19
Quote from: Pumaman on Sun 15/08/2010 23:37:10
Thanks, yep that fits together nicely. So if that was done, your request would become quite easily possible.

Yup the code is already done, just need the access to that texture and I can release full (post process) shader support for AGS :D:D:D


Quote from: Pumaman on Sun 15/08/2010 23:37:10

There are no D3D-specific AGS API functions at the moment.


I thought that might be the case, thanks for replying though.
Title: Re: C++ & DirectX Plugin API problem
Post by: subspark on Tue 17/08/2010 23:45:36
QuoteYup the code is already done, just need the access to that texture and I can release full (post process) shader support for AGS :D:D
HOLY Shinoouwza!!! :o This could mean the end of our game resolution woes AND the potential for working new arbitrary aspect ratios in!

Nice going Calin! We salute you. 8)

Sparky.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Wed 18/08/2010 00:04:06
Hmm my particular project would have no effect on the resolution of the engine. It just redraws the screen with a shader effect applied.

I also wouldnt recommend using an unsupported plugin in a commercial project.
Title: Re: C++ & DirectX Plugin API problem
Post by: subspark on Thu 19/08/2010 02:56:43
Fair enough of course however I was under the belief that CJ would implement this particular plugin into AGS as 'out of the box'. Don't ask me why :P.

Nice work though. I hope with this plugin in combination with better resolution support, we wont actually need to change the 'monitor' resolution when playing a game anymore. We just stretch the graphics across two tris.

When we're talking about the resolution of the texture (the game resolution) I was excited because this may mean that low res games under DirectX 9 can be scaled up directly/filtered/not filtered and still maintain the exact relative pixel grid.

So I still salute your efforts! ;D

Sparky.
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Sat 28/08/2010 17:22:33
I've just had a thought. (that happens to me sometimes)

CJ, Where abouts in the render cycle does the engine set the render target?

Could I create a texture and set the render target to that texture myself? Or would the engine just set it back to the backbuffer before it renders stuff?

If I could set the render target myself then I could get the texture very easily since i was the one who created it.

EDIT: Yup, that works.
Title: Re: C++ & DirectX Plugin API problem
Post by: subspark on Thu 02/09/2010 11:44:53
QuoteI've just had a thought. (that happens to me sometimes)
That happens to you ALOT Cal, don't be modest! ;)

Sparkz

EDIT: I had an idea too! Make a Calin Leafshade plugin so that everybody can have their own personal wonderbrain. ^^
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Thu 02/09/2010 16:41:56
Ha, wonderbrain is a little much.

Incidentally this plugin works now.

Now I just need to finish some shaders for a demo.
Title: Re: C++ & DirectX Plugin API problem
Post by: Dualnames on Thu 02/09/2010 21:36:01
Quote from: Calin Leafshade on Thu 02/09/2010 16:41:56
Ha, wonderbrain is a little much.

Incidentally this plugin works now.

Now I just need to finish some shaders for a demo.

Are we referring the BLOOM? Cause if we are, I officially propose to marry you! ;)
Title: Re: C++ & DirectX Plugin API problem
Post by: Calin Leafshade on Thu 02/09/2010 22:33:20
More generally a Post Processing shader allows you you skip through each pixel and apply some kind of mathematical formula to it.

Here are a couple of videos showing what they do.

http://www.youtube.com/watch?v=d4S__Nyi3t0
http://www.youtube.com/watch?v=6tp9Simhq2w
http://www.youtube.com/watch?v=e2gFynRah7g

Basically anything that affects the screen as a whole.