|
|
|
|
@@ -299,6 +299,8 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
|
|
|
|
|
// Benchmark de rendimiento (determina max_auto_scenario_ para modos automáticos)
|
|
|
|
|
if (!skip_benchmark_)
|
|
|
|
|
runPerformanceBenchmark();
|
|
|
|
|
else if (custom_scenario_enabled_)
|
|
|
|
|
custom_auto_available_ = true; // benchmark omitido: confiar en que el hardware lo soporta
|
|
|
|
|
|
|
|
|
|
// Precalentar caché: shapes PNG (evitar I/O en primera activación de PNG_SHAPE)
|
|
|
|
|
{
|
|
|
|
|
@@ -716,34 +718,31 @@ void Engine::render() {
|
|
|
|
|
// MODO FIGURA 3D: Ordenar por profundidad Z (Painter's Algorithm)
|
|
|
|
|
// Las pelotas con menor depth_brightness (más lejos/oscuras) se renderizan primero
|
|
|
|
|
|
|
|
|
|
// Crear vector de índices para ordenamiento
|
|
|
|
|
std::vector<size_t> render_order;
|
|
|
|
|
render_order.reserve(balls.size());
|
|
|
|
|
// Bucket sort per profunditat Z (O(N) vs O(N log N))
|
|
|
|
|
for (size_t i = 0; i < balls.size(); i++) {
|
|
|
|
|
render_order.push_back(i);
|
|
|
|
|
int b = static_cast<int>(balls[i]->getDepthBrightness() * (DEPTH_SORT_BUCKETS - 1));
|
|
|
|
|
depth_buckets_[std::clamp(b, 0, DEPTH_SORT_BUCKETS - 1)].push_back(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ordenar índices por profundidad Z (menor primero = fondo primero)
|
|
|
|
|
std::sort(render_order.begin(), render_order.end(), [&balls](size_t a, size_t b) {
|
|
|
|
|
return balls[a]->getDepthBrightness() < balls[b]->getDepthBrightness();
|
|
|
|
|
});
|
|
|
|
|
// Renderizar en orden de profundidad (bucket 0 = fons, bucket 255 = davant)
|
|
|
|
|
for (int b = 0; b < DEPTH_SORT_BUCKETS; b++) {
|
|
|
|
|
for (size_t idx : depth_buckets_[b]) {
|
|
|
|
|
SDL_FRect pos = balls[idx]->getPosition();
|
|
|
|
|
Color color = theme_manager_->getInterpolatedColor(idx); // Usar color interpolado (LERP)
|
|
|
|
|
float brightness = balls[idx]->getDepthBrightness();
|
|
|
|
|
float depth_scale = balls[idx]->getDepthScale();
|
|
|
|
|
|
|
|
|
|
// Renderizar en orden de profundidad (fondo → frente)
|
|
|
|
|
for (size_t idx : render_order) {
|
|
|
|
|
SDL_FRect pos = balls[idx]->getPosition();
|
|
|
|
|
Color color = theme_manager_->getInterpolatedColor(idx); // Usar color interpolado (LERP)
|
|
|
|
|
float brightness = balls[idx]->getDepthBrightness();
|
|
|
|
|
float depth_scale = balls[idx]->getDepthScale();
|
|
|
|
|
// Mapear brightness de 0-1 a rango MIN-MAX
|
|
|
|
|
float brightness_factor = (ROTOBALL_MIN_BRIGHTNESS + brightness * (ROTOBALL_MAX_BRIGHTNESS - ROTOBALL_MIN_BRIGHTNESS)) / 255.0f;
|
|
|
|
|
|
|
|
|
|
// Mapear brightness de 0-1 a rango MIN-MAX
|
|
|
|
|
float brightness_factor = (ROTOBALL_MIN_BRIGHTNESS + brightness * (ROTOBALL_MAX_BRIGHTNESS - ROTOBALL_MIN_BRIGHTNESS)) / 255.0f;
|
|
|
|
|
// Aplicar factor de brillo al color
|
|
|
|
|
int r_mod = static_cast<int>(color.r * brightness_factor);
|
|
|
|
|
int g_mod = static_cast<int>(color.g * brightness_factor);
|
|
|
|
|
int b_mod = static_cast<int>(color.b * brightness_factor);
|
|
|
|
|
|
|
|
|
|
// Aplicar factor de brillo al color
|
|
|
|
|
int r_mod = static_cast<int>(color.r * brightness_factor);
|
|
|
|
|
int g_mod = static_cast<int>(color.g * brightness_factor);
|
|
|
|
|
int b_mod = static_cast<int>(color.b * brightness_factor);
|
|
|
|
|
|
|
|
|
|
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, r_mod, g_mod, b_mod, depth_scale);
|
|
|
|
|
addSpriteToBatch(pos.x, pos.y, pos.w, pos.h, r_mod, g_mod, b_mod, depth_scale);
|
|
|
|
|
}
|
|
|
|
|
depth_buckets_[b].clear(); // netejar per al proper frame
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// MODO PHYSICS: Renderizar en orden normal del vector (sin escala de profundidad)
|
|
|
|
|
|