PLUGIN: Direct3D v1.0 (Sprite and Theora video rendering) [2012-02-08]

Started by AJA, Tue 07/02/2012 22:50:14

Previous topic - Next topic

AJA

Hello, fellow AGSers! It's been a while since I've done anything even remotely useful for the community, so here goes...

Since scotch hasn't been active for years now, I decided to remake the Theora plugin in order to fix some things that have been bothering me. (I hope he doesn't mind.) Well, as it turns out I went a bit further and also added the possibility to create Direct3D textures and render them. And since this plugin only supports the Direct3D driver (and 32bit colours), I've decided to megalomaniacally call this the Direct3D plugin.

Restrictions:

  • Games must be played with the Direct3D driver
  • Only 32 bit colours supported
Main features:

  • Play external Theora video files (with extremely simple obfuscation)
  • Create textures from AGS sprites
  • Create textures from external image files
Todo:

  • Transparency, tinting
  • Some kind of "free memory on room change" automation. (Because room_Leave is called before fade out, argh!)
  • ???
Manual/website

Download!

I made this plugin for my own needs so I really have no idea if anybody else finds it useful. If you do, feel free to post any comments, feature suggestions or bug reports.

It's not fully tested 'cause I'm a lazy sod. That's why it currently prints debug information into a debug.txt file. Send it to me if the plugin crashes your game or something weird happens. Also, no demo game available for now, sorry. There's a couple of examples in the manual, though.


--EDIT--

Source code now available!

Calin Leafshade


Knox

Cool! Gonna test that out now :)


Pardon my ignorance, but what are some of the things one can do with "textures" within AGS?
--All that is necessary for evil to triumph is for good men to do nothing.

AJA

Well, the main thing is being able to rotate and scale them freely and smoothly.

For example, if you want something like a rotating wheel on your background, you can just make a D3D_Sprite out of an AGS sprite and render it onto the background, increasing rotation each frame. No need for an animating bg which takes up lots of memory, or a prerendered wheel animation, or a bunch of prerotated dynamic sprites which tend to look blocky and crappy.

Calin Leafshade

It would be nice if you could specify the quad that the texture is rendered to, specifically so you could make it non-square, allowing for perspective deformation.



AJA

Good idea, I'll put it on my list!

It's gonna take a while before I can continue working on the next version, since I'm trying to get a game project into the development phase. But since that request is pretty easy to implement, I can make a minor update sooner if you need it. Just let me know.

None

 :-D Thanks for the nifty little plugin!

I've been playing with it since this morning, made a little 320 x 240 video in after-effects to make sure it was working.
The file is slightly large, but that's to keep the .ogg from being lossy. The test demonstrates the plugins ability to seamlessly loop a video.
And more importantly to me, I had to be sure I could get the gosh-darn thing to work before I started rendering out tons of video backgrounds! (laugh)

Here's the link, and again; Thanks.
http://www.charlescreations.com/d3dptest.zip


DazJ

Please forgive me ignorance but how do I get the background video to constantly loop over? Which piece of code do I use and where?

Excellent plugin! :D

AJA

After you've opened the video just set video.isLooping to true.

DazJ

Ah, I did use that code but put it BEFORE the video was actually loaded...DUH! Cheers AJA ;)

EDIT: I've actually just noticed that using this plugin seems to messup the Z-Order of my GUIs (particulartly the SSH's Description Module). If I've been playing a background video and progress to another room, the Z-Order of the Description Hotspot over the Inventory items falls BEHIND them.

However, if I go to that room WITHOUT first visiting the room with the background video, I have no issues with the Z-Order on the inventory.

Any ideas at all?

AJA

First of all, that's weird. Second of all, that's really really weird.

Do the actual z-order values change? (Can you even access them in runtime?) I don't see how the plugin could screw that up without messing with AGS's internal stuff. But then again, I'm no DirectX expert, so who knows how badly I've messed things up. :-\

DazJ

Yeah, it has me baffled too.

The Z-Orders aren't physically changed in the properties windows, no. I've even tried setting the Z-Orders in the script after the room changes but alas, it has no effect. Using the plugin seems to just render all Z-Order settings as void, no matter what they're set at.

I'm under the impression that the video itself could perhaps have it's own Z-Order? This isn't my thing so I'm probably wrong.

If I remove the plugin then hey-presto, everything works again so it seems to be down to the plugin, unfortunately :/

Does anyone else have any suggestions?

DazJ

Has anybody any idea on why this is happening? I really want this plugin but might have to go without it :(

AJA

I'll try to replicate this over the weekend and see if I can find a way to fix it. Unfortunately there are also some other things to fix since a while back I managed to break the new version I'd been working on. 8-)

DazJ

Oh dear lol. There's no rush - I can still keep plowing on in terms of coding and it still ultimately works, I just want it to be polished. It certainly is a baffler :/

Absolutely amazing plugin though! :D

DazJ

I've fixed the Z-Order issue. For some stupid STUPID reason I'd copied two different variants of the Description Plugin code into both the GlobalScript AND a Room. One set to use Overlay and the other to use GUI. Of course, with Overlay, you can't set the Z-Order. Anyhow, the problem has been resolved. I just feel like a bloody fool now. I am so sincerely sorry for wasting any of your time.

Of course, this means that your plugin works flawlessly for me :)


Cassiebsg

Hey

Soryy to dig up this old thread, but I was trying scotch theora plugin, which worked fine, until I run into the flipped frames bug... so thought I would try this one. Only AGS is giving me an error when trying to load it:

Quote
---------------------------
Adventure Game Studio
---------------------------
There was an error loading plugin 'ags_d3d.dll'.



Unable to load plugin 'ags_d3d.dll'. It may depend on another DLL that is missing.
---------------------------
OK   
---------------------------

Any ideas what that eventual DLL might be?
I'm using the latest AGS 3.4.0.13-Patch1.
There are those who believe that life here began out there...

Crimson Wizard

According to Dependency Walker, this plugin requires D3DX9_43.DLL (part of some certain Direct3D 9 version).

Quickly searching for the name of this file I found this discussion: https://answers.microsoft.com/en-us/windows/forum/windows_7-gaming/system-error-the-program-cant-start-because/261e2bb5-2e75-e011-8dfc-68b599b31bf5


As a side note, that may be obvious but I think I'd note that using this plugin in your game will make it impossible to play your game on other platforms.

Cassiebsg

Thanks! :)
I'll see about getting it downloaded and test it.

Yes, I know about not working on other platforms, and atm am not that worried about it.
So unless you can make the AGS play.movie (or what it's called) command play a movie in the BG (non-blocking), which I would rather use than a plugin... I have litte choice.
The only other choice is importing a huge amount of sprites and explode the sprite and game size. :( 

EDIT: Just finished installing the D3DX9_43 (dxwebsetup.exe I downloaded by following the CW's link), and that fixed it! :D I'm on win10, just for future reference. ;)

Thanks bunch, now I can test this pluging and see if it fixes the flipped frames bug from scotch's plugin. :D

EDIT 2: This is weird... I got this error even though my game is 32bits colour with true alpha. ??? ???
Quote
---------------------------
Adventure Game Studio
---------------------------
An internal error has occurred. Please note down the following information.
If the problem persists, post the details on the AGS Technical Forum.
(ACI version 3.4.0.13)

Error: 32bit colour mode required.

---------------------------
OK   
---------------------------
There are those who believe that life here began out there...

Crimson Wizard

Quote from: Cassiebsg on Tue 10/01/2017 13:55:23
EDIT 2: This is weird... I got this error even though my game is 32bits colour with true alpha. ??? ???
Quote
---------------------------
Adventure Game Studio
---------------------------
An internal error has occurred. Please note down the following information.
If the problem persists, post the details on the AGS Technical Forum.
(ACI version 3.4.0.13)

Error: 32bit colour mode required.

---------------------------
OK   
---------------------------

This is because the plugin checks which graphics mode is set preliminary, in AGS_EngineInitGfx plugin callback, and therefore gets "incorrect" values.
Something changed in between AGS 3.2.1 and 3.4.0, probably in earlier versions AGS set up these values in advance (before actually trying to set screen mode).



EDIT:

I have checked the Plugin API description, and this is what is said there:
Quote
DLLEXPORT void AGS_EngineInitGfx(const char* driverID, void *data);
Called by AGS just before the graphics driver is initialized. This allows you to make changes to how the driver starts up.
driverID is the ID of the graphics driver in use. This can either be "D3D9" if the player is using the Direct3D driver, or "DX5" if they are using the standard DirectDraw driver.
If driverID is "D3D9", then the data parameter is a pointer to the D3DPRESENT_PARAMETERS structure that AGS is about to pass into CreateDevice. If you need to enable extra features such as the Auto Depth Stencil, then you can do so by changing the member variables at this point.
If driverID is "DX5", then the data parameter will currently be passed as NULL.
   
This event is called just as the graphics subsystem is starting, so functions that like GetScreenDimensions that rely on the screen being initialized will not work if called from this event.

Note what I marked with red color. This is actually what the plugin is doing: it calls GetScreenDimensions at that point, which is not guaranteed to work. The reason that it worked with 3.2.1 was pure luck, it's just that engine was coded in such way back then.


EDIT2:
I can with all honesty say, that I would not want to "fix" engine to work with this plugin; although we make such backwards-compatible fixes for old scripts, but how plugin is coded is not responsibility of AGS developers.
AJA seem to visit forums recently, I suggest to contact him and ask if he still has this plugin sources and whether he may fix it. Plugin needs to use callback argument (D3DPRESENT_PARAMETERS) instead of GetScreenDimensions to check screen mode.

Cassiebsg

Thanks bunch for checking CW! (nod)
I'll wait a bit and see if AJA sees and replies here in the thread, before PMing him.
There are those who believe that life here began out there...

AJA

To my great surprise, I found the sources for this ancient turd, whee!

Should run in AGS 3.4.x now: http://www.serpentpictures.net/ags_d3d/ags_d3d.zip

Thanks, CW, for figuring out the fix beforehand. Saved me a lot of time, cheers! :cheesy:

Cassiebsg

Cool, thanks bunch you two! :)

Downloaded, activated and tested (as in yes, I can open my game now with no error! :-D ).
Looking forward to test it with the code and video now! (nod)

EDIT: eeeeewwwwwwwww..... :~( Finally had some time to test this, and now I get a game crash when trying to load the video.

Quote
---------------------------
Illegal exception
---------------------------
An exception 0xE06D7363 occurred in ACWIN.EXE at EIP = 0x76BDB727 ; program pointer is +1004, ACI version 3.4.0.13, gtags (32,400)

AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and post the details on the AGS Technical Forum.

in "room1.asc", line 29


Most versions of Windows allow you to press Ctrl+C now to copy this entire message to the clipboard for easy reporting.

An error file CrashInfo.dmp has been created. You may be asked to upload this file when reporting this problem on the AGS Forums. (code 0)
---------------------------
OK   
---------------------------

The line in question is: video = D3D.OpenVideo( "Galactica_Intro.ogv" );

Now, this video works fine if I use scotch's Theora plugin.
I basically just copy/pasted this code:
Code: ags

D3D_Video* video;

function room_Load()
{
    // Required for autoplay
    D3D.SetLoopsPerSecond( GetGameSpeed() );
    
    // Open video file
    video = D3D.OpenVideo( "TheoraVideo.ogv" );
    
    if ( video )
    {
        // Use room coordinates
        video.relativeTo = eD3D_RelativeToRoom;
        
        // Anchor point to top left corner
        video.SetAnchor( -0.5, -0.5 );
        
        // Play!
        video.Autoplay();
    }
    else
    {
        Display( "Couldn't open video." );
        return;
    }
}

function room_Leave()
{
    // Free memory when leaving the room
    video = null;
}


And replaced the name of the file with my video.
Is it me that is doing something wrong?
I can provide the dump, if needed.
There are those who believe that life here began out there...

AJA

Apparently if you run it from the editor it's looking for the video file in the Compiled folder but if you run the windows executable it looks for it in the Compiled\Windows folder. Maybe that's the issue you're running into? The error handling in this plugin appears to be quite lacking, sigh.

CW, can you confirm that GetPathToFileInCompiledFolder(const char*fileName, char *buffer) is no longer working as expected with the new platform specific folders or is there some other method I should be using to get the final compilation folder?

Cassiebsg

Okay, thanks for the info! :-D

Yes, that seems to be the problem. I copied the video to the compiled folder and now it loads! (nod)

Guess I just assumed that since the Theora plugin worked with the video from the game project, that so would this one. (roll)
Sorry about it. :)

Now I can launch myself into making my cutscene entirely in Blender and save on the sprite size ;)... or maybe I should do a few tests before counting victory... again.

EDIT: Just one more question, and probably why I didn't thought of copying the file into the compiled folder...
but shouldn't the code with the else Display("Couldn't open the video."); had been shown instead of crashing the game?
There are those who believe that life here began out there...

Crimson Wizard

Quote from: AJA on Tue 17/01/2017 19:08:07
CW, can you confirm that GetPathToFileInCompiledFolder(const char*fileName, char *buffer) is no longer working as expected with the new platform specific folders or is there some other method I should be using to get the final compilation folder?
With changes to build folders structure I was going to remove any dependency on hard-coded folder names in the engine in the future, and subsitute them with some parameter passed by the Editor.

But as of 3.4.0 we still have a rule that all game data should be placed into Compiled folder, from where they are copied to every version (Windows etc).
This actually brings me to a thought that running game under debugger may not work correctly if you have Windows-only data for you game.

AJA

Ah, so it gets copied there on compile, gotcha!

Cassiebsg, I uploaded a new version which should fix the file not found issue but also, and more importantly, implements screen scaling so it should look the same regardless of at what resolution you're running the game. Might not work perfectly but at least it's a start in case you decide to keep using the plugin.

Cassiebsg

Thanks, the scaling was a nice fix, I noticed on my previous run that the video was small and on the lower corner. But now it's filling the screen. (laugh)

However... the game no longer almost not crashes if it doesn't find the file. :-\
Putting a display into room_load crashes the game.
But then again, does the video need to be in room_load? what happens if it's in AfterFadeIn? I'm guessing, and hoping that it'll work just as fine. Because I'm planing to use the same room to run all 3 movies/cutscenes.

Also, file doesn't get copied on compile. But I suspect that is expected, and I have no problem moving the file into the compiled version, or even into the final game version. No problem here that needs urgent fix. Maybe just a note on the html file though. ;)

EDIT: Just tested with a second video in the room, and works fine. Well, again, almost, the return; after the Display puts the game on a loop, of constantly repeating the "Couldn't open video.". So I just deleted the line,now displays the message and continues running the code and thus the game. ;)
There are those who believe that life here began out there...

AJA

At least in AGS 3.4.0.13 if I had the video file in the compiled folder and built the game, it got copied to the folder that has the exe.

Quote from: Cassiebsg on Tue 17/01/2017 21:33:37
But then again, does the video need to be in room_load?
You can of course load the videos whenever you need them, shouldn't make any difference.

Anyway, glad to hear you're mananing to wrestle this thing into submission! ;D

Cassiebsg

Hey :)

All is working just fine!  (nod)

Just one "quirk", I have the movie inside a skipable cutscene, and I've noticed that I need to press ESC twice to actually skip the scene. First ESC stops the movie and all text and then just "hangs" there, untill I press it again, and then it opens the menu GUI.

Here's the code I'm using:
Code: ags

void Cutscene_Intro()
{
StartCutscene(eSkipESCOnly);
// some speech and music code
while (video.NextFrame() && !IsKeyPressed(eKeyEscape))
{
    Wait(1);
}
EndCutscene();
//other code including turning the menu visible
}


I can post the entire room code, if you think it makes a difference.
There are those who believe that life here began out there...

AJA

I ran the same code quickly in my test project (AGS 3.4.0.13) and didn't notice any issues enabling any menus after the video is skipped. Only thing I noticed was that if you have a line of dialogue (probably anything skippable with a key press), it would be skipped without an extra wait after the cutscene.

Code: ags

    StartCutscene(eSkipESCOnly);
    
    while (video.NextFrame() && !IsKeyPressed(eKeyEscape))
    {
      Wait(1);
    }
    
    EndCutscene();
    
    Wait(1); // Need to wait here so the key press doesn't skip the dialogue
    cEgo.Say("This is not shown without the extra wait");


Could your issue be something related to that or caused by some other part of your code?

Cassiebsg

Okay, seems to be working even more weirdly than I expected. I removed CW's typewriter module out and the problem went away... So seems to be the other module that is interfering. But after I put the typewriter back is started working right (as in just one key press), but not if I do it right at the start...

So ignore this, problem seems to the be with the typewriter module.
Sorry to bother you and thanks for the quick reply.  (nod)
There are those who believe that life here began out there...

AJA

No problem. Let's hope it doesn't mysteriously unfix itself. :P

Cassiebsg

Okay, stumble into a new problem, not sure if this is caused by the plugin or the AGS code, though.

So, I have this working perfectly now, and decided to address the problem of "what happens if the player is in a system that can't run the plugin?" And to avoid having the game just crashing and refusing to play I added the following code:

Code: ags

if (Game.IsPluginLoaded("Direct3D Plugin")) 
  // load the video code
else 
  Display("Couldn't load the plugin");


The good news is that the game no longer crashes if the plugin fails to load  :-D... the bad news is that I can't get the video to load  :~(...I've tried putting on the string's plugin name "Direct3D" , "Direct3D Plugin" , "Direct3D Plugin (ags_d3d.dll)" and "ags_d3d.dll" .

And just to be sure this:

Code: ags

if (!Game.IsPluginLoaded("Direct3D Plugin")) 
  // load the video code
else 
  Display("Couldn't load the plugin");


Results in video loads just fine, and crashes if I remove the dll from the compile folder. So it's definitely the check that is failing...

Any ideas?  ???
There are those who believe that life here began out there...

AJA

It should be "Direct3D Plugin", at least that's what the plugin returns as its name, so either the method is broken or it's checking against some other string.

Crimson Wizard

Oh, I realized the manual entry is not elaborate enough.

IsPluginLoaded checks against plugin's FILENAME WITHOUT EXTENSION. Because the OS may not be Windows, but e.g. Linux, which have different extensions for plugins.

Like "ags_d3d".

I decided to make it check against filename, because game references plugin same way in its data when decides what to load.

Cassiebsg

Ah, cool.

Thanks CW.  (nod)

But now it's acting up like before I added the check. It just crashes if I remove the dll from compile folder.  8-0

Quote
Error:Unable to create local script: Runtime error. unresolved import 'D3D_Video::get_renderStage'

I have my code in the room script, where I have
Code: ags


D3D_Video* video; // defined at the top of the script

function room_Load()
{
  if (Game.IsPluginLoaded("ags_d3d"))
    // load the video code
  else
    Display("Couldn't load the plugin");


Still not sure if this is my poor scripting skills, AGS or the plugin.  :-\
There are those who believe that life here began out there...

Crimson Wizard

If you are using SCRIPT COMMANDS from plugin in your script, then using IsPluginLoaded won't help you in any way.

This is how AGS works, it must get a script function if it was even mentioned in scripts, and if it cannot get one from plugin, then it refuses to continue.

Cassiebsg

Okay, guess I'll have to confine to having to compile and upload two versions of the game, one with video and one without.  :-\

Ps - I've now added some #define code, that Gurok suggested for this effect (creating 2 versions of the game)...
There are those who believe that life here began out there...

Gurok

Here are the instructions I sent Cassie:

--

Make a new script file and put it at the top of your script list.
Put this in the header:

Code: ags
#define VIDEO_VERSION

     
Change your code to
     
Code: ags
#ifdef VIDEO_VERSION
D3D_Video* video; // defined at the top of the script
#endif

function room_Load()
{
#ifdef VIDEO_VERSION
    // load the video code
#endif
#ifndef VIDEO_VERSION
    Display("Couldn't load the plugin");
#endif


Use #ifdef VIDEO_VERSION anywhere D3D_Video stuff is referenced.
When you want to make the non-video version, comment out the #define line.

--

I'm posting this for future people who stumble across this thread, in the hope it helps others with the problem CW outlined above.
[img]http://7d4iqnx.gif;rWRLUuw.gi

Crimson Wizard

In the past I wrote a feature which let you to configure stubs for plugin functions. I gave it out for testing, but no one seemed to be interested, and I later forgot about it myself thus it never ended up into the official version.


Gurok

Ah, I was just suggesting something like this to Cassie on IRC.
This would be great. Is the branch still around? The link to the branch didn't seem to work for me.
[img]http://7d4iqnx.gif;rWRLUuw.gi

Crimson Wizard

It should be working, still in my repository. But the branch is very outdated and has to be rebased.
Branch name is "improve-scapimap", you could try fetching it in git.


Although, today I'd rather try some different approach which would do similar thing automatically, if compiler could add a note on imports that belong to plugins to let engine distinct these.

Cassiebsg

So, is that something I could use/implement or does it require more than what I can? 
Cause that sounds just like what I need.  (nod)

I can either offer my project for testing, or just make a snippet of it, for the purpose, if you like.
There are those who believe that life here began out there...

Cassiebsg

Okay, quick question/problem.

I decided to use the Credits Module by SSH to scroll the end credits, and all was going pretty good, until I finally was done rendering the movie and added it to the project...  :-\ Apparently it suffers from the same problem that CWs TypedText suffered. But no matter what I try, I just can't get the video running on the BG.  :~(
Now this isn't that big a deal, since the video is mostly the ships just moving from the right to the left, so AGS can do that easy with a few sprites, but thought I would mentioned just in case you want/can fix this.

If you figure out what is causing this, or how to solve it, I'll be all ears.  (nod)

There are those who believe that life here began out there...

AJA

Are you using the correct render stage?

Code: ags
video.renderStage = eD3D_StageBackground;


That should render it immediately after the game background finishes rendering and before anything else.

Cassiebsg

Erm... yes I had that... but now I'm unsure what happened, cause now it's working.  :-[

Last time I had tried it was running the video, and then the credits after the video was finished.  (roll)
There are those who believe that life here began out there...

eri0o

AJA, are you still around? I would reaaaally like to take a look at your code to see what you needed to initialize of Directx in it and what you didn't because AGS had already done it for you.



rmonic79

Hi Guys anyone solved scaling and aspect ratio issues with 3.5 and also the crash on Fullscreen/windowed switch?

nightmarer


nightmarer

Hello everybody.

My videos does't load if I don't set the property video.isLooping to true.
But it is strange that if I enter a Display("") to pop-up a message pausing the game after calling the function, the video is Displayed while the action is paused.


   
Code: ags

    videofile="Rosefall.ogv";    //here I set the videofile that must be load
    videoloop=false;       //this is a global bool to set as value in video.islooping
    playbackground (videofile); //this is the call to the global function
    Display("Playing"); //If I enter this I see the video running, but if not the video is not shown
    stopplay();  //this is how I call the function to set video as null, because it didn't work in the original function in the else statement
    videofile="Nebula2.ogv"; //setting another video
    videoloop=true; //this is the way to set that the loop works agaoin
    playbackground (videofile); //and this oe works fine


This is how I modified this functions.

Code: ags
function playbackground (String videofile) {
 if (Game.IsPluginLoaded("ags_d3d")) {
  // Required for autoplay
  D3D.SetLoopsPerSecond( GetGameSpeed() );
  // Open video file
  video = D3D.OpenVideo( videofile );
  if ( video ){
   // Use room coordinates
   video.relativeTo = eD3D_RelativeToRoom;
       
   // Anchor point to top left corner
   video.SetAnchor( -0.5, -0.5 );
        
   // Play!
   video.Autoplay();
   video.isLooping=videoloop;
  }
  else {
   Display( "Couldn't open video." );
   return;
  }
 }
 else{
  Display("Couldn't load ags_d3d plugin");
 }
}

function stopplay() {
video=null;
}


Do I need to do anything to let the video finish?
How can I load a video to be played just once without doing weird things?

Regards.

Crimson Wizard

As an experiment, I took this plugin and removed D3D part keeping only Theora playing, and then remade it to write video frames into the given sprite (number) instead of plugin's texture.
This is relatively slower, as video frame goes first to the sprite, and then from sprite to the texture inside engine itself. But this way it should work with any renderer, also one can put the sprite anywhere you usually put sprites in AGS. It's hard to tell if it may be optimized further with existing plugin api and theoraplayer library this plugin uses.

This is roughly how I'd attempt to implement playing videos on objects in AGS, but it's just easier to do with the existing plugin (with engine one would have to rewrite number of things to make it good, and also write a whole new playback API).

Did not have time today to further tidy the code etc yet, so uploaded the dirty version of the project here:
https://www.dropbox.com/s/k33h1fi7xe7mc4c/ags-spritevideo.zip?dl=0
and compiled plugin:
https://www.dropbox.com/s/0cai4gtd9uuk9df/ags-spritevideo-dll.zip?dl=0
note file is still called "ags_d3d", forgot to rename it...


One known problem is that AGS does not know that the sprite was updated, and so does not update objects on screen. I need to look more into whether plugin API allows to notify engine about that. For now I use the dirty hack by "poking" it with drawing surface ---

Example of script
Code: ags

DynamicSprite *DSPR;
D3D_Video *video;

function room_AfterFadeIn()
{
	DSPR = DynamicSprite.Create(200, 200, false);
	video = D3D.OpenVideo("test.ogv", DSPR.Graphic);
	if (video != null)
	{
		video.Autoplay();
		oVideo.Graphic = DSPR.Graphic;
	}
}

function repeatedly_execute_always()
{
	if (DSPR != null)
	{
		DrawingSurface* ds = DSPR.GetDrawingSurface();
		ds.DrawPixel(-1, -1);
		ds.Release();
	}
}

function room_Leave()
{
	video = null;
	DSPR.Delete();
}

Crimson Wizard

In regards to improving Direct3D plugin itself (or making an alternate version of such plugin), here are few thoughts about what's necessary to make it work well with the newer versions of AGS.

Multiple renderer support

Don't think there's much other choice than to implement all the same renderer types that engine supports: Direct3D, OpenGL, and software drawing too (if really wanted).
Plugin gets current driver ID, so may switch to necessary implementation on start.
Direct3D and OpenGL renderers would just apply quads to the scene according to their own rules similar to how plugin already does, and software renderer (if necessary) would call IAGSEngine::GetVirtualScreen to receive a stage backbuffer.

Support switching gfx modes

I do not know if plugin receives any events when game's gfx mode changes. If not, then this is a problem, as plugin won't be able to react and change its screen settings. Maybe it's still possible to adjust these at initial render stage callback.
There's still one important thing: Direct3D 9 gets reset when gfx mode changes, which may actually require to recreate video-memory resources. If plugin uses these and don't react to such reset, this may lead to crashes.

Viewport matrixes

It seems that Direct3D was made with an assumption that game image takes whole window, plus it obviously was made in the time when there was only 1 room camera and room viewport was also always covering whole game image.
This may still be usable while you have only 1 standard room viewport, or simply draw outside of room, but there still will be issues with aspect ratio (probably this was what rmonic79 noticed above).
Things will become more complicated if we add more transformation to the room viewport, or more different layers on screen.

The proper solution, I think, would be to actually pass viewport matrix into plugin on each render stage. I.e. on AGSE_PRESCREENDRAW plugin would receive corresponding room viewport matrix, on AGSE_PREGUIDRAW it would receive GUI layer matrix, and so forth.
In such case plugin will not have to make any assumptions, but simply use this parent matrix that engine provides.

Plugin callback already has an argument, which is unused for these stages, and which may be turned into pointer to a struct with necessary data. Such struct could be expanded further when necessary.
The only problem there is that this argument is currently declared as 32-bit integer and cannot work as 64-bit pointer, so this has to be adjusted. Maybe it's safe to do so, as pointer size will still be 32-bit in 32-bit engine/plugins. If it's not (as this argument is already used for other purposes), then there might be other paths to achieve this, such as expanding callback function prototype, adding second callback for new plugin API version etc. Anyway, this is all technical details.

Crimson Wizard

Another heads-up, few things changed in AGS 3.5.1 regarding path handling, and this plugin has a mistake by not allocating enough buffer for video path, so it has high chance to crash when trying to open video in AGS 3.5.1.
Crash itself is a consequence of unsafe plugin API (specifically GetPathToFileInCompiledFolder function) where it does not let plugin pass buffer length into engine, so engine literally does not know how much is it allowed to write there...

This is trivial to fix in plugin, but you got to rebuild it from source of course. The buffer should normally not be smaller than MAX_PATH constant (260 on Windows, may be much higher on Linux afaik).

PS. This is found in D3D_OpenSpriteFile and D3D_OpenVideo functions.

Crimson Wizard

Ok, I actually found out why this plugin scaling broke after 3.4.0. It happened after following engine change:
https://github.com/adventuregamestudio/ags/commit/e1cc278aa38cf66de38cb2bda2e45267e0391fc4

Or more precisely, Orthographic projection has changed from
Code: cpp

(2.0 / (float)_mode.Width), 0.0, 0.0, 0.0,
0.0, (2.0 / (float)_mode.Height), 0.0, 0.0,

to
Code: cpp

(2.0 / (float)_srcRect.GetWidth()), 0.0, 0.0, 0.0,
0.0, (2.0 / (float)_srcRect.GetHeight()), 0.0, 0.0,


Which means projection is no longer in full window resolution, but in native game resolution.
Which is questionable, considering we might want to render something outside game's frame and this projection makes that inconvenient probably (not impossible), but this was convenient for rendering at native pixel resolution mode afaik. Anyway this is what we have currently, unless this changes in the future once more...



If hardcoded fix is acceptable, all you have to do is to fix the scaling for post-3.4.0 engine is these 2 lines in D3DObject.cpp:
Code: cpp

float screenScaleX = static_cast<float>(screen->backBufferWidth) / screen->width;
float screenScaleY = static_cast<float>(screen->backBufferHeight) / screen->height;

they should be just
Code: cpp

float screenScaleX = 1.0;
float screenScaleY = 1.0;

because, if I understand correctly, plugin assumes it has to rescale object from native resolution to projection (which was correct with the old engine), but since now projection equals native resolution, no scale is necessary.




For non-hardcoded fix, I've been doing an experiment with passing engine matrixes into the plugin.
Unfortunately, passing through event hook arguments appeared to be too complicated as multiple changes need to be done in the engine to pass these through.
So I favor another approach: introduce new engine interface function which looks roughly like:
Code: cpp

AGSIFUNC(void)  GetRenderStageDesc(AGSRenderStageDesc* desc);

where AGSRenderStageDesc is an extendable struct which may contain all 3 engine matrixes for the current render stage (screen, room, gui, etc):
Code: cpp

struct AGSRenderStageDesc {
  // Which version of plugin the struct corresponds to;
  // this field must be filled by plugin before passing the struct into engine!
  int     Version;
  BITMAP *StageSurface;
  float   ProjectionMatrix[16];
  float   WorldMatrix[16];
  float   ViewMatrix[16];
};

These matrixes would be filled by each gfx renderer in their format (Direct3D and OpenGL), and thus could be used by any existing renderer and any renderer AGS might have in the future, in theory.

I'd like to try adding this new function into 3.5.1, only need to test more if it's viable to read necessary screen scaling from project matrix in the plugin itself, and if these matrixes actually let to work with custom room viewports.

Crimson Wizard

Sorry for all my rambling here...

Here's a rebuilt version of Direct3D plugin fixed for AGS 3.5.0/3.5.1:
https://www.dropbox.com/s/u23fvlar4q45kvd/ags_d3d_for351.zip?dl=0
It should have fixed scaling, and also fixed few more errors found during research.
Source project: https://www.dropbox.com/s/4rtfeh7gzxqs1hh/ags_d3d_for351_source.zip?dl=0

This version works in 2 modes, first is for ags 3.5.0 where it does not fully support custom room viewports, because it cannot do that correctly with existing plugin API. D3D objects will have correct viewport offset, but won't have correct camera scaling (and maybe something else will be wrong). It should work fine if you don't change default room viewport/camera.
Second mode is experimental and it only activates if engine plugin interface has certain number which is not in official release yet. But if everything is fine and we'll add this new interface into AGS 3.5.1, then D3D plugin (and others) will be able to receive full information on how to render things with Direct3D/OpenGL in modern AGS (there's a function that returns 3 transformation matrixes for each given render stage).


Couple of notes on the source project. It's made in Visual Studio 2010, because it uses libtheoraplayer library built for MSVS 2010. It will not work if you compile it with later MSVS, unless you also rebuild libtheoraplayer from source. Lib source may be found here: https://www.cateia.com/libtheoraplayer/wiki/index.php?title=Releases . Which may in turn involve more issues you have to fix; maybe I missed something, but it took me some time to make it actually work and compile, and I decided to stick to old project for now (plus I have MSVS 2010 on my pc). Just saying as a warning. Ideally someone got to gather it all up into a proper contemporary MSVS project and host on github etc. Even better - provide OpenGL support within same plugin - that would be awesome and make this plugin crossplatform.

Tarnos12

Hey, anyone using this plugin figured out how to fix an issue with full screen alt-tabbing?
The screen goes white after coming back to the game.

The log file says:
Code: ags

D3DGraphicsDriver: D3D Device Not Reset
D3DGraphicsDriver: Failed to reset D3D device


This happens if you OpenSprite with D3D plugin in full screen mode.

Test Game
https://www.dropbox.com/s/wqa0295aonpd8pk/D3D_Test.rar?dl=0

Steps to reproduce:
1) Open the game through Compiled/Windows folder so it launches in full screen.
2) Click "GO" button to draw a sprite using D3D
3) Alt Tab
4) Go back
5) Screen will go white and you can no longer play the game, the only way to close it is via task manager.

Crimson Wizard

Updated build with a stricter script API syntax, fixes this plugin for the new compiler from ags4 branch, but should work normally in AGS 3.5 and 3.6 as well; no functional changes.
https://www.dropbox.com/s/fogrd0v3xry0vso/ags_d3d_for399.zip?dl=0
Source project:
https://www.dropbox.com/s/nahgib8xay692p5/ags_d3d_for399_source.zip?dl=0



Quote from: Tarnos12 on Sun 03/04/2022 17:40:05
Hey, anyone using this plugin figured out how to fix an issue with full screen alt-tabbing?

There have been few fixes to Direct3D fullscreen in the engine since, please try again with the latest 3.6.0 / ags4 branch.

Crimson Wizard

As an experiment, I am making a new version of this plugin, that will work with both Direct3D and OpenGL. The latter theoretically allows to use the plugin on other platforms.
Just mentioning it here for the reference; perhaps should be posted in its own thread later.

dll: https://www.dropbox.com/s/w5b31vm0iow7psa/ags_sprite3d.zip?dl=0
64-bit linux so: https://www.dropbox.com/s/mrp3kv5do8mqhxr/libags_sprite3d.zip?dl=0
source: https://www.dropbox.com/s/bp6k5nwg4izvgzz/ags_sprite3d_source.zip?dl=0
The plugin file is called differently (ags_sprite3d), but it's 100% script compatible, which means that you may:
- rename it to ags_d3d.dll and use in same game.
- disable ags_d3d and enable ags_sprite3d in your project and recompile, for the similar result.
No script changes will be necessary.
WARNING: currently not working: theora video playback, creating textures directly from files.

UPDATE: support building for Linux (OpenGL only).
UPDATE: reintegrated video playback.
UPDATE: created a thread for the new plugin: https://www.adventuregamestudio.co.uk/forums/index.php?topic=60089.0

Tarnos12

Quote from: Crimson Wizard on Sun 03/07/2022 22:29:07

Quote from: Tarnos12 on Sun 03/04/2022 17:40:05
Hey, anyone using this plugin figured out how to fix an issue with full screen alt-tabbing?

There have been few fixes to Direct3D fullscreen in the engine since, please try again with the latest 3.6.0 / ags4 branch.

Confirmed, it works.
Tho with the new updated plugin it is not a problem anymore anyway :D

SMF spam blocked by CleanTalk