Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/linux/clang_tidy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ git diff -U0 --no-color "$BASE_COMMIT..$2" | \
-extra-arg="-DWITH_VULKAN" \
-extra-arg="-DVULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1" \
-extra-arg="-DVK_NO_PROTOTYPES" \
-regex '(code(?!((\/graphics\/shaders\/compiled)|(\/globalincs\/windebug)))|freespace2|qtfred|test\/src|build|tools)\/.*\.(cpp|h)' \
-regex '(code(?!((\/graphics\/shaders\/compiled)|(\/globalincs\/windebug)|(\/def_files\/data)))|freespace2|qtfred|test\/src|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-16 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
177 changes: 91 additions & 86 deletions code/decals/decals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,66 +181,52 @@ void parse_decals_table(const char* filename) {
}
}

struct Decal {
int definition_handle = -1;
object_h object;
int orig_obj_type = OBJ_NONE;
int submodel = -1;

float creation_time = -1.0f; //!< The mission time at which this decal was created
float lifetime = -1.0f; //!< The time this decal is active. When negative it never expires

vec3d position = vmd_zero_vector;
vec3d scale;
matrix orientation = vmd_identity_matrix;
Decal::Decal() {
vm_vec_make(&scale, 1.f, 1.f, 1.f);
}

Decal() {
vm_vec_make(&scale, 1.f, 1.f, 1.f);
bool Decal::isValid() const {
if (!object.isValid()) {
return false;
}
if (object.objp()->flags[Object::Object_Flags::Should_be_dead]) {
return false;
}

bool isValid() const {
if (!object.isValid()) {
return false;
}
if (object.objp()->flags[Object::Object_Flags::Should_be_dead]) {
return false;
}
if (orig_obj_type != object.objp()->type) {
mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n",
object.objnum, Object_type_names[orig_obj_type], Object_type_names[object.objp()->type]));
return false;
}

if (orig_obj_type != object.objp()->type) {
mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n",
object.objnum, Object_type_names[orig_obj_type], Object_type_names[object.objp()->type]));
if (lifetime > 0.0f) {
if (f2fl(Missiontime) >= creation_time + lifetime) {
// Decal has expired
return false;
}
}

if (lifetime > 0.0f) {
if (f2fl(Missiontime) >= creation_time + lifetime) {
// Decal has expired
return false;
}
}

auto objp = object.objp();
if (objp->type == OBJ_SHIP) {
auto shipp = &Ships[objp->instance];
auto model_instance = model_get_instance(shipp->model_instance_num);
auto objp = object.objp();
if (objp->type == OBJ_SHIP) {
auto shipp = &Ships[objp->instance];
auto model_instance = model_get_instance(shipp->model_instance_num);

Assertion(submodel >= 0 && submodel < object_get_model(objp)->n_models,
"Invalid submodel number detected!");
auto smi = &model_instance->submodel[submodel];
Assertion(submodel >= 0 && submodel < object_get_model(objp)->n_models,
"Invalid submodel number detected!");
auto smi = &model_instance->submodel[submodel];

if (smi->blown_off) {
return false;
}
} else {
Assertion(false, "Only ships are currently supported for decals!");
if (smi->blown_off) {
return false;
}

return true;
} else {
Assertion(false, "Only ships are currently supported for decals!");
return false;
}
};

SCP_vector<Decal> active_decals;
return true;
}

SCP_vector<Decal> active_decals, active_single_frame_decals;

bool required_string_if_new(const char* token, bool new_entry) {
if (!new_entry) {
Expand Down Expand Up @@ -374,7 +360,7 @@ void initializeMission() {
const float DECAL_ANGLE_CUTOFF = fl_radians(45.f);
const float DECAL_ANGLE_FADE_START = fl_radians(30.f);

static matrix4 getDecalTransform(Decal& decal, float alpha) {
static matrix4 getDecalTransform(const Decal& decal, float alpha) {
Assertion(decal.object.objp()->type == OBJ_SHIP, "Only ships are currently supported for decals!");

auto objp = decal.object.objp();
Expand Down Expand Up @@ -418,6 +404,51 @@ static matrix4 getDecalTransform(Decal& decal, float alpha) {
return mat4;
}

inline static void renderDecal(graphics::decal_draw_list& draw_list, const Decal& decal) {
auto mission_time = f2fl(Missiontime);

int diffuse_bm = -1;
int glow_bm = -1;
int normal_bm = -1;

auto decal_time = mission_time - decal.creation_time;
auto progress = decal_time / decal.lifetime;

float alpha = 1.0f;
if (progress > 0.8) {
// Fade the decal out for the last 20% of its lifetime
alpha = 1.0f - smoothstep(0.8f, 1.0f, progress);
}

if (std::holds_alternative<int>(decal.definition_handle)) {
int definition_handle = std::get<int>(decal.definition_handle);
Assertion(definition_handle >= 0 && definition_handle < (int) DecalDefinitions.size(),
"Invalid decal handle detected!");
auto &decalDef = DecalDefinitions[definition_handle];

if (decalDef.getDiffuseBitmap() >= 0) {
diffuse_bm = decalDef.getDiffuseBitmap()
+
bm_get_anim_frame(decalDef.getDiffuseBitmap(), decal_time, 0.0f, decalDef.isDiffuseLooping());
}

if (decalDef.getGlowBitmap() >= 0) {
glow_bm = decalDef.getGlowBitmap()
+ bm_get_anim_frame(decalDef.getGlowBitmap(), decal_time, 0.0f, decalDef.isGlowLooping());
}

if (decalDef.getNormalBitmap() >= 0) {
normal_bm = decalDef.getNormalBitmap()
+ bm_get_anim_frame(decalDef.getNormalBitmap(), decal_time, 0.0f, decalDef.isNormalLooping());
}
}
else {
std::tie(diffuse_bm, glow_bm, normal_bm) = std::get<std::tuple<int, int, int>>(decal.definition_handle);
}

draw_list.add_decal(diffuse_bm, glow_bm, normal_bm, decal_time, getDecalTransform(decal, alpha));
}

void renderAll() {
if (!Decal_system_active || !Decal_option_active || !gr_is_capable(gr_capability::CAPABILITY_INSTANCED_RENDERING)) {
return;
Expand All @@ -442,51 +473,21 @@ void renderAll() {
++iter;
}

if (active_decals.empty()) {
if (active_decals.empty() && active_single_frame_decals.empty()) {
return;
}

auto mission_time = f2fl(Missiontime);

graphics::decal_draw_list draw_list;
for (auto& decal : active_decals) {

Assertion(decal.definition_handle >= 0 && decal.definition_handle < (int)DecalDefinitions.size(),
"Invalid decal handle detected!");
auto& decalDef = DecalDefinitions[decal.definition_handle];

int diffuse_bm = -1;
int glow_bm = -1;
int normal_bm = -1;

auto decal_time = mission_time - decal.creation_time;
auto progress = decal_time / decal.lifetime;

float alpha = 1.0f;
if (progress > 0.8) {
// Fade the decal out for the last 20% of its lifetime
alpha = 1.0f - smoothstep(0.8f, 1.0f, progress);
}

if (decalDef.getDiffuseBitmap() >= 0) {
diffuse_bm = decalDef.getDiffuseBitmap()
+ bm_get_anim_frame(decalDef.getDiffuseBitmap(), decal_time, 0.0f, decalDef.isDiffuseLooping());
}

if (decalDef.getGlowBitmap() >= 0) {
glow_bm = decalDef.getGlowBitmap()
+ bm_get_anim_frame(decalDef.getGlowBitmap(), decal_time, 0.0f, decalDef.isGlowLooping());
}

if (decalDef.getNormalBitmap() >= 0) {
normal_bm = decalDef.getNormalBitmap()
+ bm_get_anim_frame(decalDef.getNormalBitmap(), decal_time, 0.0f, decalDef.isNormalLooping());
}

draw_list.add_decal(diffuse_bm, glow_bm, normal_bm, decal_time, getDecalTransform(decal, alpha));
}
graphics::decal_draw_list draw_list;
for (auto& decal : active_decals)
renderDecal(draw_list, decal);
for (auto& decal : active_single_frame_decals)
renderDecal(draw_list, decal);

draw_list.render();

active_single_frame_decals.clear();
}

void addDecal(creation_info& info, const object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
Expand Down Expand Up @@ -531,4 +532,8 @@ void addDecal(creation_info& info, const object* host, int submodel, const vec3d
active_decals.push_back(newDecal);
}

void addSingleFrameDecal(Decal&& info) {
active_single_frame_decals.push_back(info);
}

}
21 changes: 21 additions & 0 deletions code/decals/decals.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,25 @@ class DecalDefinition {
bool isNormalLooping() const;
};

struct Decal {
//DecalDefinition idx vs immediate diffuse/glow/normal
std::variant<int, std::tuple<int, int, int>> definition_handle = -1;
object_h object;
int orig_obj_type = OBJ_NONE;
int submodel = -1;

float creation_time = -1.0f; //!< The mission time at which this decal was created
float lifetime = -1.0f; //!< The time this decal is active. When negative it never expires

vec3d position = vmd_zero_vector;
vec3d scale;
matrix orientation = vmd_identity_matrix;

Decal();

bool isValid() const;
};

extern SCP_vector<DecalDefinition> DecalDefinitions;
extern bool Decal_system_active;
extern bool Decal_option_active;
Expand Down Expand Up @@ -139,4 +158,6 @@ void addDecal(creation_info& info,
const vec3d& local_pos,
const matrix& local_orient);

void addSingleFrameDecal(Decal&& info);

}
13 changes: 0 additions & 13 deletions code/def_files/data/effects/decal-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ layout (std140) uniform decalGlobalData {
mat4 invViewMatrix;
mat4 invProjMatrix;

vec3 ambientLight;
float pad0;

vec2 viewportSize;
};

Expand Down Expand Up @@ -135,16 +132,6 @@ void main() {
// Additive blending
diffuse_out = vec4(color.rgb * alpha, 1.0);
}

// The main model shader applies ambient lighting by drawing the ambient part of the texture into the emissive
// texture. We do the same here to make sure the decal material is applied correctly
if (glow_blend_mode == 0) {
// Normal alpha blending
emissive_out = vec4(color.rgb * ambientLight, color.a * alpha);
} else {
// Additive blending
emissive_out = vec4(alpha * color.rgb * ambientLight, 1.0);
}
}

if (glow_index >= 0) {
Expand Down
5 changes: 1 addition & 4 deletions code/def_files/data/effects/decal-v.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ layout (std140) uniform decalGlobalData {
mat4 invViewMatrix;
mat4 invProjMatrix;

vec3 ambientLight;
float pad0;

vec2 viewportSize;
};

Expand All @@ -40,6 +37,6 @@ void main() {
modelMatrix[2][3] = 0.0;

invModelMatrix = inverse(modelMatrix);
decalDirection = mat3(viewMatrix) * vec3(modelMatrix[0][2], modelMatrix[1][2], modelMatrix[2][2]);
decalDirection = mat3(viewMatrix) * modelMatrix[2].xyz;
gl_Position = projMatrix * viewMatrix * modelMatrix * vertPosition;
}
2 changes: 1 addition & 1 deletion code/def_files/data/effects/deferred-clear-f.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ out vec4 fragOut5;
void main()
{
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
fragOut1 = vec4(0.0, 0.0, -1000000.0, 1.0); // position
fragOut1 = vec4(0.0, 0.0, -1000000.0, 0.0); // position
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
Expand Down
Loading
Loading