JeffR You have to advertise your patreon on the frontpage or so, this way nobody will see it. @All others You should consider donating a bit, even if its just a symbolic amount, since Jeff is basically our main developer and repo maintainer.
Firstly: don't pick up any seasonal sicknesses. I had one at the beginning of last week, and while I got better in time for thanksgiving, it still sucked to largely be lying around feeling gross for a few days. Definitely hampers productivity!
But I'm obviously better now, so we get to talk about all the cool crap that's been getting worked on!
First and foremost, I sat down and spent some time on a refactor of the Menubars and popup menus. It's PR'd and while I've spotted a few minor issues I need to add to the PR before I get it merged in, largely it's WILDLY superior to the old stuff. This is in part due to how much baggage was involved with it. See, back in the old T3D days when it was Windows-only, it hooked the menubar and popup menus through the actual Windows platform stuff. That was neat and all, but obviously when Linux and then Mac support cam along, it meant that that was no longer acceptable.
So, what we did was implement a "SDL Platform" version, that wrappered alongside the windows platform-specific stuff but in a generic way. This basically became the standard and the only thing we used, but it still meant there was all that old crap lying around. So this meant lots of weird stuff was happening, like the popup menus associated to menubar entries were actually completely distinct objects and classes and rendered differently to popup menus that happened when you right-clicked on stuff. That meant things like submenus on right-click popups didn't work(because it wasn't implemented there) along with a litany of duplicated, redundant, spaghettified codestuffs.
So I went in there with a machete and cut out i believe it was 8 unneeded files, and collapsed all the functionality into one common popup menu class, the menubar class which tracks popup menus related to it, and the actual rendering of said popups. It's all way more standard and cleaner now.
Also helped Jeff H. get the Torquescript interpreter wrapped up with the testing and fixes and seems pretty stable now, so that's been PR'd as well.
Beyond that, got most of the Custom Shader Feature implement wrapped up. Still a few bits and bobs to sort out, but the core implement works. For example:
That uses our prior Flat Color Feature example, with a field added to shapebase objects to pass along an override color into the shader. As you can see, the passed in color not only overrides as expected, but operates nicely on a per-instance basis.
The remaining work on that basically is getting non-shared material instances for static shapes - in an effort to optimize memory usage, the engine current makes it so TSStatics never have unique instances of their materials. They always share, meaning the per-instance override doesn't work. As well as implementing the connector logic to bridge data between vertex shaders and pixel shaders.
Once that's done, I've already promised @
Skipper to help build out an example case where you can control the invisibility amount via a CSF, allowing you to fade the shape out with a smooth alpha value instead of the dither effect. We figured that'd be a pretty slick example of interesting, special behavior you can get working with that sort of thing.
Beyond that, I've done more work on the Asset Browser, trying to get the basic implementation of it wrapped up and ready for the prime-time usage.
You've seen me do the drag-and-drop import before, but now we can do interesting stuff like re-importing, finding missing files and the like. I have a video where I show that off and explain it a bit better:
And then I had a followup when I got asset dependencies working so that materials correctly refresh when the re-import happens:
The todo on the asset browser for the CORE implementation is getting shape animations importing properly and hooking to shapes as dependencies(that way if the animations change, the shapes will auto-reload with those changes, as well as always loading the animation assets before the shape itself, so there's no load-order/file finding confusion) as well as some general management logic for tracking inter-module dependencies and the like. After that, I'm going to have the various game classes accept assets alongside straight file paths, so either work as a bridging of behaviors.
There's a fairly long list of additional behaviors the AB will do, but the above is what's considered minimum.
Another experiment I did related to a discussion we had pertaining originally to post effects load order and how to manage that better(because right now, it's pretty well a mess), but then it compounded into a method to much better control and understand the general 'flow' of the rendering.
You see, the way T3D renders right now is that the main thread trips a update event signal, which the Canvas is set to. When that signal triggers, the Canvas handles the event, and triggers a refresh. This goes and updates all it's child controls, which generally includes either a guiTSControl or guiEditTSCtrl. These, during their respective render functions, do a bunch of logic to actually set up and initiate the rendering of the scene, then call up to their parent, which does more of the work, and eventually finally ending out into the scene manager where the objects are finally told to render, which passes them into the render bins, where we process them. Then we do our rendering to the GBuffer targets, after which we do our lighting and post effects, Finally resolving the image back to the main display target the GUI control displays.
If you've ever bothered trying to poke through the actual path the renderer takes, it's pretty well a giant spaghetti western with fewer hats and horses. I dealt with it when trying to get the reflection probes to bake and I did some streamlining work to collapse all that logic into a single RenderFrame() function that triggers the majority of the work and then outputs to a given Render Target.
So the idea became thus: Make the rendering camera-based. Obviously a scene can't render without a camera anyways, so instead of doing your whole render setup and getting the camera somwhere in the middle of your whole render-mess. you have the canvas's render call tell the cameras to render from their perspective. The cameras do the render work in a much more localized, streamlined way, and output that result to a render target. The GUI control that actually displays will ONLY display the resulting render target.
This comes with a TON of design advantages, which I'll enumerate below, but first, a nifty video of a very hacky initial pass at this setup:
Now, obviously it's not rendering right. There's a good number of bits and bobs not fully implemented there, so more work obviously needs to be done, but that video already displays something really cool that this approach enables: Resolution scaling.
See, rendering as-is is FULLY based on the set resolution of the canvas. When you change the options for the display resolution you're dictating the canvas size. While it can be stretched to fill the screen or whatnot, ultimately the display resolution is limited to the capabilities of the monitor. If you've got a 1080 monitor, you can't set the window to be 4k. That sucks for a number of reasons, but there's other things to it too.
What happens with the new camera-based render path, though is because we output to a floating render target the GUI simply dispays, it's completely detached from whatever the window size is.As you can see in the video, though the window is mostly my full screen(just shy of 1080 resolution), I can then change the resolution scaling the camera's render target outputs as, allowing me to scale down, for a lower display resolution, which runs dramatically faster, up to 4 times that resolution - 4k. I even accidentally set it to 8k once, but that tanked my framerate into slideshow land, haha.
One of the novel advancements newer games have been supporting is 'Resolution Scaling' as a preference setting. This lets the user control the actual processed number of pixels, distinct from the actual window/monitor resolution, usually anywhere between 50% to 200% of the window resolution. So, if you're having problems running the game, you can lower the resolution scaling without shrinking the window, and you'll get better performance. If you blow way past the performance requirements, you can sample above the window size, causing super-sampling, which actually often better reduces aliasing and blurriness of the scene without needing to resort to Anti-Aliasing effects and the like.
Further, from there, some games have implemented Dynamic Resolution Scaling - an option where, if enabled, the game tracks the per-frame performance and if it falls below a certain mark, it will automatically reduce the resolution scaling slightly in the background for you, which improves performance. This is a subtle way to get a performance increase to hit a framerate target in especially complex scenes. Then when the complexity dials back - say your nuke finishes exploding - the frames are taking less time, so it scales back up. It can even be set to super sample in particularly cheap scenes so things look nice if not much is going on.
So that's something we can very easily support with the new camera-based render path setup which is great for performance AND looking even better. But that's not all it'll allow:
MUCH cleaner render pipeline, which is GUI control agnostic. It'll be much easier to trace through the code and understand what's happening
FAR superior control of when things happen in the process, allowing easier expansion of future functionality, render modes, etc
It'll let us clear out a whole lot of extraneous, old or unnecessary code. Also given that we'll make fewer hops and function calls and jump-arounds, it's better for memory thrashing and should all around help performance. Even if not a large jump in framerate, it should help performance be stable and assist in better frame pacing
Opening up much better control of what post effects are active and when. By associating post effects to cameras, it not only lets us dictate what post effects are active and when much more flexibly than a static per-level file, but lets us do unique, specific behaviors per-camera. Which leads into...
Multiple camera display support. This has a wide ranging impact, but it'll let us easily do things like: Multiple viewports. Which is good for editors as well as split-screen local play. Because the cameras output a render target, This can be displayed onto materials directly, allowing stuff like monitors showing security camera feeds. Combined with the per-camera post process controls, it means that you could do stuff like a static post process effect on the security camera, but not on the player's main view. 3d scopes and other interesting mixed-view displays.
Better control of scoping and zoning. Because we can better assume the camera's association to the rendering throughput(after all, it's what's doing the rendering in the first place) we can better tie zoning and scoping logic directly to the cameras, so only things relevent to a camera is ghosted, scoped and rendered. Keeping networking AND rendering saner.
Looking forward to the future, having a much simpler and cleaner render path means that expanding and refactoring the GFX renderer for new features will be MUCH easier to implement if we have to touch fewer places in the engine to make it happen.
So yeah, that'll be a preeeetty big deal. I'll be sure to keep everyone posted about how that's going, because honestly, it's pretty freaking cool
I know for a fact there's some other things that were worked on, but it's already 4am and I'm starting to have trouble, haha, so I'll likely expand upon this post in the morning.
Hopefully all of you had a wonderful Thanksgiving, or at least a most excellent Thursday
Smart idea with the resolution scaling, right now if you want a fullscreen resolution smaller than your monitor (for fps-quality trade-off) the GPU/Windows has to change the whole desktop/monitor - cue black flashing screen for 2 seconds as it rescales.
Julius, yeah, it should make it appreciably easier. In addition to that, I've already got a plan for VRCameraComponent and VRControllerComponents to make it even easier to just drop everything in and go with VR setup.
Is there some aspect of the current functionality that's not working for you? I know controllers aren't working yet, though the component above will resolve that.