Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interior lighting to stations #5823

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

tatjam
Copy link

@tatjam tatjam commented Apr 15, 2024

Makes ships that are inside stations (as defined on the model file using tags and a series of new parser commands) have increased ambient light and reduced direct lightning, fixing the issue of black ships on eclipsed stations (Issue #4399).

TO-DO:

  • Working interiors
  • Make all stations compatible with the code
  • Adjustable lighting colors with some kind of station config?
  • Make it work with the ship cockpit and other bodies that may be found inside stations

Demo: https://www.youtube.com/watch?v=D56iUkvpOac

@impaktor
Copy link
Member

Adjustable lighting colors with some kind of station config?

Stations in Haber space are blood red.

@fluffyfreak
Copy link
Contributor

That's an interesting approach, another might be to gather the nearest 3 or 4 lights from within the station and apply them as light sources to the ship. However I'm not sure if "lights" like that are defined in the model or if that's something that could be done later.

@nozmajner
Copy link
Contributor

There are no lights in the model. I can add them if needed. Not sure if Blender lights are exported to collada, with their settings. Or they could be tags.

@tatjam
Copy link
Author

tatjam commented Apr 17, 2024

Love the idea, that way it's more in-line with the new PBR renderer idea. Guess adjusting ambient lighting is useful even then, if no dynamical env-maps are used.

Even if actual lights are used I guess the interior checking is important, to prevent outside ships from being lit. (Otherwise shadow casting is needed, or really thick exterior walls).

@nozmajner
Copy link
Contributor

I'd suggest first doing the ambient light only, get it to merge, and then you can think about the next step, or if you want to do other features instead. No need to build a huge PR, especially when you are still getting your feet wet. This is a free-time passion project after all, avoid burnout and such!

@Web-eWorks Web-eWorks self-requested a review April 19, 2024 16:02
@tatjam
Copy link
Author

tatjam commented Apr 22, 2024

If I'm not mistaken all stations use either hub A o B so that should be done. Going to quickly find a "A" type station to see if it works

@nozmajner
Copy link
Contributor

Yes, all stations use those two hubs.

@impaktor
Copy link
Member

@tatjam For testing big vs. small ships, I assume you're aware of Ctrl+i to change your ship model.

@tatjam
Copy link
Author

tatjam commented Apr 24, 2024

Messed around a bit with various ships and a fixed fade value feels good. There's really not any ship that's so long its center is way outside the station before it visually is outside.

@impaktor
Copy link
Member

@tatjam If you're feeling done, please rebase commits if/as needed, and remove draft status on PR

@tatjam tatjam marked this pull request as ready for review April 27, 2024 21:13
@tatjam
Copy link
Author

tatjam commented Apr 27, 2024

Fine! The custom light feature could be implemented later on if needed.

@impaktor
Copy link
Member

impaktor commented May 7, 2024

Going to need some review on this @Web-eWorks or/and @fluffyfreak

@Web-eWorks
Copy link
Member

Will do - not had a chance to get to this yet but it's been on my TODO list.

src/SpaceStation.cpp Outdated Show resolved Hide resolved
src/Camera.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@fluffyfreak fluffyfreak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from a couple of minor things which could be using the Color constants I think this is great work 👍

Copy link
Member

@Web-eWorks Web-eWorks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is certainly better than no lighting at all, and the implementation is fairly well-contained and easy to upgrade to shadow maps and punctual lights later down the line when we add support for them.

However, there are a few issues. The most notable one is that the new model bounds information will not be present when a model is converted to .SGM format when we ship a compiled build of the game, which will manifest as a complete lack of the new station lighting. The bounds information will need to be round-tripped through src/scenegraph/BinaryConverter.cpp in the Save and Load methods.

The second is that there is a worrying number of string comparisons and operations involved in computing interior lighting for stations. Model::DistanceFromPointToBound is called N*M times per frame, where N=number of ships on screen and M=number of stations within render distance. If a model contains more than one named bound type, there's a linear loop over bound entries by name. There is quite a bit of room for improvement here, starting with ignoring station-ship pairs with no overlap of visible cull radius. I'll leave some inline review comments where the behavior is non-optimal and presents scaling issues on lower-end hardware.

On the whole I'm quite happy with the PR and I do apologize that it took this long to review only to ask you to make major changes. I'd be happy to discuss further on the individual change requests if needed.

Comment on lines +43 to +45
camera->PrepareLighting(this, true, true);
RenderModel(renderer, camera, viewCoords, viewTransform);
camera->RestoreLighting();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this during hyperjump to ensure it doesn't crash / assert (using e.g. an address sanitizer build)?

Comment on lines 689 to 690
const auto& start = FindTagByName(bound.tags[0])->GetGlobalTransform().GetTranslate();
const auto& end = FindTagByName(bound.tags[1])->GetGlobalTransform().GetTranslate();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, FindTagByName shouldn't be called here at all, as it does a linear search over the list of tags present on the model (which for stations can reach the 100s). Instead, m_bounds could be defined in terms of a runtime-only struct which holds a direct pointer to the tag node, as well as a string hash for fast equality comparison with bound.for_bound. This is a lower-priority optimization if DistanceFromPointToBound is only called for ships actually within range of the station however.

src/Camera.cpp Outdated
Comment on lines 562 to 565
SpaceStation* as_ss = (SpaceStation*)ss;
// Only one of these calls will do anything
if(as_ss->CalcInteriorLighting(b, sLight, sFac))
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should perform early-out rejection if the distance between the body and the space station is greater than b->GetClipRadius() + ss->GetClipRadius().

@@ -180,6 +180,14 @@ namespace SceneGraph {
throw ParseError("Animation start/end frames seem wrong");
m_model->animDefs.push_back(AnimDefinition(animName, startFrame, endFrame, loopMode));
return true;
} else if (match(token, "bound_thick_line")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I think bound_cylinder is a better choice of name here, but I'll leave it to your discretion whether thick_line is the technically correct name.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've chosen "capsule" as a name instead, as this matches the typical capsule collider used in most game engines (cylinder with rounded endcaps)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely a better choice - I would not have been able to tell that was the underlying shape from the existing nomenclature.

@@ -69,12 +70,36 @@ namespace SceneGraph {
bool loop;
};

struct BoundDefinition {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I see this structure as unnecessarily future-proofed. Do you have any further plans to use tags[2] or params[1] for other bound types that you plan to implement immediately? If not, I'd recommend reducing the struct to only what's needed to express the minimum set of bounds currently in use.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got a feeling as most stations are going to be relatively linear, the cylinder / thick line thing is good enough. I'm going to change it to only support that, and if in the future other types are needed an union could be used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually using an union doesn't seem like a great idea if strings are used to store the tags, so probably just having different meanings for the tags. For example, an AABB can also be defined by an start and end tag, and the radius could be used for rounding.

AABBs and the cylinders can get you some really complex geometries!

@Web-eWorks
Copy link
Member

Just taking a first look over the code from my phone here - named struct field initializers are (AFAIK) a c++20 feature (which we don't currently target). Would recommend double-checking for that in the last few commits.

@tatjam
Copy link
Author

tatjam commented Jun 9, 2024

Dangit! I've been lately working on a C++20 codebase and have gotten used to its quirks! Gonna change it back to simply setting the fields, which should be equivalent under any good compiler.

EDIT: Not using a normal aggregate initializer just because i find those to be prone to causing bugs if you reorder fields

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants