Skip to content

Commit f67a42d

Browse files
authored
Merge pull request #1319 from asarium/fix/envmapHandling
Improve handling of environment map redrawing
2 parents 52b48bd + b9413a2 commit f67a42d

File tree

8 files changed

+261
-206
lines changed

8 files changed

+261
-206
lines changed

code/graphics/opengl/gropengldraw.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1912,6 +1912,7 @@ void gr_opengl_scene_texture_begin()
19121912
}
19131913

19141914
GR_DEBUG_SCOPE("Begin scene texture");
1915+
TRACE_SCOPE(tracing::SceneTextureBegin);
19151916

19161917
GL_state.PushFramebufferState();
19171918
GL_state.BindFrameBuffer(Scene_framebuffer);
@@ -1956,12 +1957,14 @@ void gr_opengl_scene_texture_begin()
19561957
float time_buffer = 0.0f;
19571958
void gr_opengl_scene_texture_end()
19581959
{
1959-
GR_DEBUG_SCOPE("End scene texture");
19601960

19611961
if ( !Scene_framebuffer_in_frame ) {
19621962
return;
19631963
}
19641964

1965+
GR_DEBUG_SCOPE("End scene texture");
1966+
TRACE_SCOPE(tracing::SceneTextureEnd);
1967+
19651968
time_buffer+=flFrametime;
19661969
if(time_buffer>0.03f)
19671970
{

code/parse/sexp.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,11 +3505,6 @@ int get_sexp()
35053505
case OP_MISSION_SET_NEBULA:
35063506
// set flag for WMC
35073507
Nebula_sexp_used = true;
3508-
Dynamic_environment = true;
3509-
break;
3510-
3511-
case OP_MISSION_SET_SUBSPACE:
3512-
Dynamic_environment = true;
35133508
break;
35143509

35153510
case OP_WARP_EFFECT:
@@ -3529,7 +3524,6 @@ int get_sexp()
35293524
// model is argument #1
35303525
n = CDR(start);
35313526
do_preload_for_arguments(sexp_set_skybox_model_preload, n, arg_handler);
3532-
Dynamic_environment = true;
35333527
break;
35343528

35353529
case OP_TURRET_CHANGE_WEAPON:
@@ -3541,13 +3535,11 @@ int get_sexp()
35413535
case OP_ADD_SUN_BITMAP:
35423536
n = CDR(start);
35433537
do_preload_for_arguments(stars_preload_sun_bitmap, n, arg_handler);
3544-
Dynamic_environment = true;
35453538
break;
35463539

35473540
case OP_ADD_BACKGROUND_BITMAP:
35483541
n = CDR(start);
35493542
do_preload_for_arguments(stars_preload_background_bitmap, n, arg_handler);
3550-
Dynamic_environment = true;
35513543
break;
35523544

35533545
case OP_TECH_ADD_INTEL_XSTR:
@@ -12157,7 +12149,8 @@ void sexp_mission_set_subspace(int n)
1215712149
Game_subspace_effect = 0;
1215812150
game_stop_subspace_ambient_sound();
1215912151
}
12160-
12152+
12153+
stars_set_dynamic_environment(Game_subspace_effect != 0);
1216112154
The_mission.flags.set(Mission::Mission_Flags::Subspace, Game_subspace_effect != 0);
1216212155
}
1216312156

code/starfield/starfield.cpp

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ int Num_debris_nebula = 0;
177177
bool Dynamic_environment = false;
178178
bool Motion_debris_override = false;
179179

180+
static int Default_env_map = -1;
181+
static int Mission_env_map = -1;
182+
static bool Env_cubemap_drawn = false;
183+
180184
void stars_release_debris_vclips(debris_vclip *vclips)
181185
{
182186
int i;
@@ -702,6 +706,10 @@ void stars_init()
702706
parse_startbl("stars.tbl");
703707

704708
parse_modular_table("*-str.tbm", parse_startbl);
709+
710+
if (Cmdline_env) {
711+
ENVMAP = Default_env_map = bm_load("cubemap");
712+
}
705713
}
706714

707715
// call only from game_shutdown()!!
@@ -778,6 +786,41 @@ void stars_pre_level_init(bool clear_backgrounds)
778786

779787
Dynamic_environment = false;
780788
Motion_debris_override = false;
789+
790+
Env_cubemap_drawn = false;
791+
}
792+
793+
// setup the render target ready for this mission's environment map
794+
static void environment_map_gen()
795+
{
796+
const int size = 512;
797+
int gen_flags = (BMP_FLAG_RENDER_TARGET_STATIC | BMP_FLAG_CUBEMAP | BMP_FLAG_RENDER_TARGET_MIPMAP);
798+
799+
if ( !Cmdline_env ) {
800+
return;
801+
}
802+
803+
if (gr_screen.envmap_render_target >= 0) {
804+
if ( !bm_release(gr_screen.envmap_render_target, 1) ) {
805+
Warning(LOCATION, "Unable to release environment map render target.");
806+
}
807+
808+
gr_screen.envmap_render_target = -1;
809+
}
810+
811+
if ( Dynamic_environment || (The_mission.flags[Mission::Mission_Flags::Subspace]) ) {
812+
Dynamic_environment = true;
813+
gen_flags &= ~BMP_FLAG_RENDER_TARGET_STATIC;
814+
gen_flags |= BMP_FLAG_RENDER_TARGET_DYNAMIC;
815+
}
816+
// bail if we are going to be static, and have an envmap specified already
817+
else if ( strlen(The_mission.envmap_name) ) {
818+
// Load the mission map so we can use it later
819+
Mission_env_map = bm_load(The_mission.envmap_name);
820+
return;
821+
}
822+
823+
gr_screen.envmap_render_target = bm_make_render_target(size, size, gen_flags);
781824
}
782825

783826
// call this in game_post_level_init() so we know whether we're running in full nebula mode or not
@@ -853,6 +896,23 @@ void stars_post_level_init()
853896
}
854897

855898
starfield_generate_bitmap_buffers();
899+
900+
environment_map_gen();
901+
}
902+
903+
void stars_level_close() {
904+
if (gr_screen.envmap_render_target >= 0) {
905+
if ( bm_release(gr_screen.envmap_render_target, 1) ) {
906+
gr_screen.envmap_render_target = -1;
907+
}
908+
}
909+
910+
if (Mission_env_map >= 0) {
911+
bm_release(Mission_env_map);
912+
Mission_env_map = -1;
913+
}
914+
915+
ENVMAP = Default_env_map;
856916
}
857917

858918

@@ -2092,6 +2152,9 @@ void stars_set_background_model(const char *model_name, const char *texture_name
20922152
Nmodel_instance_num = model_create_instance(false, Nmodel_num);
20932153
}
20942154
}
2155+
2156+
// Since we have a new skybox we need to rerender the environment map
2157+
stars_invalidate_environment_map();
20952158
}
20962159

20972160
// call this to set a specific orientation for the background
@@ -2216,6 +2279,9 @@ int stars_add_sun_entry(starfield_list_entry *sun_ptr)
22162279
}
22172280
}
22182281

2282+
// The background changed so we need to invalidate the environment map
2283+
stars_invalidate_environment_map();
2284+
22192285
// now check if we can make use of a previously discarded instance entry
22202286
// this should never happen with FRED
22212287
if ( !Fred_running ) {
@@ -2275,6 +2341,9 @@ int stars_add_bitmap_entry(starfield_list_entry *sle)
22752341
}
22762342
}
22772343

2344+
// The background changed so we need to invalidate the environment map
2345+
stars_invalidate_environment_map();
2346+
22782347
// now check if we can make use of a previously discarded instance entry
22792348
for (int i = 0; i < (int)Starfield_bitmap_instances.size(); i++) {
22802349
if ( Starfield_bitmap_instances[i].star_bitmap_index < 0 ) {
@@ -2379,6 +2448,9 @@ void stars_mark_instance_unused(int index, bool is_a_sun)
23792448
delete [] Starfield_bitmap_instances[index].verts;
23802449
Starfield_bitmap_instances[index].verts = NULL;
23812450
}
2451+
2452+
// The background changed so we need to invalidate the environment map
2453+
stars_invalidate_environment_map();
23822454
}
23832455

23842456
// retrieves the name from starfield_bitmap for the instance index
@@ -2427,6 +2499,8 @@ void stars_set_nebula(bool activate)
24272499
Debris_vclips = Debris_vclips_normal;
24282500
HUD_contrast = 0;
24292501
}
2502+
// We need to reload the environment map now
2503+
stars_invalidate_environment_map();
24302504
}
24312505

24322506
// retrieves the name from starfield_bitmap, really only used by FRED2
@@ -2663,3 +2737,149 @@ void stars_pack_backgrounds()
26632737
}
26642738
}
26652739
}
2740+
2741+
static void render_environment(int i, vec3d *eye_pos, matrix *new_orient, float new_zoom)
2742+
{
2743+
bm_set_render_target(gr_screen.envmap_render_target, i);
2744+
2745+
gr_clear();
2746+
2747+
g3_set_view_matrix( eye_pos, new_orient, new_zoom );
2748+
2749+
gr_set_proj_matrix( PI_2 * new_zoom, 1.0f, Min_draw_distance, Max_draw_distance);
2750+
gr_set_view_matrix( &Eye_position, &Eye_matrix );
2751+
2752+
if ( Game_subspace_effect ) {
2753+
stars_draw(0, 0, 0, 1, 1);
2754+
} else {
2755+
stars_draw(0, 1, 1, 0, 1);
2756+
}
2757+
2758+
gr_end_view_matrix();
2759+
gr_end_proj_matrix();
2760+
}
2761+
2762+
void stars_setup_environment_mapping(camid cid) {
2763+
matrix new_orient = IDENTITY_MATRIX;
2764+
2765+
extern float View_zoom;
2766+
float old_zoom = View_zoom, new_zoom = 1.0f;//0.925f;
2767+
int i = 0;
2768+
2769+
if(!cid.isValid())
2770+
return;
2771+
2772+
vec3d cam_pos;
2773+
matrix cam_orient;
2774+
cid.getCamera()->get_info(&cam_pos, &cam_orient);
2775+
2776+
// prefer the mission specified envmap over the static-generated envmap, but
2777+
// the dynamic envmap should always get preference if in a subspace mission
2778+
if ( !Dynamic_environment && Mission_env_map >= 0 ) {
2779+
ENVMAP = Mission_env_map;
2780+
return;
2781+
}
2782+
2783+
if (gr_screen.envmap_render_target < 0) {
2784+
if (ENVMAP >= 0)
2785+
return;
2786+
2787+
if (Mission_env_map >= 0) {
2788+
ENVMAP = Mission_env_map;
2789+
} else {
2790+
ENVMAP = Default_env_map;
2791+
}
2792+
2793+
return;
2794+
}
2795+
2796+
if (Env_cubemap_drawn) {
2797+
// Nothing to do here anymore
2798+
return;
2799+
}
2800+
2801+
GR_DEBUG_SCOPE("Environment Mapping");
2802+
TRACE_SCOPE(tracing::EnvironmentMapping);
2803+
2804+
ENVMAP = gr_screen.envmap_render_target;
2805+
2806+
/*
2807+
* Envmap matrix setup -- left-handed
2808+
* -------------------------------------------------
2809+
* Face -- Forward Up Right
2810+
* px +X +Y -Z
2811+
* nx -X +Y +Z
2812+
* py +Y -Z +X
2813+
* ny -Y +Z +X
2814+
* pz +Z +Y +X
2815+
* nz -Z +Y -X
2816+
*/
2817+
// NOTE: OpenGL needs up/down reversed
2818+
2819+
// Save the previous render target so we can reset it once we are done here
2820+
auto previous_target = gr_screen.rendering_to_texture;
2821+
2822+
// face 1 (px / right)
2823+
memset( &new_orient, 0, sizeof(matrix) );
2824+
new_orient.vec.fvec.xyz.x = 1.0f;
2825+
new_orient.vec.uvec.xyz.y = 1.0f;
2826+
new_orient.vec.rvec.xyz.z = -1.0f;
2827+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2828+
i++; // bump!
2829+
2830+
// face 2 (nx / left)
2831+
memset( &new_orient, 0, sizeof(matrix) );
2832+
new_orient.vec.fvec.xyz.x = -1.0f;
2833+
new_orient.vec.uvec.xyz.y = 1.0f;
2834+
new_orient.vec.rvec.xyz.z = 1.0f;
2835+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2836+
i++; // bump!
2837+
2838+
// face 3 (py / up)
2839+
memset( &new_orient, 0, sizeof(matrix) );
2840+
new_orient.vec.fvec.xyz.y = (gr_screen.mode == GR_OPENGL) ? 1.0f : -1.0f;
2841+
new_orient.vec.uvec.xyz.z = (gr_screen.mode == GR_OPENGL) ? -1.0f : 1.0f;
2842+
new_orient.vec.rvec.xyz.x = 1.0f;
2843+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2844+
i++; // bump!
2845+
2846+
// face 4 (ny / down)
2847+
memset( &new_orient, 0, sizeof(matrix) );
2848+
new_orient.vec.fvec.xyz.y = (gr_screen.mode == GR_OPENGL) ? -1.0f : 1.0f;
2849+
new_orient.vec.uvec.xyz.z = (gr_screen.mode == GR_OPENGL) ? 1.0f : -1.0f;
2850+
new_orient.vec.rvec.xyz.x = 1.0f;
2851+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2852+
i++; // bump!
2853+
2854+
// face 5 (pz / forward)
2855+
memset( &new_orient, 0, sizeof(matrix) );
2856+
new_orient.vec.fvec.xyz.z = 1.0f;
2857+
new_orient.vec.uvec.xyz.y = 1.0f;
2858+
new_orient.vec.rvec.xyz.x = 1.0f;
2859+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2860+
i++; // bump!
2861+
2862+
// face 6 (nz / back)
2863+
memset( &new_orient, 0, sizeof(matrix) );
2864+
new_orient.vec.fvec.xyz.z = -1.0f;
2865+
new_orient.vec.uvec.xyz.y = 1.0f;
2866+
new_orient.vec.rvec.xyz.x = -1.0f;
2867+
render_environment(i, &cam_pos, &new_orient, new_zoom);
2868+
2869+
2870+
// we're done, so now reset
2871+
bm_set_render_target(previous_target);
2872+
g3_set_view_matrix( &cam_pos, &cam_orient, old_zoom );
2873+
2874+
if ( !Dynamic_environment ) {
2875+
Env_cubemap_drawn = true;
2876+
}
2877+
}
2878+
void stars_set_dynamic_environment(bool dynamic) {
2879+
Dynamic_environment = dynamic;
2880+
stars_invalidate_environment_map();
2881+
}
2882+
void stars_invalidate_environment_map() {
2883+
// This will cause a redraw in the next frame
2884+
Env_cubemap_drawn = false;
2885+
}

code/starfield/starfield.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ extern int Cur_background;
4747
extern background_t Backgrounds[MAX_BACKGROUNDS];
4848
extern int Nmodel_flags;
4949

50-
extern bool Dynamic_environment;
5150
extern bool Motion_debris_override;
5251

5352
void stars_swap_backgrounds(int idx1, int idx2);
@@ -94,6 +93,8 @@ void stars_pre_level_init(bool clear_backgrounds = true);
9493
// call this in game_post_level_init() so we know whether we're running in full nebula mode or not
9594
void stars_post_level_init();
9695

96+
void stars_level_close();
97+
9798
// draw background bitmaps
9899
void stars_draw_background();
99100

@@ -145,4 +146,19 @@ void stars_load_first_valid_background();
145146
int stars_get_first_valid_background();
146147
void stars_load_background(int background_idx);
147148

149+
void stars_setup_environment_mapping(camid cid);
150+
151+
/**
152+
* @brief Enabled dynamic rendering of environment map
153+
* @param dynamic @c true if the environment should be dynamic
154+
*/
155+
void stars_set_dynamic_environment(bool dynamic);
156+
157+
/**
158+
* @brief Invalidates the current environment map
159+
*
160+
* This will cause a redraw of the environment map in the next frame
161+
*/
162+
void stars_invalidate_environment_map();
163+
148164
#endif

0 commit comments

Comments
 (0)