/** * @brief Sorts Decals so that as many decals can be batched together as possible * * This uses the bitmaps in the definitions to determine if two decals can be rendered at the same time. Since we use * texture arrays we can use the base frame for batching which increases the number of draw calls that can be batched together. * * @param left * @param right * @return */ bool decal_draw_list::sort_draws(const decal_draw_info& left, const decal_draw_info& right) { auto left_diffuse_base = bm_get_base_frame(left.draw_mat.get_texture_map(TM_BASE_TYPE)); auto right_diffuse_base = bm_get_base_frame(right.draw_mat.get_texture_map(TM_BASE_TYPE)); if (left_diffuse_base != right_diffuse_base) { return left_diffuse_base < right_diffuse_base; } auto left_normal_base = bm_get_base_frame(left.draw_mat.get_texture_map(TM_NORMAL_TYPE)); auto right_normal_base = bm_get_base_frame(left.draw_mat.get_texture_map(TM_NORMAL_TYPE)); return left_normal_base < right_normal_base; }
void decal_draw_list::add_decal(int diffuse_bitmap, int normal_bitmap, float decal_timer, const matrix4& transform, float base_alpha) { if (!check_box_in_view(transform)) { // The decal box is not in view so we don't need to render it return; } auto& aligner = _buffer->aligner(); auto info = aligner.addTypedElement<graphics::decal_info>(); info->model_matrix = transform; // This is currently a constant but in the future this may be configurable by the decals table info->normal_angle_cutoff = DECAL_ANGLE_CUTOFF; info->angle_fade_start = DECAL_ANGLE_FADE_START; info->alpha_scale = base_alpha; matrix transform_rot; vm_matrix4_get_orientation(&transform_rot, &transform); // The decal shader works in view-space so the direction also has to be transformed into that space vm_vec_transform(&info->decal_direction, &transform_rot.vec.fvec, &gr_view_matrix, false); vm_inverse_matrix4(&info->model_matrix, &info->inv_model_matrix); info->diffuse_index = bm_get_array_index(diffuse_bitmap); info->normal_index = bm_get_array_index(normal_bitmap); decal_draw_info current_draw; current_draw.uniform_offset = aligner.getCurrentOffset(); material_set_decal(¤t_draw.draw_mat, bm_get_base_frame(diffuse_bitmap), bm_get_base_frame(normal_bitmap)); info->blend_mode = current_draw.draw_mat.get_blend_mode() == ALPHA_BLEND_ADDITIVE ? 1 : 0; _draws.push_back(current_draw); }
primitive_batch* batching_find_batch(int texture, batch_info::material_type material_id, primitive_type prim_type, bool thruster) { // Use the base texture for finding the batch item since all items can reuse the same texture array auto base_tex = bm_get_base_frame(texture); batch_info query(material_id, base_tex, prim_type, thruster); SCP_map<batch_info, primitive_batch>::iterator iter = Batching_primitives.find(query); if ( iter == Batching_primitives.end() ) { primitive_batch* batch = &Batching_primitives[query]; *batch = primitive_batch(query); return batch; } else { return &iter->second; } }