mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
* Extract shadows into own shader and render pass # Conflicts: # code/def_files/data/effects/main-g.sdr * Consolidate render queue code * More cleanup * Fix missing clear of shadow buffer inter frame * Request capability for viewport layer rendering * instanced shadows * Fix issues * Switch to PCF+PCSS and proper textures for it * Smooth PCSS toggle * Fix for windows * Fix OGL error * Cleanup of old flag * Expose shadow smoothness * Fix missing uniform * Make number of shadow cascades dynamic * Progress on cockpit shadow integration * Wrangle Cockpit and show-ship shadows into correct behaviour * Cleanup * make player ship shadow table options more intuitive * Cleanup * Only read from correct set of shadow maps, also stretch first main-scene map to 0 * Remove now non-necessary validation * Make shadow cascade buffer more typesafe and less wasteful * Don't allocate cockpit cascades if not used * Cleanup * Final fixes * Fix Warnings * clang tidy * Fix missing fallback for shader precaching * That weird FOV multiplier that always ruins your day * Avoid shadow geometry artifacts by using hardware depth clamping * Correctly handle shadow cascade overrides with hardcoded length * GCC9 and its sad state of C++17 support. * Address Feedback # Conflicts: # code/graphics/shadows.cpp
245 lines
7.0 KiB
C++
245 lines
7.0 KiB
C++
//
|
|
//
|
|
|
|
#include "uniforms.h"
|
|
#include "matrix.h"
|
|
#include "light.h"
|
|
#include "globalincs/systemvars.h"
|
|
#include "shadows.h"
|
|
#include "nebula/neb.h"
|
|
#include "mod_table/mod_table.h"
|
|
|
|
#define MODEL_SDR_FLAG_MODE_CPP
|
|
#include "def_files/data/effects/model_shader_flags.h"
|
|
|
|
namespace {
|
|
void scale_matrix(matrix4& mat, const vec3d& scale) {
|
|
mat.a2d[0][0] *= scale.xyz.x;
|
|
mat.a2d[0][1] *= scale.xyz.x;
|
|
mat.a2d[0][2] *= scale.xyz.x;
|
|
|
|
mat.a2d[1][0] *= scale.xyz.y;
|
|
mat.a2d[1][1] *= scale.xyz.y;
|
|
mat.a2d[1][2] *= scale.xyz.y;
|
|
|
|
mat.a2d[2][0] *= scale.xyz.z;
|
|
mat.a2d[2][1] *= scale.xyz.z;
|
|
mat.a2d[2][2] *= scale.xyz.z;
|
|
}
|
|
}
|
|
|
|
namespace graphics {
|
|
namespace uniforms {
|
|
|
|
void convert_model_material(model_uniform_data* data_out,
|
|
const model_material& material,
|
|
const matrix4& model_transform,
|
|
const vec3d& scale,
|
|
size_t transform_buffer_offset) {
|
|
auto shader_flags = material.get_shader_flags();
|
|
|
|
Assertion(gr_model_matrix_stack.depth() == 1, "Uniform conversion does not respect previous transforms! "
|
|
"Model matrix stack must be empty!");
|
|
|
|
matrix4 scaled_matrix = model_transform;
|
|
scale_matrix(scaled_matrix, scale);
|
|
|
|
data_out->modelMatrix = scaled_matrix;
|
|
data_out->viewMatrix = gr_view_matrix;
|
|
vm_matrix4_x_matrix4(&data_out->modelViewMatrix, &gr_view_matrix, &scaled_matrix);
|
|
data_out->projMatrix = gr_projection_matrix;
|
|
data_out->textureMatrix = gr_texture_matrix;
|
|
|
|
data_out->color = material.get_color();
|
|
|
|
data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
|
|
data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
|
|
|
|
data_out->effect_num = -1;
|
|
data_out->anim_timer = 0;
|
|
data_out->use_clip_plane = 0;
|
|
|
|
data_out->flags = material.get_shader_runtime_early_flags() | material.get_shader_runtime_flags();
|
|
|
|
if (material.get_animated_effect() >= 0) {
|
|
data_out->anim_timer = material.get_animated_effect_time();
|
|
data_out->effect_num = material.get_animated_effect();
|
|
}
|
|
|
|
data_out->sBasemapIndex = 0;
|
|
data_out->sAmbientmapIndex = 0;
|
|
data_out->sGlowmapIndex = 0;
|
|
data_out->sMiscmapIndex = 0;
|
|
data_out->sNormalmapIndex = 0;
|
|
data_out->sSpecmapIndex = 0;
|
|
|
|
if (material.is_clipped()) {
|
|
auto& clip_info = material.get_clip_plane();
|
|
|
|
data_out->use_clip_plane = true;
|
|
|
|
vec4 clip_equation;
|
|
clip_equation.xyzw.x = clip_info.normal.xyz.x;
|
|
clip_equation.xyzw.y = clip_info.normal.xyz.y;
|
|
clip_equation.xyzw.z = clip_info.normal.xyz.z;
|
|
clip_equation.xyzw.w = -vm_vec_dot(&clip_info.normal, &clip_info.position);
|
|
data_out->clip_equation = clip_equation;
|
|
}
|
|
|
|
if (material.is_lit()) {
|
|
int num_lights = MIN(Num_active_gr_lights, (int)graphics::MAX_UNIFORM_LIGHTS);
|
|
data_out->n_lights = num_lights;
|
|
|
|
gr_lighting_fill_uniforms(data_out->lights, sizeof(data_out->lights));
|
|
|
|
float light_factor = material.get_light_factor();
|
|
data_out->diffuseFactor.xyz.x = gr_light_color[0] * light_factor;
|
|
data_out->diffuseFactor.xyz.y = gr_light_color[1] * light_factor;
|
|
data_out->diffuseFactor.xyz.z = gr_light_color[2] * light_factor;
|
|
gr_get_ambient_light(&data_out->ambientFactor);
|
|
|
|
if (material.get_light_factor() > 0.25f && Cmdline_emissive) {
|
|
data_out->emissionFactor.xyz.x = gr_light_emission[0];
|
|
data_out->emissionFactor.xyz.y = gr_light_emission[1];
|
|
data_out->emissionFactor.xyz.z = gr_light_emission[2];
|
|
} else {
|
|
data_out->emissionFactor.xyz.x = gr_light_zero[0];
|
|
data_out->emissionFactor.xyz.y = gr_light_zero[1];
|
|
data_out->emissionFactor.xyz.z = gr_light_zero[2];
|
|
}
|
|
|
|
}
|
|
data_out->defaultGloss = 0.6f;
|
|
|
|
if (material.get_texture_map(TM_BASE_TYPE) >= 0) {
|
|
if (material.is_desaturated()) {
|
|
data_out->desaturate = 1;
|
|
} else {
|
|
data_out->desaturate = 0;
|
|
}
|
|
|
|
|
|
switch (material.get_blend_mode()) {
|
|
case ALPHA_BLEND_PREMULTIPLIED:
|
|
data_out->blend_alpha = 1;
|
|
break;
|
|
case ALPHA_BLEND_ADDITIVE:
|
|
data_out->blend_alpha = 2;
|
|
break;
|
|
default:
|
|
data_out->blend_alpha = 0;
|
|
break;
|
|
}
|
|
|
|
data_out->sBasemapIndex = bm_get_array_index(material.get_texture_map(TM_BASE_TYPE));
|
|
}
|
|
|
|
if (material.get_texture_map(TM_GLOW_TYPE) >= 0) {
|
|
data_out->sGlowmapIndex = bm_get_array_index(material.get_texture_map(TM_GLOW_TYPE));
|
|
}
|
|
|
|
|
|
if (material.get_texture_map(TM_SPEC_GLOSS_TYPE) >= 0) {
|
|
data_out->sSpecmapIndex = bm_get_array_index(material.get_texture_map(TM_SPEC_GLOSS_TYPE));
|
|
|
|
data_out->gammaSpec = 1;
|
|
data_out->alphaGloss = 1;
|
|
|
|
}
|
|
|
|
if (material.get_texture_map(TM_SPECULAR_TYPE) >= 0) {
|
|
data_out->sSpecmapIndex = bm_get_array_index(material.get_texture_map(TM_SPECULAR_TYPE));
|
|
|
|
data_out->gammaSpec = 0;
|
|
data_out->alphaGloss = 0;
|
|
}
|
|
|
|
if (material.get_texture_map(TM_NORMAL_TYPE) >= 0) {
|
|
data_out->sNormalmapIndex = bm_get_array_index(material.get_texture_map(TM_NORMAL_TYPE));
|
|
}
|
|
|
|
if (material.get_texture_map(TM_AMBIENT_TYPE) >= 0) {
|
|
data_out->sAmbientmapIndex = bm_get_array_index(material.get_texture_map(TM_AMBIENT_TYPE));
|
|
}
|
|
|
|
if (material.get_texture_map(TM_MISC_TYPE) >= 0) {
|
|
data_out->sMiscmapIndex = bm_get_array_index(material.get_texture_map(TM_MISC_TYPE));
|
|
}
|
|
|
|
|
|
|
|
if (material.is_batched()) {
|
|
data_out->buffer_matrix_offset = (int) transform_buffer_offset;
|
|
}
|
|
|
|
// Team colors are passed to the shader here, but the shader needs to handle their application.
|
|
// By default, this is handled through the r and g channels of the misc map, but this can be changed
|
|
// in the shader; test versions of this used the normal map r and b channels
|
|
if (material.get_texture_map(TM_MISC_TYPE) > 0 && material.is_team_color_set()) {
|
|
auto& tm_clr = material.get_team_color();
|
|
vec3d stripe_color;
|
|
vec3d base_color;
|
|
|
|
stripe_color.xyz.x = tm_clr.stripe.r;
|
|
stripe_color.xyz.y = tm_clr.stripe.g;
|
|
stripe_color.xyz.z = tm_clr.stripe.b;
|
|
|
|
base_color.xyz.x = tm_clr.base.r;
|
|
base_color.xyz.y = tm_clr.base.g;
|
|
base_color.xyz.z = tm_clr.base.b;
|
|
|
|
data_out->stripe_color = stripe_color;
|
|
data_out->base_color = base_color;
|
|
|
|
data_out->team_glow_enabled = bm_has_alpha_channel(material.get_texture_map(TM_MISC_TYPE)) ? 1 : 0;
|
|
}
|
|
|
|
if (material.get_thrust_scale() > 0.0f) {
|
|
data_out->thruster_scale = material.get_thrust_scale();
|
|
}
|
|
|
|
|
|
if (material.is_fogged()) {
|
|
auto& fog_params = material.get_fog();
|
|
|
|
if (fog_params.enabled) {
|
|
float fog_near, fog_density;
|
|
neb2_get_adjusted_fog_values(&fog_near, &fog_density);
|
|
data_out->fogNear = fog_near;
|
|
data_out->fogDensity = fog_density;
|
|
|
|
data_out->fogColor.xyzw.x = i2fl(fog_params.r) / 255.0f;
|
|
data_out->fogColor.xyzw.y = i2fl(fog_params.g) / 255.0f;
|
|
data_out->fogColor.xyzw.z = i2fl(fog_params.b) / 255.0f;
|
|
data_out->fogColor.xyzw.w = 1.0f;
|
|
}
|
|
}
|
|
|
|
if ( shader_flags & MODEL_SDR_FLAG_THICK_OUTLINES ) {
|
|
data_out->outlineWidth = material.get_outline_thickness();
|
|
}
|
|
|
|
if (material.is_alpha_mult_active()) {
|
|
data_out->alphaMult = material.get_alpha_mult();
|
|
}
|
|
}
|
|
|
|
void convert_shadow_material(shadow_uniform_data* data_out,
|
|
const matrix4& model_transform,
|
|
const vec3d& scale,
|
|
size_t transform_buffer_offset)
|
|
{
|
|
matrix4 scaled_matrix = model_transform;
|
|
|
|
scale_matrix(scaled_matrix, scale);
|
|
|
|
data_out->modelMatrix = scaled_matrix;
|
|
|
|
vm_matrix4_x_matrix4(&data_out->modelViewMatrix, &gr_view_matrix, &scaled_matrix);
|
|
|
|
data_out->buffer_matrix_offset = (int) transform_buffer_offset;
|
|
}
|
|
|
|
}
|
|
}
|