mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 17:48:46 -10:00
* Remove ambient handling from amin / decal pass * Add ambient light to deferred pass * Make decals work and fix double insignia rendering * Fix decal vertex shader * render insignias as decals * Cleanup of old insignia stuff * Move insignia post-processing to model load * perform envmap lighting in deferred shader * Remove Envmapping from main shader * Fix MSVC warning * exclude def_files from clang tidy
150 lines
4.9 KiB
C++
150 lines
4.9 KiB
C++
#include "graphics/decal_draw_list.h"
|
|
|
|
#include "graphics/matrix.h"
|
|
|
|
#include "render/3d.h"
|
|
#include "tracing/tracing.h"
|
|
#include "light.h"
|
|
|
|
namespace {
|
|
|
|
vec3d BOX_VERTS[] = {{{{ -0.5f, -0.5f, -0.5f }}},
|
|
{{{ -0.5f, 0.5f, -0.5f }}},
|
|
{{{ 0.5f, 0.5f, -0.5f }}},
|
|
{{{ 0.5f, -0.5f, -0.5f }}},
|
|
{{{ -0.5f, -0.5f, 0.5f }}},
|
|
{{{ -0.5f, 0.5f, 0.5f }}},
|
|
{{{ 0.5f, 0.5f, 0.5f }}},
|
|
{{{ 0.5f, -0.5f, 0.5f }}}};
|
|
|
|
uint32_t BOX_FACES[] =
|
|
{ 7, 3, 4, 3, 0, 4, 2, 6, 1, 6, 5, 1, 7, 6, 3, 6, 2, 3, 0, 1, 4, 1, 5, 4, 6, 7, 4, 5, 6, 4, 3, 2, 0, 2, 1, 0, };
|
|
|
|
const size_t BOX_NUM_FACES = sizeof(BOX_FACES) / sizeof(BOX_FACES[0]);
|
|
|
|
gr_buffer_handle box_vertex_buffer;
|
|
gr_buffer_handle box_index_buffer;
|
|
gr_buffer_handle decal_instance_buffer;
|
|
|
|
void init_buffers() {
|
|
box_vertex_buffer = gr_create_buffer(BufferType::Vertex, BufferUsageHint::Static);
|
|
gr_update_buffer_data(box_vertex_buffer, sizeof(BOX_VERTS), BOX_VERTS);
|
|
|
|
box_index_buffer = gr_create_buffer(BufferType::Index, BufferUsageHint::Static);
|
|
gr_update_buffer_data(box_index_buffer, sizeof(BOX_FACES), BOX_FACES);
|
|
|
|
decal_instance_buffer = gr_create_buffer(BufferType::Vertex, BufferUsageHint::Streaming);
|
|
}
|
|
|
|
bool check_box_in_view(const matrix4& transform) {
|
|
for (auto& point : BOX_VERTS) {
|
|
vec3d pt;
|
|
vm_vec_transform(&pt, &point, &transform, true);
|
|
vec3d tmp;
|
|
if (!g3_rotate_vector(&tmp, &pt)) {
|
|
// This point lies in the view cone so we need to render it
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
namespace graphics {
|
|
|
|
void decal_draw_list::globalInit() {
|
|
init_buffers();
|
|
|
|
gr_maybe_create_shader(SDR_TYPE_DECAL, 0);
|
|
gr_maybe_create_shader(SDR_TYPE_DECAL, SDR_FLAG_DECAL_USE_NORMAL_MAP);
|
|
}
|
|
void decal_draw_list::globalShutdown() {
|
|
gr_delete_buffer(box_vertex_buffer);
|
|
gr_delete_buffer(box_index_buffer);
|
|
}
|
|
|
|
void decal_draw_list::prepare_global_data() {
|
|
_buffer = gr_get_uniform_buffer(uniform_block_type::DecalInfo, _draws.size());
|
|
auto& aligner = _buffer.aligner();
|
|
|
|
// Initialize header data
|
|
auto header = aligner.getHeader<graphics::decal_globals>();
|
|
matrix4 invView;
|
|
vm_inverse_matrix4(&invView, &gr_view_matrix);
|
|
|
|
header->viewMatrix = gr_view_matrix;
|
|
header->projMatrix = gr_projection_matrix;
|
|
header->invViewMatrix = invView;
|
|
vm_inverse_matrix4(&header->invProjMatrix, &gr_projection_matrix);
|
|
|
|
header->viewportSize.x = (float) gr_screen.max_w;
|
|
header->viewportSize.y = (float) gr_screen.max_h;
|
|
|
|
for (auto& [batch_info, draw_info] : _draws) {
|
|
auto info = aligner.addTypedElement<graphics::decal_info>();
|
|
info->diffuse_index = batch_info.diffuse < 0 ? -1 : bm_get_array_index(batch_info.diffuse);
|
|
info->glow_index = batch_info.glow < 0 ? -1 : bm_get_array_index(batch_info.glow);
|
|
info->normal_index = batch_info.normal < 0 ? -1 : bm_get_array_index(batch_info.normal);
|
|
|
|
draw_info.first.uniform_offset = _buffer.getBufferOffset(aligner.getCurrentOffset());
|
|
|
|
material_set_decal(&draw_info.first.material,
|
|
bm_get_base_frame(batch_info.diffuse),
|
|
bm_get_base_frame(batch_info.glow),
|
|
bm_get_base_frame(batch_info.normal));
|
|
info->diffuse_blend_mode = draw_info.first.material.get_blend_mode(0) == ALPHA_BLEND_ADDITIVE ? 1 : 0;
|
|
info->glow_blend_mode = draw_info.first.material.get_blend_mode(2) == ALPHA_BLEND_ADDITIVE ? 1 : 0;
|
|
}
|
|
}
|
|
|
|
void decal_draw_list::render() {
|
|
GR_DEBUG_SCOPE("Render decals");
|
|
TRACE_SCOPE(tracing::RenderDecals);
|
|
|
|
prepare_global_data();
|
|
|
|
_buffer.submitData();
|
|
|
|
vertex_layout layout;
|
|
layout.add_vertex_component(vertex_format_data::POSITION3, sizeof(vec3d), 0);
|
|
layout.add_vertex_component(vertex_format_data::MATRIX4, sizeof(matrix4), 0, 1, 1);
|
|
|
|
indexed_vertex_source source;
|
|
source.Vbuffer_handle = box_vertex_buffer;
|
|
source.Ibuffer_handle = box_index_buffer;
|
|
|
|
// Bind the global data only once
|
|
gr_bind_uniform_buffer(uniform_block_type::DecalGlobals,
|
|
_buffer.getBufferOffset(0),
|
|
sizeof(graphics::decal_globals),
|
|
_buffer.bufferHandle());
|
|
gr_screen.gf_start_decal_pass();
|
|
|
|
for (auto& [textures, decal_list] : _draws) {
|
|
GR_DEBUG_SCOPE("Draw decal type");
|
|
TRACE_SCOPE(tracing::RenderSingleDecal);
|
|
|
|
gr_update_buffer_data(decal_instance_buffer, sizeof(matrix4) * decal_list.second.size(), decal_list.second.data());
|
|
gr_bind_uniform_buffer(uniform_block_type::DecalInfo, decal_list.first.uniform_offset, sizeof(graphics::decal_info), _buffer.bufferHandle());
|
|
gr_screen.gf_render_decals(&decal_list.first.material, PRIM_TYPE_TRIS, &layout, BOX_NUM_FACES, source, decal_instance_buffer, static_cast<int>(decal_list.second.size()));
|
|
}
|
|
|
|
gr_screen.gf_stop_decal_pass();
|
|
}
|
|
void decal_draw_list::add_decal(int diffuse_bitmap,
|
|
int glow_bitmap,
|
|
int normal_bitmap,
|
|
float /*decal_timer*/,
|
|
const matrix4& instancedata) {
|
|
if (!check_box_in_view(instancedata)) {
|
|
// The decal box is not in view so we don't need to render it
|
|
return;
|
|
}
|
|
|
|
_draws[decal_batch_info{diffuse_bitmap, glow_bitmap, normal_bitmap}].second.emplace_back(instancedata);
|
|
}
|
|
|
|
}
|