I've been noticing much more lately that there are trends going on specifically in software development of all forms, but specifically one in Game Development which has a large factor in why I have not pushed harder towards finishing and publishing any projects. The trend is simple to understand, but hard to admit when guilty. Heavy hitter established programmers are generating blockades for up and coming programmers who love the craft of programming.
One business development pattern that falls in this is the development shift to use web services. Even though I rather enjoy working in them, I do enjoy networking code far more. What happened to all the companies doing socket work? Well some genius of an individual found it would be easier and just as fast performance wise and way faster development time to use web services. It's a great idea, but it dumbs down the task to a point where most anyone with some programming knowledge can pull it off.
Numerous companies building UI frameworks or other similar systems for dealing with hard to accomplish tasks. Business leaders wouldn't dream of paying their staff for the time it would take to implement these things. So, they just pay for the third party.
Now, to hone in specifically to game development. There are and always will be people out there, myself included, who would aspire to be more like Eskil Steenberg and write an entire game with the use of no third party in straight C!! This man is hardcore, and would not dream of doing it any other way. The problem exists in that investors and business have taken over the industry. Funding a project with this methodology is not probable.
Having a background of being heavy in the modding community through high school and some after I say nearly the entire indie development franchise don't really develop video games. They're glorified modders. I'm not writing this as an assault against anyone who would fall in this category. It's mainly a thought and would aim to remind those of you who are aware of the time when video game industry almost disappeared completely. I'd hope to encourage and inspire those that are not in the "Notch" or Eskil Steenberg personality type to rethink your game plan for development moving forward. Allowing big business and publish over polish to mandate the development of your games will in my opinion lead to another near extinction of Video Games. If you don't really believe that's a possibility, go looking at new releases. Even from the AAA ranks we're getting a lot of weak titles. Look on your phone count how many of the top grossing mobile games are clones of one another. There are definitely a few great games out there, but the market is flooded with clones. Time to innovate and build video games on Radar machines again.
History Repeats Itself
Tuesday, July 22, 2014
Monday, May 20, 2013
Generics and Boxing Capabilities
Generic classes and Boxing techniques are fairly common practice. It is often under appreciated. If we look at a linked list we see that it is using both simultaneously. It is a great implementation, even though performance can both be improved and hurt by it. This is a crucial part of understanding how these topics coincide. The LinkedList<T> from the .NET framework is just one example of this type of concept, and probably in a weaker example.
LinkedList(T) MSDN DOCs
If you want to understand this class further viewing forum topics regarding LinkedList pros and cons would be wise.
This post however is about taking this concept to a new level. In many application development practices we work with Hierarchies. They're often coded to be specific to the application. Sometimes, we implement base classes for this architecture because we use it so often, but how much further can we take such a technology? Can it be improved upon? Obviously this is rhetorical, and theoretical. Not only can we make the assumption there are no code practices that cannot be improved upon, we can also use this case as an example of such.
The run down of how we using Boxing and Generics to take this tech further is actually not that complex. Linked lists get their benefit from faster insertion and navigating related objects. Same sort of reason we use Hierarchies often. One weakness of hierarchies is always starting at the top. This implementation is two part. The data is actually stored for the tree in more ways than one. And it is retrieved in more ways than one as well.
Storage
We store the hierarchy in two crucial ways. Since this is a full generic class we have to create boxing for the nodes. The nodes store information about the level parent and child relations. So, we can still start from the top of a tree and iterate down the nodes like normal. There's a new trick though for faster access. Sometimes, we need to access only data a few levels deep. Or all items on a particular level only. This is why the storage is actually storing nodes in arrays for each level as well. There is no distinction in this storage regarding parents and children, just all nodes on that level. There is one trick to this that was discovered by accident, but absolutely incredible. Children can actually be added first. The other one that was intentional is that an array of values can be converted into a hierarchy. My test project acftually converts an array of random integers into a hierarchy driven by digits where multiples of ten define the level. Looks like this:
1000
1100
1110
1111
The way this system is designed such generation is purely algorithmic or interface driven. Very cool and very powerful. May sound kinda lame but if you're into "fancy" code... this is right up your alley.
Retrieval
Since we've stored the data in this way, we can do some incredible things. One example, say we have a tree 5 levels deep, but the upper 4 levels just contain informational data not important to our actual processing. In most oldschool hierarchies this would still have to iterate all levels to get the bottom. Not here. We can pull just level 5 and not even acknowledge the parents even exist. Pretty cool huh? (Pretty simple too....) This structuring also gives a few benefits in speed. When retrieving nodes where the parent matching a condition(yes seriously) this is very easy and faster than it would normally be. If we already have a node we just access it's children which prevents us from having to navigate and compare the entire level. This is normally how we would do it, just felt it important to note this implementation does not exclude that.
The ways in which the data is accessed is always the fasted option to retrieve the value desired given the information supplied. In many cases faster than it would normally be from a normal hierarchy setup, but admittedly not all. It's functional and optimized in many ways, but as many practices teach us, functionality often sacrifices performance.
Code Snippet
Below is a quick snippet from the integer example mentioned: (There are other parts not visible here excluded to avoid confusion)
LinkedList(T) MSDN DOCs
If you want to understand this class further viewing forum topics regarding LinkedList pros and cons would be wise.
This post however is about taking this concept to a new level. In many application development practices we work with Hierarchies. They're often coded to be specific to the application. Sometimes, we implement base classes for this architecture because we use it so often, but how much further can we take such a technology? Can it be improved upon? Obviously this is rhetorical, and theoretical. Not only can we make the assumption there are no code practices that cannot be improved upon, we can also use this case as an example of such.
The run down of how we using Boxing and Generics to take this tech further is actually not that complex. Linked lists get their benefit from faster insertion and navigating related objects. Same sort of reason we use Hierarchies often. One weakness of hierarchies is always starting at the top. This implementation is two part. The data is actually stored for the tree in more ways than one. And it is retrieved in more ways than one as well.
Storage
We store the hierarchy in two crucial ways. Since this is a full generic class we have to create boxing for the nodes. The nodes store information about the level parent and child relations. So, we can still start from the top of a tree and iterate down the nodes like normal. There's a new trick though for faster access. Sometimes, we need to access only data a few levels deep. Or all items on a particular level only. This is why the storage is actually storing nodes in arrays for each level as well. There is no distinction in this storage regarding parents and children, just all nodes on that level. There is one trick to this that was discovered by accident, but absolutely incredible. Children can actually be added first. The other one that was intentional is that an array of values can be converted into a hierarchy. My test project acftually converts an array of random integers into a hierarchy driven by digits where multiples of ten define the level. Looks like this:
1000
1100
1110
1111
The way this system is designed such generation is purely algorithmic or interface driven. Very cool and very powerful. May sound kinda lame but if you're into "fancy" code... this is right up your alley.
Retrieval
Since we've stored the data in this way, we can do some incredible things. One example, say we have a tree 5 levels deep, but the upper 4 levels just contain informational data not important to our actual processing. In most oldschool hierarchies this would still have to iterate all levels to get the bottom. Not here. We can pull just level 5 and not even acknowledge the parents even exist. Pretty cool huh? (Pretty simple too....) This structuring also gives a few benefits in speed. When retrieving nodes where the parent matching a condition(yes seriously) this is very easy and faster than it would normally be. If we already have a node we just access it's children which prevents us from having to navigate and compare the entire level. This is normally how we would do it, just felt it important to note this implementation does not exclude that.
The ways in which the data is accessed is always the fasted option to retrieve the value desired given the information supplied. In many cases faster than it would normally be from a normal hierarchy setup, but admittedly not all. It's functional and optimized in many ways, but as many practices teach us, functionality often sacrifices performance.
Code Snippet
Below is a quick snippet from the integer example mentioned: (There are other parts not visible here excluded to avoid confusion)
No, I am not kidding... It's that simple... And yes... this works flawlessly after 100s of tests.
Fun stuff right? =P
Saturday, May 4, 2013
Extension Method Insanity!!!
Extension methods are something I've known about for a while, but I have realized some new things in their practice recently that make them only that much more fascinating. The first thing is to understand exactly what they are. An extension method is "actually" a static method where the first argument designates it being available as an instance method. Here is a snippet of one for syntax.
The above snippet is a simple extension that can be called on ANY IEnumerable<T> to wrap it within a TSList object(this is just a thread safe list I created). Pretty cool, but doesn't do much. This is way I would use them mainly when I first discovered them. It works well to reduce code lines a good bit.
RECENT DISCOVERY #1
So, given that extension methods are trully static methods, we can actually call them on any field/property that matchs the first argument type. The value CAN be null!!! This works well in a few other cases. Here's another snippet of a simple use case.
So, the above extensions allow any event handler to be called using one line instead of the normal two to ensure it's not null. Yawn.... these two examples are really not that exciting.
RECENT DISCOVERY #2
Extensions can actually be used to do incredible things with reinstantiating objects, and thread safety during that change. In the snippet below I am taking an array, we don't need to know what kind, and resizing it while maintaining thread safety. There are other extension methods for pulling the values etc. while utilizing the same thread safety techniques.
The using brackets are due to a Smartlock class I use which is instantiated by the CreateLock EXTENSION method on objects with the ICollection interface. If you review this closely you should see that it pulses both the previous lock and the new lock when a new array is created. It does this to ensure that the other thread safe extensions will be pulsed if needed one way or another. (This has been tested for stability with success).
RECENT DISCOVERY #3
Ok, this is where things get a little more interesting and becomes that much more useful with all the above practices considered as well. Using polymorphing types extension methods can be used to change objects state and type in method chains. I don't have quite enough space here to really showcase the whole thing, but my posting isn't a tutorial anyway, just something to think about.
When looking at this one note that it doesn't always return the same object. It may return a "MultiSelector" or the argument passed. There are others to force return of the parent or a child etc etc. Methods like the first ToList example make this less fantastic, it just shows a more clear example of how extreme this can go. If you study up on interfaces and polymorphism you can do amazing things with extension methods. Like converting Enums to arrays. That one is really fun =)
The above snippet is a simple extension that can be called on ANY IEnumerable<T> to wrap it within a TSList object(this is just a thread safe list I created). Pretty cool, but doesn't do much. This is way I would use them mainly when I first discovered them. It works well to reduce code lines a good bit.
RECENT DISCOVERY #1
So, given that extension methods are trully static methods, we can actually call them on any field/property that matchs the first argument type. The value CAN be null!!! This works well in a few other cases. Here's another snippet of a simple use case.
So, the above extensions allow any event handler to be called using one line instead of the normal two to ensure it's not null. Yawn.... these two examples are really not that exciting.
RECENT DISCOVERY #2
Extensions can actually be used to do incredible things with reinstantiating objects, and thread safety during that change. In the snippet below I am taking an array, we don't need to know what kind, and resizing it while maintaining thread safety. There are other extension methods for pulling the values etc. while utilizing the same thread safety techniques.
The using brackets are due to a Smartlock class I use which is instantiated by the CreateLock EXTENSION method on objects with the ICollection interface. If you review this closely you should see that it pulses both the previous lock and the new lock when a new array is created. It does this to ensure that the other thread safe extensions will be pulsed if needed one way or another. (This has been tested for stability with success).
RECENT DISCOVERY #3
Ok, this is where things get a little more interesting and becomes that much more useful with all the above practices considered as well. Using polymorphing types extension methods can be used to change objects state and type in method chains. I don't have quite enough space here to really showcase the whole thing, but my posting isn't a tutorial anyway, just something to think about.
When looking at this one note that it doesn't always return the same object. It may return a "MultiSelector" or the argument passed. There are others to force return of the parent or a child etc etc. Methods like the first ToList example make this less fantastic, it just shows a more clear example of how extreme this can go. If you study up on interfaces and polymorphism you can do amazing things with extension methods. Like converting Enums to arrays. That one is really fun =)
Tuesday, October 16, 2012
Comparing RuneEngine to Unity3D - Test #1
Last night I performed my first official render comparison test with Unity3D's latest released version. Unity 4.0 may be a significantly different story, but I use what I have access to for now. I was unable to test against Unity Pro version which supports static instancing which may make a significant difference in the results, but here is my test case and what was found:
Test Case --
20,000 Cubes assigned to Diffuse texture
500 Point lights
0 moving objects
Deferred Rendering configured.
720x480 resolution
Physics Disabled
Input Disabled
Unity3D 3.5.6f4 --
Editor Crashed
Debug build Crashed
Release build Runs
FPS in Debug: n/a
FPS in Release: ~3-4
RuneEngine v2 --
Editor n/a
Debug Build Runs
Release Build Runs
FPS in Debug: not tested due to Unity3D results
FPS in Release: ~135-140 as Active Window ~35-40 as Inactive Window
Further tested to determine threshold for 30FPS with 500 deferred lights found that this can support up to 400,000 diffuse textured cubes in conjunction with 500 deferred lights non-moving while remaining above 30FPS.
Ok, a lot of abstract information. Well, for those who are not aware 28+ is a solid framerate to avoid jerkiness, but some video formats only push 24/25 FPS and remains unnoticed. Therefore RuneEngine is fully capable of pushing non-jerky frames in this test case and well beyond the specific test case while Unity is not.
My analysis from these results is as follows, the new Update Systems and the Rendering Pipeline are optimal, though are still receiving some improvements. However, Unity3d is likely to have some overhead that RuneEngine at this time has not accounted for. Such as the Quad tree sorting. In the basic scene all objects are rendered, but Unity would still be processing this sort. Depending on the nature of how they do this that could be the cause of what is seen. However, I must note that prior to the new Update System in RuneEngine my framerate results were rather similar to what is seen in Unity3D suggesting that this optimization may be the sole reason for the substantial performance difference.
Time will tell if this landslide performance difference continues to be so, but at the moment RuneEngine outperforms Unity3D by ~45-46 times...
I intend to do some further testing with this as time progresses, as well as confirming the performance of Unity3D Professional in comparison. For now this is a pretty big success for RuneEngine I believe.
Test Case --
20,000 Cubes assigned to Diffuse texture
500 Point lights
0 moving objects
Deferred Rendering configured.
720x480 resolution
Physics Disabled
Input Disabled
Unity3D 3.5.6f4 --
Editor Crashed
Debug build Crashed
Release build Runs
FPS in Debug: n/a
FPS in Release: ~3-4
RuneEngine v2 --
Editor n/a
Debug Build Runs
Release Build Runs
FPS in Debug: not tested due to Unity3D results
FPS in Release: ~135-140 as Active Window ~35-40 as Inactive Window
Further tested to determine threshold for 30FPS with 500 deferred lights found that this can support up to 400,000 diffuse textured cubes in conjunction with 500 deferred lights non-moving while remaining above 30FPS.
Ok, a lot of abstract information. Well, for those who are not aware 28+ is a solid framerate to avoid jerkiness, but some video formats only push 24/25 FPS and remains unnoticed. Therefore RuneEngine is fully capable of pushing non-jerky frames in this test case and well beyond the specific test case while Unity is not.
My analysis from these results is as follows, the new Update Systems and the Rendering Pipeline are optimal, though are still receiving some improvements. However, Unity3d is likely to have some overhead that RuneEngine at this time has not accounted for. Such as the Quad tree sorting. In the basic scene all objects are rendered, but Unity would still be processing this sort. Depending on the nature of how they do this that could be the cause of what is seen. However, I must note that prior to the new Update System in RuneEngine my framerate results were rather similar to what is seen in Unity3D suggesting that this optimization may be the sole reason for the substantial performance difference.
Time will tell if this landslide performance difference continues to be so, but at the moment RuneEngine outperforms Unity3D by ~45-46 times...
I intend to do some further testing with this as time progresses, as well as confirming the performance of Unity3D Professional in comparison. For now this is a pretty big success for RuneEngine I believe.
Thursday, September 27, 2012
RuneEngine V2's Flow System
I thought it would be kind of me to write a larger post about what this system is, how it will be used, and why it is a crucial part of the new RuneEngine V2 feature list.
If you're at all familiar with DirectShow basically imagine that, but re purposed for something... different. For those who don't know, essentially we're working in Blocks that I call the IFlowBlock interface. A block defines a procedure that handles a certain type of data. This part is somewhat different from what DirectShow does. The data is generic, where in DirectShow it's always a type of media passed by a buffer of bytes. RuneEngine's Flow system can pass more or less whatever you see fit. There are just a few rules. So, in DirectShow a sample or data is passed downstream all the way to the end, in every case. Well... Flow is not going to do the same necessarily. It can, but generally speaking the end block is going to be a renderer or finalizing state, so it should only be hit when the rest is complete. Flow data starts upstream and passes downstream until it hits a breaking condition. Data can be flagged for passthrough transit meaning, it's going all the way to the end or to a certain point before processing itself.
I could go on and on about how data moves and the different possibilities, but the key thing to understand about Flow vs DirectShow. DirectShow has rules, while Flow is more user defined. The both have Pins and "Filters" or "Blocks", even "Graphs", but ultimately they are completely different beasts.
Flow is not designed for processing video/image data, it is designed for processing some data in a specified sequence using a system of interchangeable blocks. Within the upcoming particle system this will be used by the ParticleController.
The blocks though will control a state of a particle. A particle graph may look rather complicated, but it houses some insane possibilities compared to other particle systems. And it does this without creating 20 emitters and controllers. Below is an example of what a simple particle system graph may look like:
This may not be the final example, but in this the idea is despite the appearance, when in one of the velocity blocks the object actually does not receive wind, it just uses velocity to update. Wind control happens after the velocity state is complete. So, for a certain time, a particle will be moving in a specified velocity, when reaching it's final output, it moves to wind control. Particles internally hold a velocity value, so the old velocity should be there still. Wind control is going to manipulate this. So, you would see the particle slow down and react to the wind. Imagine and explosion where the particles move out quickly then get carried away in the wind after. That is what this somewhat the idea of what this effect would accomplish.
This demonstrates that this system is more sequence driven. One block does not start til the following is complete, though that is not a forced behavior. It was the design. However, particles are small instances so the overall will almost seem like streaming update, it's not exactly. Now, in theory could you create a loop back effect to handling particles, without changing the underlying system? Absolutely!!! You could easily create a block that has a loop back output pin which send's items back to another block if the parameter to pass forward has not been met.
Given that this system is newish, and purpose is different than similar systems these are only speculations of ideas. The actual implementation and design of graphs will come after some testing. If I find some cool tricks to do with the FlowGraphs they will likely get shared as examples. =)
That's all I got for now though.
If you're at all familiar with DirectShow basically imagine that, but re purposed for something... different. For those who don't know, essentially we're working in Blocks that I call the IFlowBlock interface. A block defines a procedure that handles a certain type of data. This part is somewhat different from what DirectShow does. The data is generic, where in DirectShow it's always a type of media passed by a buffer of bytes. RuneEngine's Flow system can pass more or less whatever you see fit. There are just a few rules. So, in DirectShow a sample or data is passed downstream all the way to the end, in every case. Well... Flow is not going to do the same necessarily. It can, but generally speaking the end block is going to be a renderer or finalizing state, so it should only be hit when the rest is complete. Flow data starts upstream and passes downstream until it hits a breaking condition. Data can be flagged for passthrough transit meaning, it's going all the way to the end or to a certain point before processing itself.
I could go on and on about how data moves and the different possibilities, but the key thing to understand about Flow vs DirectShow. DirectShow has rules, while Flow is more user defined. The both have Pins and "Filters" or "Blocks", even "Graphs", but ultimately they are completely different beasts.
Flow is not designed for processing video/image data, it is designed for processing some data in a specified sequence using a system of interchangeable blocks. Within the upcoming particle system this will be used by the ParticleController.
The blocks though will control a state of a particle. A particle graph may look rather complicated, but it houses some insane possibilities compared to other particle systems. And it does this without creating 20 emitters and controllers. Below is an example of what a simple particle system graph may look like:
This demonstrates that this system is more sequence driven. One block does not start til the following is complete, though that is not a forced behavior. It was the design. However, particles are small instances so the overall will almost seem like streaming update, it's not exactly. Now, in theory could you create a loop back effect to handling particles, without changing the underlying system? Absolutely!!! You could easily create a block that has a loop back output pin which send's items back to another block if the parameter to pass forward has not been met.
Given that this system is newish, and purpose is different than similar systems these are only speculations of ideas. The actual implementation and design of graphs will come after some testing. If I find some cool tricks to do with the FlowGraphs they will likely get shared as examples. =)
That's all I got for now though.
Wednesday, September 19, 2012
New API objects for RuneEngine V2
Ok, the title of this post is almost misleading, this is more about the correction of some features that were slightly flawed in their design which have now been corrected. So I'm going to talk a little about it.
RuneEngine V2 has had a feature since the beginning referred to as a content reference system. The idea and purpose of this system is to be able to dynamically load content and handle such implementation as transparently as possible. Sadly, it only truly came to my attention last night it was not serving it's full purpose. It wasn't exactly wrong.. but it was defeating it's purpose in existing with the existing implementation.
Now some MAJOR changes were made, everything from the outside looks almost the same, except it is a little easier to use now. I should be taking that another notch further, but that's a completely different talk. So, what was changed? Here's a basic list from the far back perspective:
Removed--
IMaterialReference
IPostShaderReference
MaterialReferenceObject
PostShaderReferenceObject
MultimapTextureReferenceObject (rebuilt to interact with the TextureReferenceObject instead of separate)
Added--
IShaderReference (new material reference, but also serves as post shader reference)
RenderTargetReferenceObject( it was missing )
IContentContainer (this guy... does magic)
ShaderReferenceObject
Ok, that's about it. As you can see it's a pretty even exchange, but the added were completely missing or are more of a rename. The multimap texture reference and texture reference objects were completely unnecessary to be separate, I may have to do some wiggling to make it work, but it is done. Material references and post shading references were extremely redundant hence the spark to make these changes. In the process is how I found the issues.
IContentContainer was added to resolve the biggest of the issues as well as add a few functionalities that really make this feature sing. The issue was, the reference objects were calling load methods on instantiation in most cases, and if they didn't. The components were. Why not use a normal load call if I'm not going to use these for what they were added for right? So, first I stripped all calls that forced loading of the content references, then looked closely at what was missing. IContentContainer was what I came up with. This interface defines a collection of callbacks that the IContentReference objects call when they are loaded or unloaded. It has a method for making sure the reference is associated. That sort of thing.
One interface all it really took? Not a chance! Now, the IContentReference interface also has some added methods for working with the IContentContainer. Also, RuneContentManager was extended and improved to work more closely with this new interface as well.
So, rather than being super abstract about what happens let me just explain a few scenarios and how these changes have impacted them.
Scenario #1:
I'm building a game where the scene is rather simple, but the Content takes a long time to load. I do not want to make a super long load time when a level is loaded. But, I'm afraid to preload the content bogging down the CPU in the main menu. In this case I can preload the Scene files but not the content. Once the level is selected we can prioritize required content loading it first allowing the level to start with partial content and potentially even a partial scene. The reference objects allow this separation of load times, but not in a way that is forced by the engine. You can load it whenever you please.
Scenario #2:
I have a large collection of global resources that need to be loaded. I can put them in a global RuneContentManager and link it to my SceneGraphs allow the components to search through it's content as well. I can load all these global content items at startup, background or load screen. And pull them using the RuneContentManager linking systems. The amazing part here is that the contentReferences will manage unloading and reloading of those assets individually if they're not really being used. Also, the ContentReferences will pull more directly from the contentManagers now than before.
Scenario #3:
I'm building an Elder Scrolls Clone.... GG! The newest implementations actually allow full user control over when content is loaded and the IContentReference objects do all the tricky stuff. You can load a resource in anyway RuneEngine allows and the components and the IContentReferences will receive that callback letting all places that need to know, know that the resource is available and can be used now. No periodic or frame by frame update required. All of this leading to a fully seamless platform capability in a very simple way at that.
TextureContentComponent.AssetName = "assetName";
RuneContentManager.Load( "assetName" );
Done.. This like much of RuneEngine, is order independent. RuneEngine is unique in this element that I've spent a lot of time working around pre-requisite type issues. The game will not fail when resources are missing it'll just respond to it internally or with user defined code. Components can be added in any order. SceneNodes can be activated before or after components are added, it doesn't matter. The only real prequisite to any of RuneEngine is this line:
RuneManagementService.Startup();
I'm extremely enthusiastic lately watching all of these architectural designs in the engine being realized. So pardon me if I seem ranty.
Anyways, happy coding.
RuneEngine V2 has had a feature since the beginning referred to as a content reference system. The idea and purpose of this system is to be able to dynamically load content and handle such implementation as transparently as possible. Sadly, it only truly came to my attention last night it was not serving it's full purpose. It wasn't exactly wrong.. but it was defeating it's purpose in existing with the existing implementation.
Now some MAJOR changes were made, everything from the outside looks almost the same, except it is a little easier to use now. I should be taking that another notch further, but that's a completely different talk. So, what was changed? Here's a basic list from the far back perspective:
Removed--
IMaterialReference
IPostShaderReference
MaterialReferenceObject
PostShaderReferenceObject
MultimapTextureReferenceObject (rebuilt to interact with the TextureReferenceObject instead of separate)
Added--
IShaderReference (new material reference, but also serves as post shader reference)
RenderTargetReferenceObject( it was missing )
IContentContainer (this guy... does magic)
ShaderReferenceObject
Ok, that's about it. As you can see it's a pretty even exchange, but the added were completely missing or are more of a rename. The multimap texture reference and texture reference objects were completely unnecessary to be separate, I may have to do some wiggling to make it work, but it is done. Material references and post shading references were extremely redundant hence the spark to make these changes. In the process is how I found the issues.
IContentContainer was added to resolve the biggest of the issues as well as add a few functionalities that really make this feature sing. The issue was, the reference objects were calling load methods on instantiation in most cases, and if they didn't. The components were. Why not use a normal load call if I'm not going to use these for what they were added for right? So, first I stripped all calls that forced loading of the content references, then looked closely at what was missing. IContentContainer was what I came up with. This interface defines a collection of callbacks that the IContentReference objects call when they are loaded or unloaded. It has a method for making sure the reference is associated. That sort of thing.
One interface all it really took? Not a chance! Now, the IContentReference interface also has some added methods for working with the IContentContainer. Also, RuneContentManager was extended and improved to work more closely with this new interface as well.
So, rather than being super abstract about what happens let me just explain a few scenarios and how these changes have impacted them.
Scenario #1:
I'm building a game where the scene is rather simple, but the Content takes a long time to load. I do not want to make a super long load time when a level is loaded. But, I'm afraid to preload the content bogging down the CPU in the main menu. In this case I can preload the Scene files but not the content. Once the level is selected we can prioritize required content loading it first allowing the level to start with partial content and potentially even a partial scene. The reference objects allow this separation of load times, but not in a way that is forced by the engine. You can load it whenever you please.
Scenario #2:
I have a large collection of global resources that need to be loaded. I can put them in a global RuneContentManager and link it to my SceneGraphs allow the components to search through it's content as well. I can load all these global content items at startup, background or load screen. And pull them using the RuneContentManager linking systems. The amazing part here is that the contentReferences will manage unloading and reloading of those assets individually if they're not really being used. Also, the ContentReferences will pull more directly from the contentManagers now than before.
Scenario #3:
I'm building an Elder Scrolls Clone.... GG! The newest implementations actually allow full user control over when content is loaded and the IContentReference objects do all the tricky stuff. You can load a resource in anyway RuneEngine allows and the components and the IContentReferences will receive that callback letting all places that need to know, know that the resource is available and can be used now. No periodic or frame by frame update required. All of this leading to a fully seamless platform capability in a very simple way at that.
TextureContentComponent.AssetName = "assetName";
RuneContentManager.Load( "assetName" );
Done.. This like much of RuneEngine, is order independent. RuneEngine is unique in this element that I've spent a lot of time working around pre-requisite type issues. The game will not fail when resources are missing it'll just respond to it internally or with user defined code. Components can be added in any order. SceneNodes can be activated before or after components are added, it doesn't matter. The only real prequisite to any of RuneEngine is this line:
RuneManagementService.Startup();
I'm extremely enthusiastic lately watching all of these architectural designs in the engine being realized. So pardon me if I seem ranty.
Anyways, happy coding.
Wednesday, September 5, 2012
Thoughts after the RuneEngine V2 Code Review
Last night I spent a lot of time going through the RuneEngine V2 source code, updating documentation and reviewing the source for poor organization and garbage code left behind. This is a good practice to act on with some regularity, but isn't always necessary.
Going through this I had quite a few thoughts. Absolutely none of them involved considering change. I found that for 210 code files currently they all seem to be in pretty good order and have great readability. But that is aside from the point. The real point is an issue of mentality gained from reviewing the source.
I have spent a lot of time over the past few months procrastinating about not working on the engine. I am getting heavy back in development with it so I decided a cleanup pass was in my best interest. I had been procrastinating because of "how much is left." Well, this review showed me quite a it in the direction of how inaccurate that really is. There are still plenty of unfinished areas and new features that need implementation, but reminding myself that there are systems and features already implemented that push into professional grade quality affected my opinion of where I am at. It would appear that by the end of the week I could have any loose ends taken care of and begin development of new features next week. By new features I specifically mean building the editor.
Now, I've spoken here about the goals of the engine as far as features, but here's a list of what I found that gives me such a confident outlook on the status.
- Deferred Rendering
- Post Processing System
- Dynamic Content system
- Custom material format
- User defined geometry system capable of working to the extent of a simple modeling utility
- Extendable file IO system
- Extendable XNA content resource extensibility (This is small, but huge at the same time, specifically it is built that shaders with custom structs used can be applied via the material file format with some extension to this area)
- Input System, with plugin capabilities
- Updateless and per-frame draw call removed system (huge optimization)
- Custom SpriteBatch which renders into a deferred scene with textures that support the multiple channels.
- Architecture in a way that almost every part of the engine is 100% self reliant.
- Low-Level and High-Level implementations for most features
As a foundation, RuneEngine V2 has all the necessary pieces to be something really impressive. Nearly the entire engine is designed for extendability. This design is going to make moving forward significantly easier than it was in past iterations.
Very soon, after the loose ends are tied up I will be making a post here and on the RuneEngine V2 facebook page. This post is going to be a demonstration of development with RuneEngine V2. I want to showcase, how some of this stuff is compartmentalized and how, as a coder using it, things are going to be done. In many cases a test project only consists of a few RuneEngine lines of code. If it's much more then it is due to setting up parameters of objects for a less "defaulted" test.
Anyways, happy coding.
Going through this I had quite a few thoughts. Absolutely none of them involved considering change. I found that for 210 code files currently they all seem to be in pretty good order and have great readability. But that is aside from the point. The real point is an issue of mentality gained from reviewing the source.
I have spent a lot of time over the past few months procrastinating about not working on the engine. I am getting heavy back in development with it so I decided a cleanup pass was in my best interest. I had been procrastinating because of "how much is left." Well, this review showed me quite a it in the direction of how inaccurate that really is. There are still plenty of unfinished areas and new features that need implementation, but reminding myself that there are systems and features already implemented that push into professional grade quality affected my opinion of where I am at. It would appear that by the end of the week I could have any loose ends taken care of and begin development of new features next week. By new features I specifically mean building the editor.
Now, I've spoken here about the goals of the engine as far as features, but here's a list of what I found that gives me such a confident outlook on the status.
- Deferred Rendering
- Post Processing System
- Dynamic Content system
- Custom material format
- User defined geometry system capable of working to the extent of a simple modeling utility
- Extendable file IO system
- Extendable XNA content resource extensibility (This is small, but huge at the same time, specifically it is built that shaders with custom structs used can be applied via the material file format with some extension to this area)
- Input System, with plugin capabilities
- Updateless and per-frame draw call removed system (huge optimization)
- Custom SpriteBatch which renders into a deferred scene with textures that support the multiple channels.
- Architecture in a way that almost every part of the engine is 100% self reliant.
- Low-Level and High-Level implementations for most features
As a foundation, RuneEngine V2 has all the necessary pieces to be something really impressive. Nearly the entire engine is designed for extendability. This design is going to make moving forward significantly easier than it was in past iterations.
Very soon, after the loose ends are tied up I will be making a post here and on the RuneEngine V2 facebook page. This post is going to be a demonstration of development with RuneEngine V2. I want to showcase, how some of this stuff is compartmentalized and how, as a coder using it, things are going to be done. In many cases a test project only consists of a few RuneEngine lines of code. If it's much more then it is due to setting up parameters of objects for a less "defaulted" test.
Anyways, happy coding.
Subscribe to:
Posts (Atom)





