mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
move red-blue-stereo support lower; cache cull results between left and right stereo channels
This commit is contained in:
parent
748a50fe9e
commit
90902c5cca
@ -156,6 +156,13 @@ ConfigVariableBool red_blue_stereo
|
|||||||
"by default, if the framebuffer does not support true stereo "
|
"by default, if the framebuffer does not support true stereo "
|
||||||
"rendering."));
|
"rendering."));
|
||||||
|
|
||||||
|
ConfigVariableString red_blue_stereo_colors
|
||||||
|
("red-blue-stereo-colors", "red blue",
|
||||||
|
PRC_DESC("This defines the color channels that are used for the left and "
|
||||||
|
"right eye, respectively, for red-blue-stereo mode. This should "
|
||||||
|
"be a two-word string, where each word is one of 'red', 'blue', "
|
||||||
|
"'green', or 'alpha'."));
|
||||||
|
|
||||||
ConfigVariableBool invert_red_blue_stereo
|
ConfigVariableBool invert_red_blue_stereo
|
||||||
("invert-red-blue-stereo", false,
|
("invert-red-blue-stereo", false,
|
||||||
PRC_DESC("When this is true, the red and blue colors of red-blue stereo mode "
|
PRC_DESC("When this is true, the red and blue colors of red-blue stereo mode "
|
||||||
|
@ -58,6 +58,7 @@ extern EXPCL_PANDA ConfigVariableBool support_rescale_normal;
|
|||||||
extern EXPCL_PANDA ConfigVariableBool copy_texture_inverted;
|
extern EXPCL_PANDA ConfigVariableBool copy_texture_inverted;
|
||||||
extern EXPCL_PANDA ConfigVariableBool window_inverted;
|
extern EXPCL_PANDA ConfigVariableBool window_inverted;
|
||||||
extern EXPCL_PANDA ConfigVariableBool red_blue_stereo;
|
extern EXPCL_PANDA ConfigVariableBool red_blue_stereo;
|
||||||
|
extern EXPCL_PANDA ConfigVariableString red_blue_stereo_colors;
|
||||||
extern EXPCL_PANDA ConfigVariableBool invert_red_blue_stereo;
|
extern EXPCL_PANDA ConfigVariableBool invert_red_blue_stereo;
|
||||||
extern EXPCL_PANDA ConfigVariableBool depth_offset_decals;
|
extern EXPCL_PANDA ConfigVariableBool depth_offset_decals;
|
||||||
extern EXPCL_PANDA ConfigVariableBool auto_generate_mipmaps;
|
extern EXPCL_PANDA ConfigVariableBool auto_generate_mipmaps;
|
||||||
|
@ -689,32 +689,7 @@ flip_frame() {
|
|||||||
do_flip_frame();
|
do_flip_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsEngine::render_subframe
|
|
||||||
// Access: Published
|
|
||||||
// Description: Performs a complete cull and draw pass for one
|
|
||||||
// particular display region. This is normally useful
|
|
||||||
// only for special effects, like shaders, that require
|
|
||||||
// a complete offscreen render pass before they can
|
|
||||||
// complete.
|
|
||||||
//
|
|
||||||
// This always executes completely within the calling
|
|
||||||
// thread, regardless of the threading model in use.
|
|
||||||
// Thus, it must always be called from the draw thread,
|
|
||||||
// whichever thread that may be.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void GraphicsEngine::
|
|
||||||
render_subframe(GraphicsOutput *win, DisplayRegion *dr,
|
|
||||||
bool cull_sorting) {
|
|
||||||
if (cull_sorting) {
|
|
||||||
cull_to_bins(win, dr);
|
|
||||||
} else {
|
|
||||||
cull_and_draw_together(win, dr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsEngine::add_callback
|
// Function: GraphicsEngine::add_callback
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -826,8 +801,8 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsEngine::cull_and_draw_together
|
// Function: GraphicsEngine::cull_and_draw_together
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: This variant of cull_and_draw_together() is called
|
// Description: Called only from within the inner loop in
|
||||||
// only by render_subframe().
|
// cull_and_draw_together(), above.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsEngine::
|
void GraphicsEngine::
|
||||||
cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
|
cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
|
||||||
@ -863,6 +838,11 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsEngine::
|
void GraphicsEngine::
|
||||||
cull_to_bins(const GraphicsEngine::Windows &wlist) {
|
cull_to_bins(const GraphicsEngine::Windows &wlist) {
|
||||||
|
// Keep track of the cameras we have already used in this thread to
|
||||||
|
// render DisplayRegions.
|
||||||
|
typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
|
||||||
|
AlreadyCulled already_culled;
|
||||||
|
|
||||||
Windows::const_iterator wi;
|
Windows::const_iterator wi;
|
||||||
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
|
||||||
GraphicsOutput *win = (*wi);
|
GraphicsOutput *win = (*wi);
|
||||||
@ -871,7 +851,26 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
|
|||||||
for (int i = 0; i < num_display_regions; ++i) {
|
for (int i = 0; i < num_display_regions; ++i) {
|
||||||
DisplayRegion *dr = win->get_active_display_region(i);
|
DisplayRegion *dr = win->get_active_display_region(i);
|
||||||
if (dr != (DisplayRegion *)NULL) {
|
if (dr != (DisplayRegion *)NULL) {
|
||||||
cull_to_bins(win, dr);
|
NodePath camera = dr->get_camera();
|
||||||
|
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, NULL)).first;
|
||||||
|
if ((*aci).second == NULL) {
|
||||||
|
// We have not used this camera already in this thread.
|
||||||
|
// Perform the cull operation.
|
||||||
|
(*aci).second = dr;
|
||||||
|
cull_to_bins(win, dr);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// We have already culled a scene using this camera in
|
||||||
|
// this thread, and now we're being asked to cull another
|
||||||
|
// scene using the same camera. (Maybe this represents
|
||||||
|
// two different DisplayRegions for the left and right
|
||||||
|
// channels of a stereo image.) Of course, the cull
|
||||||
|
// result will be the same, so just use the result from
|
||||||
|
// the other DisplayRegion.
|
||||||
|
DisplayRegion *other_dr = (*aci).second;
|
||||||
|
dr->set_cull_result(other_dr->get_cull_result(),
|
||||||
|
setup_scene(win->get_gsg(), dr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,9 +880,8 @@ cull_to_bins(const GraphicsEngine::Windows &wlist) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsEngine::cull_to_bins
|
// Function: GraphicsEngine::cull_to_bins
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: This variant of cull_to_bins() is called
|
// Description: Called only within the inner loop of cull_to_bins(),
|
||||||
// by render_subframe(), as well as within the
|
// above.
|
||||||
// implementation of cull_to_bins(), above.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsEngine::
|
void GraphicsEngine::
|
||||||
cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
|
cull_to_bins(GraphicsOutput *win, DisplayRegion *dr) {
|
||||||
@ -1178,31 +1176,6 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
|
|||||||
initial_state = initial_state->compose(get_invert_polygon_state());
|
initial_state = initial_state->compose(get_invert_polygon_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->get_red_blue_stereo()) {
|
|
||||||
// If the window has red-blue stereo mode, apply the appropriate
|
|
||||||
// color mask to the initial state.
|
|
||||||
switch (dr->get_stereo_channel()) {
|
|
||||||
case Lens::SC_left:
|
|
||||||
if (invert_red_blue_stereo) {
|
|
||||||
initial_state = initial_state->compose(get_blue_channel_state());
|
|
||||||
} else {
|
|
||||||
initial_state = initial_state->compose(get_red_channel_state());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Lens::SC_right:
|
|
||||||
if (invert_red_blue_stereo) {
|
|
||||||
initial_state = initial_state->compose(get_red_channel_state());
|
|
||||||
} else {
|
|
||||||
initial_state = initial_state->compose(get_blue_channel_state());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Lens::SC_both:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scene_setup->set_display_region(dr);
|
scene_setup->set_display_region(dr);
|
||||||
scene_setup->set_viewport_size(dr->get_pixel_width(), dr->get_pixel_height());
|
scene_setup->set_viewport_size(dr->get_pixel_width(), dr->get_pixel_height());
|
||||||
scene_setup->set_scene_root(scene_root);
|
scene_setup->set_scene_root(scene_root);
|
||||||
@ -1540,44 +1513,6 @@ get_invert_polygon_state() {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsEngine::get_red_channel_state
|
|
||||||
// Access: Protected, Static
|
|
||||||
// Description: Returns a RenderState for rendering only to the red
|
|
||||||
// channel of the color buffer, for implementing
|
|
||||||
// red-blue stereo.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
const RenderState *GraphicsEngine::
|
|
||||||
get_red_channel_state() {
|
|
||||||
// Once someone asks for this pointer, we hold its reference count
|
|
||||||
// and never free it.
|
|
||||||
static CPT(RenderState) state = (const RenderState *)NULL;
|
|
||||||
if (state == (const RenderState *)NULL) {
|
|
||||||
state = RenderState::make(ColorWriteAttrib::make(ColorWriteAttrib::C_red));
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsEngine::get_blue_channel_state
|
|
||||||
// Access: Protected, Static
|
|
||||||
// Description: Returns a RenderState for rendering only to the blue
|
|
||||||
// channel of the color buffer, for implementing
|
|
||||||
// red-blue stereo.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
const RenderState *GraphicsEngine::
|
|
||||||
get_blue_channel_state() {
|
|
||||||
// Once someone asks for this pointer, we hold its reference count
|
|
||||||
// and never free it.
|
|
||||||
static CPT(RenderState) state = (const RenderState *)NULL;
|
|
||||||
if (state == (const RenderState *)NULL) {
|
|
||||||
state = RenderState::make(ColorWriteAttrib::make(ColorWriteAttrib::C_blue));
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsEngine::get_window_renderer
|
// Function: GraphicsEngine::get_window_renderer
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -96,9 +96,6 @@ PUBLISHED:
|
|||||||
void open_windows();
|
void open_windows();
|
||||||
void sync_frame();
|
void sync_frame();
|
||||||
void flip_frame();
|
void flip_frame();
|
||||||
|
|
||||||
void render_subframe(GraphicsOutput *win, DisplayRegion *dr,
|
|
||||||
bool cull_sorting);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ThreadState {
|
enum ThreadState {
|
||||||
@ -180,8 +177,6 @@ private:
|
|||||||
#endif // DO_PSTATS
|
#endif // DO_PSTATS
|
||||||
|
|
||||||
static const RenderState *get_invert_polygon_state();
|
static const RenderState *get_invert_polygon_state();
|
||||||
static const RenderState *get_red_channel_state();
|
|
||||||
static const RenderState *get_blue_channel_state();
|
|
||||||
|
|
||||||
// The WindowRenderer class records the stages of the pipeline that
|
// The WindowRenderer class records the stages of the pipeline that
|
||||||
// each thread (including the main thread, a.k.a. "app") should
|
// each thread (including the main thread, a.k.a. "app") should
|
||||||
|
@ -231,16 +231,29 @@ get_inverted() const {
|
|||||||
// Description: Enables red-blue stereo mode on this particular
|
// Description: Enables red-blue stereo mode on this particular
|
||||||
// window. When red-blue stereo mode is in effect,
|
// window. When red-blue stereo mode is in effect,
|
||||||
// DisplayRegions that have the "left" channel set will
|
// DisplayRegions that have the "left" channel set will
|
||||||
// render in the red channel only, while DisplayRegions
|
// render in the red (or specified) channel only, while
|
||||||
// that have the "right" channel set will render in the
|
// DisplayRegions that have the "right" channel set will
|
||||||
// blue channel only.
|
// render in the blue (or specified) channel only.
|
||||||
|
//
|
||||||
|
// The remaining two parameters specify the particular
|
||||||
|
// color channel(s) to associate with each eye. Use the
|
||||||
|
// bits defined in ColorWriteAttrib::Channels.
|
||||||
//
|
//
|
||||||
// This can be used to achieve a cheesy stereo mode in
|
// This can be used to achieve a cheesy stereo mode in
|
||||||
// the absence of hardware-supported stereo.
|
// the absence of hardware-supported stereo.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void GraphicsOutput::
|
INLINE void GraphicsOutput::
|
||||||
set_red_blue_stereo(bool red_blue_stereo) {
|
set_red_blue_stereo(bool red_blue_stereo,
|
||||||
|
unsigned int left_eye_color_mask,
|
||||||
|
unsigned int right_eye_color_mask) {
|
||||||
_red_blue_stereo = red_blue_stereo;
|
_red_blue_stereo = red_blue_stereo;
|
||||||
|
if (_red_blue_stereo) {
|
||||||
|
_left_eye_color_mask = left_eye_color_mask;
|
||||||
|
_right_eye_color_mask = right_eye_color_mask;
|
||||||
|
} else {
|
||||||
|
_left_eye_color_mask = 0x0f;
|
||||||
|
_right_eye_color_mask = 0x0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -254,6 +267,32 @@ get_red_blue_stereo() const {
|
|||||||
return _red_blue_stereo;
|
return _red_blue_stereo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GraphicsOutput::get_left_eye_color_mask
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the color mask in effect when rendering a
|
||||||
|
// left-eye view in red_blue stereo mode. This is one
|
||||||
|
// or more bits defined in ColorWriteAttrib::Channels.
|
||||||
|
// See set_red_blue_stereo().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE unsigned int GraphicsOutput::
|
||||||
|
get_left_eye_color_mask() const {
|
||||||
|
return _left_eye_color_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GraphicsOutput::get_right_eye_color_mask
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the color mask in effect when rendering a
|
||||||
|
// right-eye view in red_blue stereo mode. This is one
|
||||||
|
// or more bits defined in ColorWriteAttrib::Channels.
|
||||||
|
// See set_red_blue_stereo().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE unsigned int GraphicsOutput::
|
||||||
|
get_right_eye_color_mask() const {
|
||||||
|
return _right_eye_color_mask;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsOutput::is_stereo
|
// Function: GraphicsOutput::is_stereo
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -89,6 +89,8 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
|||||||
_one_shot = false;
|
_one_shot = false;
|
||||||
_inverted = window_inverted;
|
_inverted = window_inverted;
|
||||||
_red_blue_stereo = false;
|
_red_blue_stereo = false;
|
||||||
|
_left_eye_color_mask = 0x0f;
|
||||||
|
_right_eye_color_mask = 0x0f;
|
||||||
_delete_flag = false;
|
_delete_flag = false;
|
||||||
_texture_card = 0;
|
_texture_card = 0;
|
||||||
_trigger_copy = false;
|
_trigger_copy = false;
|
||||||
|
@ -113,8 +113,13 @@ PUBLISHED:
|
|||||||
void set_inverted(bool inverted);
|
void set_inverted(bool inverted);
|
||||||
INLINE bool get_inverted() const;
|
INLINE bool get_inverted() const;
|
||||||
|
|
||||||
INLINE void set_red_blue_stereo(bool red_blue_stereo);
|
INLINE void set_red_blue_stereo(bool red_blue_stereo,
|
||||||
|
unsigned int left_eye_color_mask,
|
||||||
|
unsigned int right_eye_color_mask);
|
||||||
INLINE bool get_red_blue_stereo() const;
|
INLINE bool get_red_blue_stereo() const;
|
||||||
|
INLINE unsigned int get_left_eye_color_mask() const;
|
||||||
|
INLINE unsigned int get_right_eye_color_mask() const;
|
||||||
|
|
||||||
INLINE bool is_stereo() const;
|
INLINE bool is_stereo() const;
|
||||||
|
|
||||||
INLINE void clear_delete_flag();
|
INLINE void clear_delete_flag();
|
||||||
@ -240,6 +245,8 @@ protected:
|
|||||||
bool _one_shot;
|
bool _one_shot;
|
||||||
bool _inverted;
|
bool _inverted;
|
||||||
bool _red_blue_stereo;
|
bool _red_blue_stereo;
|
||||||
|
unsigned int _left_eye_color_mask;
|
||||||
|
unsigned int _right_eye_color_mask;
|
||||||
bool _delete_flag;
|
bool _delete_flag;
|
||||||
|
|
||||||
// These weak pointers are used to keep track of whether the
|
// These weak pointers are used to keep track of whether the
|
||||||
|
@ -559,24 +559,6 @@ get_global_gsg() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsStateGuardian::set_scene
|
|
||||||
// Access: Public
|
|
||||||
// Description: Sets the SceneSetup object that indicates the initial
|
|
||||||
// camera position, etc. This must be called before
|
|
||||||
// traversal begins. Returns true if the scene is
|
|
||||||
// acceptable, false if something's wrong.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE bool GraphicsStateGuardian::
|
|
||||||
set_scene(SceneSetup *scene_setup) {
|
|
||||||
_scene_setup = scene_setup;
|
|
||||||
_current_lens = scene_setup->get_lens();
|
|
||||||
if (_current_lens == (Lens *)NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return prepare_lens(scene_setup->get_display_region()->get_stereo_channel());
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsStateGuardian::get_scene
|
// Function: GraphicsStateGuardian::get_scene
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -605,39 +587,6 @@ clear(DisplayRegion *dr) {
|
|||||||
pop_display_region(old_dr);
|
pop_display_region(old_dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsStateGuardian::force_normals
|
|
||||||
// Access: Public
|
|
||||||
// Description: Temporarily forces the GSG to issue normals to the
|
|
||||||
// graphics pipe. Normally, the GSG will issue normals
|
|
||||||
// only if lighting is on.
|
|
||||||
//
|
|
||||||
// This call must be matched with exactly one call to
|
|
||||||
// undo_force_normals().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE int GraphicsStateGuardian::
|
|
||||||
force_normals() {
|
|
||||||
nassertr(_force_normals >= 0, _force_normals);
|
|
||||||
_force_normals++;
|
|
||||||
return _force_normals;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GraphicsStateGuardian::undo_force_normals
|
|
||||||
// Access: Public
|
|
||||||
// Description: Undoes the effect of a previous call to
|
|
||||||
// force_normals().
|
|
||||||
//
|
|
||||||
// This call must be matched with one-to-one with a
|
|
||||||
// previous call to force_normals().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE int GraphicsStateGuardian::
|
|
||||||
undo_force_normals() {
|
|
||||||
_force_normals--;
|
|
||||||
nassertr(_force_normals >= 0, _force_normals);
|
|
||||||
return _force_normals;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsStateGuardian::reset_if_new
|
// Function: GraphicsStateGuardian::reset_if_new
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "geomTristrips.h"
|
#include "geomTristrips.h"
|
||||||
#include "geomTrifans.h"
|
#include "geomTrifans.h"
|
||||||
#include "geomLinestrips.h"
|
#include "geomLinestrips.h"
|
||||||
|
#include "colorWriteAttrib.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -283,11 +284,13 @@ reset() {
|
|||||||
_scene_setup = _scene_null;
|
_scene_setup = _scene_null;
|
||||||
|
|
||||||
_buffer_mask = 0;
|
_buffer_mask = 0;
|
||||||
|
_color_write_mask = ColorWriteAttrib::C_all;
|
||||||
_color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
|
_color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
_depth_clear_value = 1.0f;
|
_depth_clear_value = 1.0f;
|
||||||
_stencil_clear_value = 0.0f;
|
_stencil_clear_value = 0.0f;
|
||||||
_accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
|
_accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
_force_normals = 0;
|
|
||||||
|
_is_stereo = get_properties().is_stereo();
|
||||||
|
|
||||||
_has_scene_graph_color = false;
|
_has_scene_graph_color = false;
|
||||||
_transform_stale = true;
|
_transform_stale = true;
|
||||||
@ -345,6 +348,39 @@ get_render_buffer(int buffer_type) {
|
|||||||
return RenderBuffer(this, buffer_type & _buffer_mask);
|
return RenderBuffer(this, buffer_type & _buffer_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GraphicsStateGuardian::set_scene
|
||||||
|
// Access: Public
|
||||||
|
// Description: Sets the SceneSetup object that indicates the initial
|
||||||
|
// camera position, etc. This must be called before
|
||||||
|
// traversal begins. Returns true if the scene is
|
||||||
|
// acceptable, false if something's wrong.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool GraphicsStateGuardian::
|
||||||
|
set_scene(SceneSetup *scene_setup) {
|
||||||
|
_scene_setup = scene_setup;
|
||||||
|
_current_lens = scene_setup->get_lens();
|
||||||
|
if (_current_lens == (Lens *)NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DisplayRegion *dr = scene_setup->get_display_region();
|
||||||
|
Lens::StereoChannel stereo_channel = dr->get_stereo_channel();
|
||||||
|
switch (stereo_channel) {
|
||||||
|
case Lens::SC_left:
|
||||||
|
_color_write_mask = dr->get_window()->get_left_eye_color_mask();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Lens::SC_right:
|
||||||
|
_color_write_mask = dr->get_window()->get_right_eye_color_mask();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Lens::SC_both:
|
||||||
|
_color_write_mask = ColorWriteAttrib::C_all;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepare_lens(stereo_channel);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GraphicsStateGuardian::get_prepared_objects
|
// Function: GraphicsStateGuardian::get_prepared_objects
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -125,7 +125,7 @@ PUBLISHED:
|
|||||||
INLINE static GraphicsStateGuardian *get_global_gsg();
|
INLINE static GraphicsStateGuardian *get_global_gsg();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INLINE bool set_scene(SceneSetup *scene_setup);
|
bool set_scene(SceneSetup *scene_setup);
|
||||||
INLINE SceneSetup *get_scene() const;
|
INLINE SceneSetup *get_scene() const;
|
||||||
|
|
||||||
virtual PreparedGraphicsObjects *get_prepared_objects();
|
virtual PreparedGraphicsObjects *get_prepared_objects();
|
||||||
@ -163,9 +163,6 @@ public:
|
|||||||
virtual void prepare_display_region()=0;
|
virtual void prepare_display_region()=0;
|
||||||
virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
|
virtual bool prepare_lens(Lens::StereoChannel stereo_channel);
|
||||||
|
|
||||||
INLINE int force_normals();
|
|
||||||
INLINE int undo_force_normals();
|
|
||||||
|
|
||||||
virtual bool begin_frame();
|
virtual bool begin_frame();
|
||||||
virtual bool begin_scene();
|
virtual bool begin_scene();
|
||||||
virtual void end_scene();
|
virtual void end_scene();
|
||||||
@ -284,6 +281,7 @@ protected:
|
|||||||
CPT(GeomVertexData) _vertex_data;
|
CPT(GeomVertexData) _vertex_data;
|
||||||
|
|
||||||
int _buffer_mask;
|
int _buffer_mask;
|
||||||
|
unsigned int _color_write_mask;
|
||||||
Colorf _color_clear_value;
|
Colorf _color_clear_value;
|
||||||
float _depth_clear_value;
|
float _depth_clear_value;
|
||||||
bool _stencil_clear_value;
|
bool _stencil_clear_value;
|
||||||
@ -296,16 +294,13 @@ protected:
|
|||||||
CPT(DisplayRegion) _current_display_region;
|
CPT(DisplayRegion) _current_display_region;
|
||||||
CPT(Lens) _current_lens;
|
CPT(Lens) _current_lens;
|
||||||
|
|
||||||
// This is used by wants_normals(). It's used as a semaphore:
|
|
||||||
// increment it to enable normals, and decrement it when you're
|
|
||||||
// done. The graphics engine will apply normals if it is nonzero.
|
|
||||||
int _force_normals;
|
|
||||||
|
|
||||||
CoordinateSystem _coordinate_system;
|
CoordinateSystem _coordinate_system;
|
||||||
CoordinateSystem _internal_coordinate_system;
|
CoordinateSystem _internal_coordinate_system;
|
||||||
CPT(TransformState) _cs_transform;
|
CPT(TransformState) _cs_transform;
|
||||||
CPT(TransformState) _inv_cs_transform;
|
CPT(TransformState) _inv_cs_transform;
|
||||||
|
|
||||||
|
bool _is_stereo;
|
||||||
|
|
||||||
Colorf _scene_graph_color;
|
Colorf _scene_graph_color;
|
||||||
bool _has_scene_graph_color;
|
bool _has_scene_graph_color;
|
||||||
bool _transform_stale;
|
bool _transform_stale;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "mutexHolder.h"
|
#include "mutexHolder.h"
|
||||||
#include "reMutexHolder.h"
|
#include "reMutexHolder.h"
|
||||||
#include "throw_event.h"
|
#include "throw_event.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
|
||||||
TypeHandle GraphicsWindow::_type_handle;
|
TypeHandle GraphicsWindow::_type_handle;
|
||||||
|
|
||||||
@ -50,6 +51,10 @@ GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_red_blue_stereo = red_blue_stereo && !_gsg->get_properties().is_stereo();
|
_red_blue_stereo = red_blue_stereo && !_gsg->get_properties().is_stereo();
|
||||||
|
if (_red_blue_stereo) {
|
||||||
|
_left_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(0));
|
||||||
|
_right_eye_color_mask = parse_color_mask(red_blue_stereo_colors.get_word(1));
|
||||||
|
}
|
||||||
|
|
||||||
_properties.set_open(false);
|
_properties.set_open(false);
|
||||||
_properties.set_undecorated(false);
|
_properties.set_undecorated(false);
|
||||||
@ -724,3 +729,44 @@ system_changed_size(int x_size, int y_size) {
|
|||||||
set_size_and_recalc(x_size, y_size);
|
set_size_and_recalc(x_size, y_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GraphicsWindow::parse_color_mask
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Parses one of the keywords in the
|
||||||
|
// red-blue-stereo-colors Config.prc variable, and
|
||||||
|
// returns the corresponding bitmask.
|
||||||
|
//
|
||||||
|
// These bitmask values are taken from ColorWriteAttrib.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
unsigned int GraphicsWindow::
|
||||||
|
parse_color_mask(const string &word) {
|
||||||
|
unsigned int result = 0;
|
||||||
|
vector_string components;
|
||||||
|
tokenize(word, components, "|");
|
||||||
|
|
||||||
|
vector_string::const_iterator ci;
|
||||||
|
for (ci = components.begin(); ci != components.end(); ++ci) {
|
||||||
|
string w = downcase(*ci);
|
||||||
|
if (w == "red" || w == "r") {
|
||||||
|
result |= 0x001;
|
||||||
|
|
||||||
|
} else if (w == "green" || w == "g") {
|
||||||
|
result |= 0x002;
|
||||||
|
|
||||||
|
} else if (w == "blue" || w == "b") {
|
||||||
|
result |= 0x004;
|
||||||
|
|
||||||
|
} else if (w == "alpha" || w == "a") {
|
||||||
|
result |= 0x008;
|
||||||
|
|
||||||
|
} else if (w == "off") {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
display_cat.warning()
|
||||||
|
<< "Invalid color in red-blue-stereo-colors: " << (*ci) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -101,6 +101,9 @@ protected:
|
|||||||
// thread other than the window thread.
|
// thread other than the window thread.
|
||||||
void system_changed_properties(const WindowProperties &properties);
|
void system_changed_properties(const WindowProperties &properties);
|
||||||
void system_changed_size(int x_size, int y_size);
|
void system_changed_size(int x_size, int y_size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static unsigned int parse_color_mask(const string &word);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef vector_GraphicsWindowInputDevice InputDevices;
|
typedef vector_GraphicsWindowInputDevice InputDevices;
|
||||||
|
@ -967,7 +967,7 @@ set_background_type(WindowFramework::BackgroundType type) {
|
|||||||
_display_region_3d->set_clear_color(_window->get_clear_color());
|
_display_region_3d->set_clear_color(_window->get_clear_color());
|
||||||
_display_region_3d->set_clear_depth(_window->get_clear_depth());
|
_display_region_3d->set_clear_depth(_window->get_clear_depth());
|
||||||
if (_display_region_right) {
|
if (_display_region_right) {
|
||||||
_display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
|
_display_region_right->set_clear_color_active(true);
|
||||||
_display_region_right->set_clear_depth_active(true);
|
_display_region_right->set_clear_depth_active(true);
|
||||||
_display_region_right->set_clear_color(_window->get_clear_color());
|
_display_region_right->set_clear_color(_window->get_clear_color());
|
||||||
_display_region_right->set_clear_depth(_window->get_clear_depth());
|
_display_region_right->set_clear_depth(_window->get_clear_depth());
|
||||||
@ -980,7 +980,7 @@ set_background_type(WindowFramework::BackgroundType type) {
|
|||||||
_display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
|
_display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
_display_region_3d->set_clear_depth(1.0f);
|
_display_region_3d->set_clear_depth(1.0f);
|
||||||
if (_display_region_right) {
|
if (_display_region_right) {
|
||||||
_display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
|
_display_region_right->set_clear_color_active(true);
|
||||||
_display_region_right->set_clear_depth_active(true);
|
_display_region_right->set_clear_depth_active(true);
|
||||||
_display_region_right->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
|
_display_region_right->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
_display_region_right->set_clear_depth(1.0f);
|
_display_region_right->set_clear_depth(1.0f);
|
||||||
@ -993,7 +993,7 @@ set_background_type(WindowFramework::BackgroundType type) {
|
|||||||
_display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
|
_display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
|
||||||
_display_region_3d->set_clear_depth(1.0f);
|
_display_region_3d->set_clear_depth(1.0f);
|
||||||
if (_display_region_right) {
|
if (_display_region_right) {
|
||||||
_display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
|
_display_region_right->set_clear_color_active(true);
|
||||||
_display_region_right->set_clear_depth_active(true);
|
_display_region_right->set_clear_depth_active(true);
|
||||||
_display_region_right->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
|
_display_region_right->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
|
||||||
_display_region_right->set_clear_depth(1.0f);
|
_display_region_right->set_clear_depth(1.0f);
|
||||||
@ -1006,7 +1006,7 @@ set_background_type(WindowFramework::BackgroundType type) {
|
|||||||
_display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
|
_display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
|
||||||
_display_region_3d->set_clear_depth(1.0f);
|
_display_region_3d->set_clear_depth(1.0f);
|
||||||
if (_display_region_right) {
|
if (_display_region_right) {
|
||||||
_display_region_right->set_clear_color_active(!_window->get_red_blue_stereo());
|
_display_region_right->set_clear_color_active(true);
|
||||||
_display_region_right->set_clear_depth_active(true);
|
_display_region_right->set_clear_depth_active(true);
|
||||||
_display_region_right->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
|
_display_region_right->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
|
||||||
_display_region_right->set_clear_depth(1.0f);
|
_display_region_right->set_clear_depth(1.0f);
|
||||||
|
@ -794,8 +794,6 @@ reset() {
|
|||||||
GLP(Disable)(GL_MULTISAMPLE);
|
GLP(Disable)(GL_MULTISAMPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
_stereo = ((get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_stereo) != 0);
|
|
||||||
|
|
||||||
// Set up all the enabled/disabled flags to GL's known initial
|
// Set up all the enabled/disabled flags to GL's known initial
|
||||||
// values: everything off.
|
// values: everything off.
|
||||||
_multisample_mode = 0;
|
_multisample_mode = 0;
|
||||||
@ -817,8 +815,6 @@ reset() {
|
|||||||
GLP(Disable)(GL_DITHER);
|
GLP(Disable)(GL_DITHER);
|
||||||
_dithering_enabled = false;
|
_dithering_enabled = false;
|
||||||
|
|
||||||
_texgen_forced_normal = false;
|
|
||||||
|
|
||||||
_current_shader_expansion = (ShaderExpansion *)NULL;
|
_current_shader_expansion = (ShaderExpansion *)NULL;
|
||||||
_current_shader_context = (CLP(ShaderContext) *)NULL;
|
_current_shader_context = (CLP(ShaderContext) *)NULL;
|
||||||
_vertex_array_shader_expansion = (ShaderExpansion *)NULL;
|
_vertex_array_shader_expansion = (ShaderExpansion *)NULL;
|
||||||
@ -3185,7 +3181,9 @@ do_issue_blending() {
|
|||||||
// all the other blending-related stuff doesn't matter. If the
|
// all the other blending-related stuff doesn't matter. If the
|
||||||
// device doesn't support color-write, we use blending tricks
|
// device doesn't support color-write, we use blending tricks
|
||||||
// to effectively disable color write.
|
// to effectively disable color write.
|
||||||
if (_target._color_write->get_channels() == ColorWriteAttrib::C_off) {
|
unsigned int color_channels =
|
||||||
|
_target._color_write->get_channels() & _color_write_mask;
|
||||||
|
if (color_channels == ColorWriteAttrib::C_off) {
|
||||||
if (_target._color_write != _state._color_write) {
|
if (_target._color_write != _state._color_write) {
|
||||||
enable_multisample_alpha_one(false);
|
enable_multisample_alpha_one(false);
|
||||||
enable_multisample_alpha_mask(false);
|
enable_multisample_alpha_mask(false);
|
||||||
@ -3202,11 +3200,10 @@ do_issue_blending() {
|
|||||||
} else {
|
} else {
|
||||||
if (_target._color_write != _state._color_write) {
|
if (_target._color_write != _state._color_write) {
|
||||||
if (CLP(color_mask)) {
|
if (CLP(color_mask)) {
|
||||||
unsigned int channels = _target._color_write->get_channels();
|
GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0,
|
||||||
GLP(ColorMask)((channels & ColorWriteAttrib::C_red) != 0,
|
(color_channels & ColorWriteAttrib::C_green) != 0,
|
||||||
(channels & ColorWriteAttrib::C_green) != 0,
|
(color_channels & ColorWriteAttrib::C_blue) != 0,
|
||||||
(channels & ColorWriteAttrib::C_blue) != 0,
|
(color_channels & ColorWriteAttrib::C_alpha) != 0);
|
||||||
(channels & ColorWriteAttrib::C_alpha) != 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3734,7 +3731,7 @@ set_draw_buffer(const RenderBuffer &rb) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderBuffer::T_front_right:
|
case RenderBuffer::T_front_right:
|
||||||
if (_stereo) {
|
if (_is_stereo) {
|
||||||
GLP(DrawBuffer)(GL_FRONT_RIGHT);
|
GLP(DrawBuffer)(GL_FRONT_RIGHT);
|
||||||
} else {
|
} else {
|
||||||
GLP(DrawBuffer)(GL_FRONT);
|
GLP(DrawBuffer)(GL_FRONT);
|
||||||
@ -3742,7 +3739,7 @@ set_draw_buffer(const RenderBuffer &rb) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderBuffer::T_front_left:
|
case RenderBuffer::T_front_left:
|
||||||
if (_stereo) {
|
if (_is_stereo) {
|
||||||
GLP(DrawBuffer)(GL_FRONT_LEFT);
|
GLP(DrawBuffer)(GL_FRONT_LEFT);
|
||||||
} else {
|
} else {
|
||||||
GLP(DrawBuffer)(GL_FRONT);
|
GLP(DrawBuffer)(GL_FRONT);
|
||||||
@ -3750,7 +3747,7 @@ set_draw_buffer(const RenderBuffer &rb) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderBuffer::T_back_right:
|
case RenderBuffer::T_back_right:
|
||||||
if (_stereo) {
|
if (_is_stereo) {
|
||||||
GLP(DrawBuffer)(GL_BACK_RIGHT);
|
GLP(DrawBuffer)(GL_BACK_RIGHT);
|
||||||
} else {
|
} else {
|
||||||
GLP(DrawBuffer)(GL_BACK);
|
GLP(DrawBuffer)(GL_BACK);
|
||||||
@ -3758,7 +3755,7 @@ set_draw_buffer(const RenderBuffer &rb) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderBuffer::T_back_left:
|
case RenderBuffer::T_back_left:
|
||||||
if (_stereo) {
|
if (_is_stereo) {
|
||||||
GLP(DrawBuffer)(GL_BACK_LEFT);
|
GLP(DrawBuffer)(GL_BACK_LEFT);
|
||||||
} else {
|
} else {
|
||||||
GLP(DrawBuffer)(GL_BACK);
|
GLP(DrawBuffer)(GL_BACK);
|
||||||
@ -3768,6 +3765,13 @@ set_draw_buffer(const RenderBuffer &rb) {
|
|||||||
default:
|
default:
|
||||||
GLP(DrawBuffer)(GL_FRONT_AND_BACK);
|
GLP(DrawBuffer)(GL_FRONT_AND_BACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also ensure that any global color channels are masked out.
|
||||||
|
GLP(ColorMask)((_color_write_mask & ColorWriteAttrib::C_red) != 0,
|
||||||
|
(_color_write_mask & ColorWriteAttrib::C_green) != 0,
|
||||||
|
(_color_write_mask & ColorWriteAttrib::C_blue) != 0,
|
||||||
|
(_color_write_mask & ColorWriteAttrib::C_alpha) != 0);
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5432,17 +5436,6 @@ do_issue_tex_gen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certain texgen modes (sphere_map, cube_map) require forcing the
|
|
||||||
// normal to be sent to the GL while the texgen mode is in effect.
|
|
||||||
if (force_normal != _texgen_forced_normal) {
|
|
||||||
if (force_normal) {
|
|
||||||
force_normals();
|
|
||||||
} else {
|
|
||||||
undo_force_normals();
|
|
||||||
}
|
|
||||||
_texgen_forced_normal = force_normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,8 +289,6 @@ protected:
|
|||||||
MM_alpha_mask = 0x0004,
|
MM_alpha_mask = 0x0004,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool _stereo;
|
|
||||||
|
|
||||||
int _multisample_mode;
|
int _multisample_mode;
|
||||||
bool _line_smooth_enabled;
|
bool _line_smooth_enabled;
|
||||||
bool _point_smooth_enabled;
|
bool _point_smooth_enabled;
|
||||||
@ -306,7 +304,6 @@ protected:
|
|||||||
int _decal_level;
|
int _decal_level;
|
||||||
|
|
||||||
bool _dithering_enabled;
|
bool _dithering_enabled;
|
||||||
bool _texgen_forced_normal;
|
|
||||||
|
|
||||||
LMatrix4f _projection_mat;
|
LMatrix4f _projection_mat;
|
||||||
int _viewport_width;
|
int _viewport_width;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user