Author Topic: Mods and code changes.  (Read 10975 times)

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Mods and code changes.
« on: February 12, 2016, 03:20:12 pm »
Hi guys.
I'm interested in making some mods, and it'll need some code changes to support them.

There are easy things like adding buildable corridors in the basescape, and adding some new rooms and vehicles, but actually I'm thinking about replacing the basescape renderer first.

I downloaded the source last night and Codewise it's not too big a task. Its an alternate BaseView class. I'm not sure if BasescapeState will have to change, beyond switching to instantiate a particular BaseView - The discussion on if this should be done in the CTOR, by injection or by factory injection is irrelevant right now - I'm just trying to learn about the project to start with.

What is the process for a change like this?
e.g. If I made BaseView an abstract class and moved the current implementation into a derived BaseViewReference class and then derived my own BaseView subclass with alternate rendering - is this the sort of change I submit and post an FYI thread about or is it the sort of thing I should start a discussion thread about first ?

The more flexible base renderer will help me support mods I'm thinking of - Garages & LandRangers, larger bases, overground bases, bases with unbuildable areas around them - fields, caves, coastlines, or civilian structures.

Offline yrizoud

  • Commander
  • *****
  • Posts: 1014
    • View Profile
Re: Mods and code changes.
« Reply #1 on: February 12, 2016, 03:38:28 pm »
In my opinion, modifying the class directly will make it easier for you to integrate future changes from the main development.

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #2 on: February 12, 2016, 04:10:51 pm »
OK, I'll think that through.
You are right - I do actually want to preserve BaseView to ensure integrating changes is easier. Mostly this is so that I can support an alternate render option at runtime.

I think my philosophy is that it should be divided into interface and implementation in the main development. That would let me make any changes without preventing integration from the main development.
"open to extension and closed to modification" style.
But that's probably a larger discussion.

I'll see if I get time to sketch something out and post back what I find.

Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11485
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Mods and code changes.
« Reply #3 on: February 12, 2016, 05:40:11 pm »
I just wanna say I'm extremely excited about this.

TBH my mod really needs two-level bases: aboveground and underground, with some sort of a switch to click between them. (I mean the basescape, not battlescape - it'll simply have more levels, with an aboveground part.) But even an ability to define if a new base is aboveground or underground would be something.

I wonder if I can get there with your help. :)

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #4 on: February 12, 2016, 06:58:49 pm »

If you want bases on two floors ... there is more work involved.
I don't know if you'd need BasescapeState to have to BaseView objects of if you would repopulate a single BaseView object when the floor changed. I'd have to look at both to comment on which is more suitable. I like the idea of displaying several floors in a single BaseView object because of encapsulation.

Either way, the Base will have to count both floors for Base Defence missions, for iterating facilities, for BaseInfo, and for costs too. Base also hardcodes the base size, and BaseFacility only stores X,Y coords. You'd also have to come up with a solution for the savegame... All in all There are quite a lot of places you'll have to touch to get it working but it'd be a nice touch to have more base flexibility - especially for other mod authors. I only downloaded the project last night and was drunk at the time so that probably isn't an exhaustive list of what you'd have to change.

You also might want to restrict some facilities i.e. Hangers and Radar on the above ground floor only. Alien Containment must be underground... everything else can be freely placed. That sort of thing. This will need additional parameters for facilities.

Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11485
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Mods and code changes.
« Reply #5 on: February 13, 2016, 09:35:15 am »
If you want bases on two floors ... there is more work involved.

Yeah, I know this request was pretty kamikaze on my part. :P It's just something I have been aiming at it for almost two years (as evidenced here), so I thought I'd ask.

Let me explain why: I am making a big mod where X-Com starts way more humbly. Ideally, you'd start with a government base that consists of a few surface buildings (HQ, barracks, landing pad). With time, you get access to underground versions of the facilities (vanilla ones) which you can build on the switchable second layer.

Due to logical reasons, underground buildings can only be built with connection to the lift (like in vanilla), while surface buildings can be built anywhere.

You also might want to restrict some facilities i.e. Hangers and Radar on the above ground floor only. Alien Containment must be underground... everything else can be freely placed. That sort of thing. This will need additional parameters for facilities.

Yeah, as I mentioned above, all facilities are either above- or belowground, though many exist in both versions.

So, I know it's a big task and it's probably not why you started this thread, but if you feel like giving it a try... Well, just remember about it please :)

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #6 on: February 16, 2016, 11:56:50 am »

Hey Solarius
Sorry for the delay. I had a couple of problems with lib dependencies.  All sorted now and I started a new BaseView renderer.

In my first hack I'm using a subclass of BaseView so I can substitute it in with a one-line change in BasescapeState, and I'll revisit the interface and maybe use a factory constructor or something further down the line. The architecture will be apparent once the implementation is done.

As an interim update,
The SDL_Surface blit doesn't support scale (its crop only) so in order to get variable base sizes, scroll, zoom and multiple floor support into the Basescape view I'm going to bind the surface to an OpenGL render context and reimplement the blit to draw quads.
It's more involved than I'd expected but it shouldn't be too much work, gains tons of flexibility, and we should be able to query the system and push a texture atlas to VRAM which will reduce render time.

Longer term I'd want to refactor that to vertex buffer objects instead of manually drawing quads. It'll drop the render time to basically nothing push everything onto the GPU. I think thats all in the spec for OpenGL1.2 and 1.2ES so should be supported on every target platform, but I can confirm that and we should be able to detect for hardware support and add a toggle for it all in the options screen anyway.

It'll be a couple of days before I'm back at keyboard, so I'll think it over a bit more and try and throw something together when I can.

Offline yrizoud

  • Commander
  • *****
  • Posts: 1014
    • View Profile
Re: Mods and code changes.
« Reply #7 on: February 16, 2016, 03:51:01 pm »
This sounds very ambitious. Be careful if there are any 8-bit (paletted) surfaces, you aren't likely to find 8-bit textures on modern graphic cards.

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #8 on: February 16, 2016, 07:02:30 pm »
Yeah... The 8-bit thing is a real pain.

There is an 8-bit option in OpenGL EXT that will probably work, but I might want to render everything to an RGB A framebuffer than then out to an 8Bit image after all compositing is done. I've never tried it but the API documentation should be sufficient.

If not then I'll have to write a supersampling fragment shader that reduces RGBA-to-CLUT. It's not rocket surgery but will do the trick. There are probably algorithms online for dither patterns and stuff so we can pick one that matches the art style as best as possible.

It's also just possible that I can instantiate 32bit buffers for the Basescape, and neatly sidestep this sort of thing. That might be really worth considering, although it will make the basecape stand out aesthetically.

I'm planning to keep the ambition and scope down by not adding any features - just reimplementing the renderer and supporting scroll/zoom. That should make it really easy to focus on the task at hand and then all the other stuff - overground, building restrictions, national perks, roads, corridors, garages, cars, civilian buildings, police, hospital, firing range ... etc... can all wait and be done in their own separate iterations.
My goal here is just to provide support for them, not implement all the new stuff in one go, so that I can write an "Extended Bases" mod one building at a time.


Offline Solarius Scorch

  • Global Moderator
  • Commander
  • *****
  • Posts: 11485
  • WE MUST DISSENT
    • View Profile
    • Nocturmal Productions modding studio website
Re: Mods and code changes.
« Reply #9 on: February 16, 2016, 08:01:42 pm »
Many thanks for your efforts, Roger. Much appreciated!

Offline Yankes

  • Commander
  • *****
  • Posts: 3217
    • View Profile
Re: Mods and code changes.
« Reply #10 on: February 16, 2016, 09:06:44 pm »
Yeah... The 8-bit thing is a real pain.

There is an 8-bit option in OpenGL EXT that will probably work, but I might want to render everything to an RGB A framebuffer than then out to an 8Bit image after all compositing is done. I've never tried it but the API documentation should be sufficient.

If not then I'll have to write a supersampling fragment shader that reduces RGBA-to-CLUT. It's not rocket surgery but will do the trick. There are probably algorithms online for dither patterns and stuff so we can pick one that matches the art style as best as possible.

It's also just possible that I can instantiate 32bit buffers for the Basescape, and neatly sidestep this sort of thing. That might be really worth considering, although it will make the basecape stand out aesthetically.

I'm planning to keep the ambition and scope down by not adding any features - just reimplementing the renderer and supporting scroll/zoom. That should make it really easy to focus on the task at hand and then all the other stuff - overground, building restrictions, national perks, roads, corridors, garages, cars, civilian buildings, police, hospital, firing range ... etc... can all wait and be done in their own separate iterations.
My goal here is just to provide support for them, not implement all the new stuff in one go, so that I can write an "Extended Bases" mod one building at a time.
As coder I enjoy 8-bit palettes but to do that you need stop consider it as color but as "state". Look on globe or face recoloring. Simple but powerful.

And for 32-bit you should checkout https://github.com/AndO3131/OpenXcom that already switch to 32bit.

Offline SupSuper

  • Lazy Developer
  • Administrator
  • Commander
  • *****
  • Posts: 2161
    • View Profile
Re: Mods and code changes.
« Reply #11 on: February 16, 2016, 11:56:58 pm »
You can use SDL_gfx for manipulating surfaces like you would in hardware. It just won't look very pretty, but then you're never gonna get pretty transformations with 8-bit pixel graphics. :P

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #12 on: February 17, 2016, 02:27:28 am »
Cool
Doing everything in 32 bit is going to be easier.

If AndO3131 has made the switch to 32-bit, then i'll grab and merge. It'll save me some time and generally make everything easier than wrapping everything in a 32-to-8 and 8-to-32 pipeline.

I'd probably recommend that the project switched to 32bit though for all assets and internals though. You can render with a 256 CLUT post process to capture a retro look and feel, but I can't imagine a reason to work in 8bit.


Offline yrizoud

  • Commander
  • *****
  • Posts: 1014
    • View Profile
Re: Mods and code changes.
« Reply #13 on: February 17, 2016, 03:35:23 am »
I can't imagine a reason to work in 8bit.
I'll give you a few that the game is currently using :
1) Color cycling
2) Images that look different depending on which screen displays them
3) A shading of darkness/depth that is very different from RGB fade-to-color - and impossible to generalize to the entire RGB color space.
If you don't know about them, your attempts to switch to RGBA are very naive. Sorry to be blunt, but when I see you talk about "RGBA to CLUT" conversion, it looks like you have no idea what you're talking about.
If you want to learn a bit, here's a long thread about experiments for mimic'ing the UFO/TFTD shading. https://openxcom.org/forum/index.php/topic,896.0.html
I know there was previous discussions about 24/32bit graphics, but I can't find seem to find them.

Offline RogerBennett

  • Sergeant
  • **
  • Posts: 16
    • View Profile
Re: Mods and code changes.
« Reply #14 on: February 17, 2016, 01:29:55 pm »

Sorry if I came off as naive, I'm pretty sure from a technical perspective the 8-to-32 and 32-to-8 colourspace conversion is easy on the GPU.

What I mean by RGB-to-CLUT is this:
A far as I can tell an RGB to CLUT fragment shader is reasonably simple. It's a reverse lookup which is extra work, but GPU time is cheap.
Pass in the colour lookup table to the shader as a uniform array of vec with 256 elements. You need to supersample the frame buffer to get a colour area around each pixel. You could used fixed pattern or random sampling depending on how you wanted to dither. Then you can iterate the fragment and pick an indexed colour, again there are a couple of popular options here. The result is a 32bit source image rendered to an 8-bit framebuffer with an 8bit palette.  OpenGL looks like it has a few eight bit pixel formats and the 8-bit unsigned one should be the same as the SDL_Surface pixel data.

You can pass in a second uniform parameter containing a second output palette if you want to support palette cycling. It will likely produce some artifacts if you don't mask out non-cycling areas of the original palette and are doing complex shading, but I wouldn't expect nearest-neighbour sampling to have any problems which would be a good starting point and retain compatibility with all the existing assets.
I used RGB-CLUT as a shorthand, (for the operation performed as a postprocess in the fragment shader) sorry if I didn't make that clear.

I've not written the code yet so I've not worked through all the problems, but that process can be used to output a 32-bit render pipeline onto an 8-bit render target. With the option of reading 8 or 32 bit source assets which is good for content creators.
It's the same process that photoshop goes through to palletize an image, except you can do it in milliseconds on the GPU. I'm sorry if this comes across as having no idea what I'm talking about, I am still getting to grips with the SDL and OpenGL terminology.

8-bit to RGB
Likewise going the other way is trivial since you can use the lookup table, and rendering an 8-bit source to a 32-bit framebuffer just needs the same CLUT data. You'd create a texture buffer with an 8-bit unsigned pixelformat and pass the CLUT as an uniform vec array to the fragment shader, outputting to a 32-bit RGBA target.
You could convert every asset as it loads, saving it in a 32 bit surface or more likely just pushing it to VRAM to use later. (more on this later, you'd be using the gl ETX methods from SDL_Opengl.h so I'd want to check what the compatibility is on those)

After that you can perform all render steps in 32Bit, and present back to an indexed palette using a the post-process fragment shader above.

The shading differences between RGB and CLUT are irrelevant if you maintain 8-bit source images and render to an 8-bit palette. With nearest neighbour filtering the first iteration would look pixel-perfect to the original.
But doing so opens up the option of additional effects e.g. scale/rotate/shear that just aren't possible (read impractical and slow) with 8-bit indexed surfaces. My example being the baseview, where a 32-bit render pipeline would allow easy scroll/scale to support extended base sizes and configurations.

It's also likely to be faster to draw to use 32-bit on a lot of modern platforms. Speed isn't an issue asn OpenXCom isn't really bottlenecked, but keeping things fast is always good.

I'm aware of the colour cycling that XCom uses, but it's not too difficult to emulate the effects in native 32bit. XCom seems to rarely, if ever, rely on complex cycling patterns. There are a few flashes and simple effects that are as trivial in 32bit as they are with a colour look up table.
Given that you can still cycle palettes with a 32-bit render pipeline as you are rendering to a colour look up table, palette cycling could still be supported. My opening gambit is the baseview, where complex palette cycling isn't required and that will provide a platform to iron out the problems.

Given memory capacity has increased by several orders of magnitude since the mid-90s, wanting images to look different on different screens is likely to be irrelevant as you can have a duplicate of each image customised for each context.
But given I think I can still colour cycle with a 32-bit render pipeline during the CLUT post-process step, we would have the option of multiple assets, or single assets with cook-time, load-time or runtime recolourisation. You've got the option of using original source assets but could load new 32-bit assets for new content without breaking the pipeline.

Again, this is all speculative - I've not written the code yet.
Given you can do palette cycling, and a number of other effects, in the fragment shader and we have essentially no memory limit (compared to the mid-90s) There doesn't seem to be a (technical) advantage to the eight bit render pipeline, and some reasons not to.
32 bit rendering adds up more options in the baseview, you could improve the geoscape a lot, and there are loads of battlescape options - smoke/fog for example, and the ability to have a lot more assets on screen - as well as zoom levels could be tried.

Thanks for the link to the topic about shading discussions. I think there are a couple of good points raised there and while they are mostly concerned with the battlescape, a lot of the same things apply. I'll consider those and see if they can be addressed.

Other problems I can see are hardware compatibility. The SDL_OpenGL header file looks like some of the framebuffer stuff uses the EXT methods which are old. You might need two versions of the renderer to support both generations of hardware, although TBH I suspect there isn't a target platform that doesn't support all the features we'd need but I just don't know.

I'm happy to have a discussion on any level about the render pipeline changes and requirements, and have had a little experience both with index'd palettes and modern GPU programming.