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?
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 ;))
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?
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?
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).
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.
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?
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
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 havent... How would I do that?
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)
Thanks for the help.
After much fiddling I now have shaders working and drawing to the screen :=
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?
Yeah the api has a pre gui draw event. Just draw in that event and the gui will be drawn on top.
So, what were your solutions to the problems above? Help out the future forum searchers of America (and other countries, why not?).
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.
It's obviously because he's lazy as shuch water.
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?
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).
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.
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?
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.
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.
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?
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)
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
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.
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.
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.
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.
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.
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.
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.
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. ^^
Ha, wonderbrain is a little much.
Incidentally this plugin works now.
Now I just need to finish some shaders for a demo.
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! ;)
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.