/**
 * @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(&current_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);
}
Пример #3
0
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;
	}
}