mirror of
https://github.com/astromaddie/HaloCE-VR.git
synced 2026-10-17 16:00:13 +02:00
The game side of single-pass stereo: with vr.multiview (on by default) a stereo frame's two eye windows become one, drawn from between the eyes with a frustum covering both (culling and visibility once for the pair), and the windows after it move up. rasterizer_set_frustum_z then gives the vertex programs each eye's camera: view 0's in c[-96..-89] as before, view 1's through halo_vr_set_view1_vertex_constants, both with the call's near and far. The pass draws into d3d8_gl.c's two-layer target (halo_vr_multiview_begin/end, then halo_vr_resolve_multiview); if the driver refuses it, that frame draws the left eye alone and the eyes are drawn one at a time from then on. The hidden-area mask is left out of the one pass for now. Non-VR builds keep rasterizer_set_frustum_z as it was.
742 lines
20 KiB
C
742 lines
20 KiB
C
/*
|
|
RENDER.C
|
|
|
|
symbols in this file:
|
|
001743B0 0020:
|
|
_render_effects (0000)
|
|
001743D0 0010:
|
|
_render_initialize (0000)
|
|
001743E0 0010:
|
|
_render_initialize_for_new_map (0000)
|
|
001743F0 0010:
|
|
_render_dispose_from_old_map (0000)
|
|
00174400 0010:
|
|
_render_dispose (0000)
|
|
00174410 0110:
|
|
_render_nonplayer_frame (0000)
|
|
00174520 00f0:
|
|
_render_frame_pregame (0000)
|
|
00174610 0020:
|
|
_render_frame_present (0000)
|
|
00174630 0070:
|
|
_render_location_visible (0000)
|
|
001746A0 0050:
|
|
_rendered_cluster_get (0000)
|
|
001746F0 03f0:
|
|
_render_window (0000)
|
|
00174AE0 03f0:
|
|
_render_player_frame (0000)
|
|
00174ED0 00f0:
|
|
_render_frame (0000)
|
|
0029F44C 001f:
|
|
??_C@_0BP@JNDFGHKA@c?3?2halo?2SOURCE?2render?2render?4c?$AA@ (0000)
|
|
0029F470 0061:
|
|
??_C@_0GB@NHJDHKGO@location?9?$DOcluster_index?$DO?$DN0?5?$CG?$CG?5lo@ (0000)
|
|
0029F4D8 0052:
|
|
??_C@_0FC@DLFICDJP@rendered_cluster_index?$DO?$DN0?5?$CG?$CG?5ren@ (0000)
|
|
0029F530 0052:
|
|
??_C@_0FC@NBMIPGBN@window?9?$DOrender_camera?4viewport_b@ (0000)
|
|
0029F588 0051:
|
|
??_C@_0FB@IDPOBHAJ@window?9?$DOrender_camera?4viewport_b@ (0000)
|
|
0029F5DC 002c:
|
|
??_C@_0CM@LKHLGDKF@window?9?$DOrender_camera?4viewport_b@ (0000)
|
|
0029F608 002c:
|
|
??_C@_0CM@HBCHLAAA@window?9?$DOrender_camera?4viewport_b@ (0000)
|
|
0029F638 006d:
|
|
??_C@_0GN@PKELCNNH@?$CBmemcmp?$CI?$CGwindow?9?$DOrender_camera?4w@ (0000)
|
|
0029F6A8 0071:
|
|
??_C@_0HB@BCLIBPGM@?$CBmemcmp?$CI?$CGwindow?9?$DOrender_camera?4v@ (0000)
|
|
0029F720 0048:
|
|
??_C@_0EI@NGOLLMDP@?$CD?$CD?$CD?5ERROR?5something?5is?5wrong?5wit@ (0000)
|
|
0030D4D2 0004:
|
|
_render_contrails_enabled (0000)
|
|
_render_particles_enabled (0001)
|
|
_render_particle_systems_enabled (0002)
|
|
_render_weather_particle_systems_enabled (0003)
|
|
004B8B22 0001:
|
|
_render_invalid_fog_warning_displayed (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries.h"
|
|
#include "cseries/errors.h"
|
|
#include "render.h"
|
|
#include "render_cameras_internal.h"
|
|
#include "render_particles.h"
|
|
#include "objects.h"
|
|
#include "render_sprite.h"
|
|
#include "scenario.h"
|
|
#include "structure_bsp_definitions.h"
|
|
#include "effects/player_effects.h"
|
|
#include "structures/structure_visibility.h"
|
|
#include "rasterizer.h"
|
|
#include "rasterizer/rasterizer_lights.h"
|
|
#include "profile.h"
|
|
#include "progress_bar.h"
|
|
#include "ui_widget.h"
|
|
#include "bink_playback.h"
|
|
#include "game.h"
|
|
#include "game_engine.h"
|
|
#include "interface/first_person_weapons.h"
|
|
#include "interface/interface.h"
|
|
#include "editor_stubs.h"
|
|
#include "render_debug.h"
|
|
#include "objects/object_lights_rendering.h"
|
|
#include "effects/particle_systems.h"
|
|
#include "effects/weather_particle_systems.h"
|
|
#include "main/main.h"
|
|
#include "structures/structures.h"
|
|
#include "halo_vr.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
_render_target_primary = 0,
|
|
_render_target_secondary,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_decal_layer_primary = 0,
|
|
_decal_layer_secondary,
|
|
_decal_layer_light,
|
|
_decal_layer_alpha_tested,
|
|
_decal_layer_water,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_render_planar_fog_mode_fully_fogged = 2,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
#define RASTERIZER_TARGET_RENDER_PRIMARY_WIDTH halo_screen_width()
|
|
#define RASTERIZER_TARGET_RENDER_PRIMARY_HEIGHT 480
|
|
|
|
/* ---------- structures */
|
|
|
|
#ifdef HALO_VR
|
|
/* a screen flash that only darkens what is under it (the darken type, or a
|
|
lighten toward black, as a fade to black is); the types as
|
|
rasterizer_xbox_screen_effect.c numbers them: 1 lighten, 2 darken */
|
|
static boolean vr_screen_flash_darkens(
|
|
struct render_screen_flash const *flash)
|
|
{
|
|
switch (flash->type)
|
|
{
|
|
case 2:
|
|
return TRUE;
|
|
case 1:
|
|
return flash->color.red + flash->color.green + flash->color.blue < 0.3f;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static void render_nonplayer_frame(
|
|
const struct render_window *window,
|
|
long window_type);
|
|
static void render_window(
|
|
short local_player_index,
|
|
const struct render_camera *camera,
|
|
const struct render_frustum *frustum,
|
|
const struct render_camera *rasterizer_camera,
|
|
const struct render_frustum *rasterizer_frustum,
|
|
short rasterizer_target,
|
|
boolean has_mirror);
|
|
static void render_player_frame(
|
|
struct render_window *window,
|
|
const point2d *screenshot_combined_index);
|
|
|
|
void render_sky(
|
|
void);
|
|
|
|
/* ---------- globals */
|
|
|
|
struct render_globals render;
|
|
|
|
static boolean render_invalid_fog_warning_displayed;
|
|
|
|
extern short global_screenshot_count;
|
|
|
|
boolean render_contrails_enabled = TRUE;
|
|
boolean render_particles_enabled = TRUE;
|
|
boolean render_particle_systems_enabled = TRUE;
|
|
boolean render_weather_particle_systems_enabled = TRUE;
|
|
|
|
/* ---------- public code */
|
|
|
|
void render_effects(
|
|
boolean enable)
|
|
{
|
|
render_weather_particle_systems_enabled = enable;
|
|
render_particle_systems_enabled = enable;
|
|
render_particles_enabled = enable;
|
|
render_contrails_enabled = enable;
|
|
}
|
|
|
|
void render_initialize(
|
|
void)
|
|
{
|
|
render_objects_initialize();
|
|
}
|
|
|
|
void render_initialize_for_new_map(
|
|
void)
|
|
{
|
|
render_objects_initialize_for_new_map();
|
|
}
|
|
|
|
void render_dispose_from_old_map(
|
|
void)
|
|
{
|
|
render_objects_dispose_from_old_map();
|
|
}
|
|
|
|
void render_dispose(
|
|
void)
|
|
{
|
|
render_objects_dispose();
|
|
}
|
|
|
|
static void render_nonplayer_frame(
|
|
const struct render_window *window,
|
|
long window_type)
|
|
{
|
|
struct rasterizer_window_begin_parameters parameters;
|
|
|
|
profile_render_window_start(FALSE);
|
|
memset(¶meters, 0, sizeof(parameters));
|
|
|
|
render.camera = window->render_camera;
|
|
render_camera_build_frustum(&render.camera, NULL, &render.frustum, TRUE);
|
|
|
|
parameters.camera = window->rasterizer_camera;
|
|
render_camera_build_frustum(¶meters.camera, NULL, ¶meters.frustum, TRUE);
|
|
|
|
parameters.rasterizer_target = _render_target_primary;
|
|
parameters.suppress_clear = window_type == 0;
|
|
parameters.window_index = NONE;
|
|
rasterizer_window_begin(¶meters);
|
|
|
|
switch (window_type)
|
|
{
|
|
case 0:
|
|
/* letterbox bars and split screen dividers: laid out from the
|
|
viewport, so not centered like the menus on a wide screen */
|
|
interface_draw_fullscreen_overlays();
|
|
rasterizer_debug_draw();
|
|
break;
|
|
|
|
case 1:
|
|
halo_screen_ui_offset(TRUE);
|
|
game_engine_nonplayer_post_rasterize();
|
|
halo_screen_ui_offset(FALSE);
|
|
break;
|
|
|
|
default:
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 287, !"unreachable");
|
|
break;
|
|
}
|
|
|
|
rasterizer_window_end();
|
|
profile_render_window_end();
|
|
|
|
return;
|
|
}
|
|
|
|
void render_frame_pregame(
|
|
struct render_window const *window,
|
|
struct bitmap_data *bitmap)
|
|
{
|
|
struct rasterizer_frame_begin_parameters parameters;
|
|
struct rasterizer_window_begin_parameters rasterizer_parameters;
|
|
|
|
render.frame_index++;
|
|
|
|
rasterizer_frame_begin(¶meters);
|
|
rasterizer_windows_begin();
|
|
profile_render_window_start(FALSE);
|
|
|
|
memset(&rasterizer_parameters, 0, sizeof(rasterizer_parameters));
|
|
|
|
render.camera = window->render_camera;
|
|
render_camera_build_frustum(&render.camera, NULL, &render.frustum, TRUE);
|
|
|
|
rasterizer_parameters.camera = window->rasterizer_camera;
|
|
render_camera_build_frustum(&rasterizer_parameters.camera, NULL, &rasterizer_parameters.frustum, TRUE);
|
|
|
|
rasterizer_parameters.rasterizer_target = 0;
|
|
rasterizer_window_begin(&rasterizer_parameters);
|
|
|
|
halo_screen_ui_offset(TRUE);
|
|
render_ui_widgets(0, &window->rasterizer_camera.viewport_bounds);
|
|
halo_screen_ui_offset(FALSE);
|
|
bink_playback_render();
|
|
|
|
{
|
|
real progress;
|
|
if (game_map_loading_in_progress(&progress))
|
|
{
|
|
progress_bar_display(progress);
|
|
}
|
|
}
|
|
|
|
rasterizer_window_end();
|
|
profile_render_window_end();
|
|
rasterizer_windows_end();
|
|
rasterizer_frame_end();
|
|
|
|
return;
|
|
}
|
|
|
|
void render_frame_present(
|
|
const point2d *screenshot_index,
|
|
struct bitmap_data *bitmap)
|
|
{
|
|
rasterizer_present(bitmap, screenshot_index);
|
|
|
|
return;
|
|
}
|
|
|
|
boolean render_location_visible(
|
|
struct location *location)
|
|
{
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 584, location->cluster_index>=0 && location->cluster_index<global_structure_bsp_get()->clusters.count);
|
|
return TEST_FLAG(render.visible_cluster_flags[location->cluster_index>>5], location->cluster_index&31);
|
|
}
|
|
|
|
struct rendered_cluster *rendered_cluster_get(
|
|
short rendered_cluster_index)
|
|
{
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 592, rendered_cluster_index>=0 && rendered_cluster_index<render.rendered_cluster_count);
|
|
return &render.rendered_clusters[rendered_cluster_index];
|
|
}
|
|
|
|
static void render_window(
|
|
short local_player_index,
|
|
const struct render_camera *camera,
|
|
const struct render_frustum *frustum,
|
|
const struct render_camera *rasterizer_camera,
|
|
const struct render_frustum *rasterizer_frustum,
|
|
short rasterizer_target,
|
|
boolean has_mirror)
|
|
{
|
|
struct rasterizer_window_begin_parameters parameters;
|
|
short rendered_cluster_index;
|
|
|
|
profile_render_window_start(TRUE);
|
|
render.scene_index++;
|
|
memset(¶meters, 0, sizeof(parameters));
|
|
|
|
render.local_player_index = local_player_index;
|
|
render.camera = *camera;
|
|
render.frustum = *frustum;
|
|
parameters.camera = *rasterizer_camera;
|
|
parameters.frustum = *rasterizer_frustum;
|
|
parameters.rasterizer_target = rasterizer_target;
|
|
parameters.has_mirror = has_mirror;
|
|
parameters.window_index = render.window_index;
|
|
parameters.fog = render.fog;
|
|
|
|
structure_visibility_compute();
|
|
player_effect_get_screen_flash(local_player_index, ¶meters.screen_flash);
|
|
rasterizer_window_begin(¶meters);
|
|
#ifdef HALO_VR
|
|
/* an eye's hidden area masked before anything is drawn (the window's
|
|
target, its depth too, is cleared by now) */
|
|
if (VR_RENDER_EYE() && !VR_RENDER_MULTIVIEW())
|
|
vr_draw_visibility_mask(vr_render_pass);
|
|
#endif
|
|
#ifdef HALO_VR
|
|
/* the headset's HUD pass: the HUD alone, on a transparent ground */
|
|
if (VR_RENDER_HUD())
|
|
{
|
|
halo_vr_clear_transparent();
|
|
interface_draw_screen();
|
|
/* a flash or fade is drawn over the whole of each eye; here only one
|
|
that darkens, so that a fade to black takes the HUD with it (its
|
|
alpha is its brightness): one that lightens would make the panel a
|
|
lit box */
|
|
if (vr_screen_flash_darkens(¶meters.screen_flash))
|
|
rasterizer_screen_flash();
|
|
halo_screen_ui_offset(TRUE);
|
|
render_ui_widgets(local_player_index, &rasterizer_camera->viewport_bounds);
|
|
halo_screen_ui_offset(FALSE);
|
|
rasterizer_window_end();
|
|
profile_render_window_end();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (!bink_playback_in_progress())
|
|
{
|
|
build_sprite_prepare_for_window();
|
|
render_sky();
|
|
#ifdef HALO_VR
|
|
/* posed once a frame, from the head between the eyes: per eye it
|
|
would sit at the same place in each and lose its depth */
|
|
if (!VR_RENDER_REPEAT())
|
|
{
|
|
struct render_camera eye_camera = render.camera;
|
|
|
|
vr_render_weapon_camera(&render.camera);
|
|
first_person_weapon_render_update();
|
|
render.camera = eye_camera;
|
|
}
|
|
#else
|
|
first_person_weapon_render_update();
|
|
#endif
|
|
lights_preprocess_scene();
|
|
render_objects();
|
|
structure_render_preprocess();
|
|
structure_render_lightmaps();
|
|
rasterizer_lens_flares_submit_occlusion_tests();
|
|
render_object_shadows();
|
|
lights_render_diffuse();
|
|
|
|
rasterizer_decals_begin(_decal_layer_light);
|
|
for (rendered_cluster_index = 0;
|
|
rendered_cluster_index < render.rendered_cluster_count;
|
|
rendered_cluster_index++)
|
|
{
|
|
rasterizer_decals_draw(rendered_cluster_get(rendered_cluster_index)->cluster_index);
|
|
}
|
|
rasterizer_decals_end();
|
|
|
|
rasterizer_decals_begin(_decal_layer_alpha_tested);
|
|
for (rendered_cluster_index = 0;
|
|
rendered_cluster_index < render.rendered_cluster_count;
|
|
rendered_cluster_index++)
|
|
{
|
|
rasterizer_decals_draw(rendered_cluster_get(rendered_cluster_index)->cluster_index);
|
|
}
|
|
rasterizer_decals_end();
|
|
|
|
structure_render_diffuse_texture();
|
|
|
|
rasterizer_decals_begin(_decal_layer_primary);
|
|
for (rendered_cluster_index = 0;
|
|
rendered_cluster_index < render.rendered_cluster_count;
|
|
rendered_cluster_index++)
|
|
{
|
|
rasterizer_decals_draw(rendered_cluster_get(rendered_cluster_index)->cluster_index);
|
|
}
|
|
rasterizer_decals_end();
|
|
|
|
rasterizer_decals_begin(_decal_layer_secondary);
|
|
for (rendered_cluster_index = 0;
|
|
rendered_cluster_index < render.rendered_cluster_count;
|
|
rendered_cluster_index++)
|
|
{
|
|
rasterizer_decals_draw(rendered_cluster_get(rendered_cluster_index)->cluster_index);
|
|
}
|
|
rasterizer_decals_end();
|
|
|
|
lights_render_specular();
|
|
structure_render_specular_lightmaps();
|
|
structure_render_reflection_lightmap_masks();
|
|
structure_render_reflection_mirrors();
|
|
structure_render_reflections();
|
|
structure_render_transparent_geometry();
|
|
structure_render_fog();
|
|
game_engine_post_rasterize_objects();
|
|
weather_particle_systems_render();
|
|
render_particles();
|
|
particle_systems_render();
|
|
render_contrails_normal();
|
|
rasterizer_transparent_geometry_draw(TRUE);
|
|
|
|
rasterizer_decals_begin(_decal_layer_water);
|
|
for (rendered_cluster_index = 0;
|
|
rendered_cluster_index < render.rendered_cluster_count;
|
|
rendered_cluster_index++)
|
|
{
|
|
rasterizer_decals_draw(rendered_cluster_get(rendered_cluster_index)->cluster_index);
|
|
}
|
|
rasterizer_decals_end();
|
|
|
|
structure_render_detail_objects();
|
|
rasterizer_transparent_geometry_draw(FALSE);
|
|
rasterizer_transparent_geometry_stop();
|
|
/* the fog's screen layers assume a symmetric frustum facing the
|
|
game's camera: not for the headset's eyes or scope */
|
|
if (!VR_RENDER_VIEW())
|
|
structure_render_fog_screen();
|
|
rasterizer_lens_flares_draw();
|
|
/* the headset shows the HUD on a layer of its own */
|
|
if (!VR_RENDER_VIEW())
|
|
{
|
|
interface_draw_screen();
|
|
rasterizer_screen_flash();
|
|
halo_screen_ui_offset(TRUE);
|
|
render_ui_widgets(local_player_index, &rasterizer_camera->viewport_bounds);
|
|
halo_screen_ui_offset(FALSE);
|
|
}
|
|
#ifdef HALO_VR
|
|
/* but a screen flash or fade (a white flash into a scene, a fade to
|
|
black) covers the whole view, as the game's own blend over each eye */
|
|
else if (VR_RENDER_EYE())
|
|
{
|
|
rasterizer_screen_flash();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bink_playback_render();
|
|
render_camera_debug_frustum(&render.camera, &render.frustum);
|
|
render_debug();
|
|
editor_render();
|
|
rasterizer_debug_draw();
|
|
rasterizer_window_end();
|
|
profile_render_window_end();
|
|
|
|
return;
|
|
}
|
|
|
|
static void render_player_frame(
|
|
struct render_window *window,
|
|
const point2d *screenshot_combined_index)
|
|
{
|
|
struct render_camera *camera;
|
|
boolean has_mirror;
|
|
real_rectangle2d frustum_bounds;
|
|
struct render_frustum frustum;
|
|
struct render_frustum rasterizer_frustum;
|
|
struct render_mirror mirror;
|
|
|
|
camera = &window->render_camera;
|
|
has_mirror = FALSE;
|
|
|
|
structure_visibility_find_camera(camera);
|
|
render.fog.runtime_flags = 0;
|
|
scenario_get_atmospheric_fog(
|
|
window->local_player_index,
|
|
(word)render.visible_sky_index,
|
|
&camera->position,
|
|
&render.fog);
|
|
#ifdef HALO_VR
|
|
/* the headset's HUD pass draws no world: getting the planar fog would
|
|
leave its animation offset waiting for a structure pass that never runs
|
|
(structure_render_set_fog_offset asserts it is taken once a window) */
|
|
if (!VR_RENDER_HUD())
|
|
#endif
|
|
structure_get_planar_fog((short)render.cluster_index, &render.fog);
|
|
|
|
if (render.fog.atmospheric_maximum_distance != 0.0f &&
|
|
render.visible_sky_index == NONE &&
|
|
render.fog.planar_maximum_distance > render.fog.atmospheric_maximum_distance)
|
|
{
|
|
render.fog.planar_maximum_distance = render.fog.atmospheric_maximum_distance;
|
|
}
|
|
|
|
if (render.fog.atmospheric_maximum_density == 1.0f &&
|
|
render.fog.atmospheric_maximum_distance != 0.0f)
|
|
{
|
|
window->render_camera.z_far = MIN(
|
|
window->render_camera.z_far,
|
|
render.fog.atmospheric_maximum_distance);
|
|
}
|
|
|
|
if (render.fog.planar_mode == _render_planar_fog_mode_fully_fogged &&
|
|
render.fog.planar_maximum_distance != 0.0f)
|
|
{
|
|
window->render_camera.z_far = MIN(
|
|
window->render_camera.z_far,
|
|
render.fog.planar_maximum_distance);
|
|
}
|
|
|
|
if (window->render_camera.z_far <= window->render_camera.z_near)
|
|
{
|
|
if (!render_invalid_fog_warning_displayed)
|
|
{
|
|
error(2, "### ERROR something is wrong with the fog in the sky tag or the fog tag");
|
|
render_invalid_fog_warning_displayed = TRUE;
|
|
}
|
|
|
|
window->render_camera.z_far = window->render_camera.z_near + 0.01f;
|
|
}
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\render\\render.c",
|
|
187,
|
|
!memcmp(&window->render_camera.viewport_bounds,
|
|
&window->rasterizer_camera.viewport_bounds,
|
|
sizeof(rectangle2d)));
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\render\\render.c",
|
|
188,
|
|
!memcmp(&window->render_camera.window_bounds,
|
|
&window->rasterizer_camera.window_bounds,
|
|
sizeof(rectangle2d)));
|
|
|
|
render_camera_build_frustum_bounds(camera, &frustum_bounds);
|
|
#ifdef HALO_VR
|
|
/* an eye's own, off-centre field; the scope's narrow one */
|
|
vr_render_frustum_bounds(&frustum_bounds);
|
|
#endif
|
|
|
|
if (screenshot_combined_index != NULL)
|
|
{
|
|
long tile_count;
|
|
|
|
tile_count = global_screenshot_count * global_screenshot_size;
|
|
if (tile_count > 0)
|
|
{
|
|
real tile_width;
|
|
real tile_height;
|
|
real_rectangle2d adjusted_bounds;
|
|
|
|
tile_width = (frustum_bounds.x1 - frustum_bounds.x0) / (real)tile_count;
|
|
tile_height = (frustum_bounds.y1 - frustum_bounds.y0) / (real)tile_count;
|
|
adjusted_bounds.x0 =
|
|
(real)screenshot_combined_index->x * tile_width + frustum_bounds.x0;
|
|
adjusted_bounds.y0 =
|
|
(real)(tile_count - screenshot_combined_index->y - 1) * tile_height + frustum_bounds.y0;
|
|
adjusted_bounds.x1 = adjusted_bounds.x0 + tile_width;
|
|
adjusted_bounds.y1 = adjusted_bounds.y0 + tile_height;
|
|
frustum_bounds = adjusted_bounds;
|
|
}
|
|
}
|
|
|
|
render_camera_build_frustum(camera, &frustum_bounds, &frustum, TRUE);
|
|
render_camera_build_frustum(
|
|
&window->rasterizer_camera,
|
|
&frustum_bounds,
|
|
&rasterizer_frustum,
|
|
TRUE);
|
|
|
|
/* (a mirror's camera assumes the whole screen, which the headset's
|
|
scope does not fill) */
|
|
if (main_get_window_count() == 1 && !VR_RENDER_SCOPE())
|
|
{
|
|
if (structure_visibility_find_mirror(camera, &frustum, &mirror))
|
|
{
|
|
short saved_cluster_index;
|
|
struct render_camera mirror_camera;
|
|
struct render_frustum mirror_frustum;
|
|
|
|
saved_cluster_index = (short)render.cluster_index;
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 225, window->render_camera.viewport_bounds.x0==0);
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 226, window->render_camera.viewport_bounds.y0==0);
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 227, window->render_camera.viewport_bounds.x1==RASTERIZER_TARGET_RENDER_PRIMARY_WIDTH);
|
|
match_assert("c:\\halo\\SOURCE\\render\\render.c", 228, window->render_camera.viewport_bounds.y1==RASTERIZER_TARGET_RENDER_PRIMARY_HEIGHT);
|
|
|
|
render_camera_mirror(camera, &mirror, &mirror_camera);
|
|
render_camera_build_frustum(
|
|
&mirror_camera,
|
|
&frustum_bounds,
|
|
&mirror_frustum,
|
|
TRUE);
|
|
|
|
rasterizer_profile_enable(FALSE);
|
|
render.cluster_index = mirror.cluster_index;
|
|
render_window(
|
|
NONE,
|
|
&mirror_camera,
|
|
&mirror_frustum,
|
|
&mirror_camera,
|
|
&mirror_frustum,
|
|
_render_target_secondary,
|
|
FALSE);
|
|
render.cluster_index = saved_cluster_index;
|
|
rasterizer_profile_enable(TRUE);
|
|
has_mirror = TRUE;
|
|
}
|
|
}
|
|
|
|
render_window(
|
|
window->local_player_index,
|
|
camera,
|
|
&frustum,
|
|
&window->rasterizer_camera,
|
|
&rasterizer_frustum,
|
|
_render_target_primary,
|
|
has_mirror);
|
|
|
|
return;
|
|
}
|
|
|
|
void render_frame(
|
|
struct render_window *windoze,
|
|
short window_count,
|
|
const point2d *screenshot_page_index,
|
|
const point2d *screenshot_index,
|
|
struct bitmap_data *screenshot_bitmap,
|
|
real time_delta_since_tick_sec)
|
|
{
|
|
struct rasterizer_frame_begin_parameters parameters;
|
|
short window_index;
|
|
struct render_window *window;
|
|
point2d screenshot_combined_index;
|
|
|
|
render.frame_index++;
|
|
render.time_delta_since_tick_sec = time_delta_since_tick_sec;
|
|
memset(¶meters, 0, sizeof(parameters));
|
|
/* continuous between ticks (render_interpolation.c) */
|
|
parameters.game_time_sec = render_interpolation_game_time_sec(game_time_get());
|
|
rasterizer_frame_begin(¶meters);
|
|
rasterizer_windows_begin();
|
|
|
|
for (window_index = 0; window_index < window_count; window_index++)
|
|
{
|
|
long window_type;
|
|
|
|
window = &windoze[window_index];
|
|
render.window_index = window_index;
|
|
if (window->console_window)
|
|
{
|
|
window_type = 0;
|
|
}
|
|
else if (window->local_player_index != NONE)
|
|
{
|
|
if (screenshot_index != NULL && screenshot_page_index != NULL)
|
|
{
|
|
screenshot_combined_index.x =
|
|
screenshot_page_index->x * global_screenshot_size + screenshot_index->x;
|
|
screenshot_combined_index.y =
|
|
screenshot_page_index->y * global_screenshot_size + screenshot_index->y;
|
|
}
|
|
|
|
#ifdef HALO_VR
|
|
vr_render_window_begin(window_index);
|
|
#endif
|
|
render_player_frame(
|
|
window,
|
|
screenshot_index != NULL ? &screenshot_combined_index : NULL);
|
|
#ifdef HALO_VR
|
|
vr_render_window_end(window_index);
|
|
#endif
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
window_type = 1;
|
|
}
|
|
|
|
#ifdef HALO_VR
|
|
vr_render_window_begin(window_index);
|
|
#endif
|
|
render_nonplayer_frame(window, window_type);
|
|
#ifdef HALO_VR
|
|
vr_render_window_end(window_index);
|
|
#endif
|
|
}
|
|
|
|
halo_screen_ui_offset(TRUE);
|
|
progress_bar_eachframe();
|
|
halo_screen_ui_offset(FALSE);
|
|
rasterizer_windows_end();
|
|
rasterizer_frame_end();
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|