color-scale-via-lighting

This commit is contained in:
David Rose 2005-05-05 18:19:41 +00:00
parent 00e2d94a05
commit a2eb3859cb
29 changed files with 926 additions and 462 deletions

View File

@ -158,6 +158,17 @@ ConfigVariableBool auto_generate_mipmaps
"false by default because some drivers (Intel) seem to do a "
"poor job of generating mipmaps when needed."));
ConfigVariableBool color_scale_via_lighting
("color-scale-via-lighting", true,
PRC_DESC("When this is true, Panda will try to implement ColorAttribs and "
"ColorScaleAttribs using the lighting interface, by "
"creating a default material and/or an ambient light if "
"necessary, even if lighting is ostensibly disabled. This "
"avoids the need to munge the vertex data to change each vertex's "
"color. Set this false to avoid this trickery, so that lighting "
"is only enabled when the application specifically enables "
"it."));
ConfigVariableInt win_size
("win-size", "640 480",
PRC_DESC("This is the default size at which to open a new window. This "

View File

@ -57,6 +57,7 @@ extern EXPCL_PANDA ConfigVariableBool copy_texture_inverted;
extern EXPCL_PANDA ConfigVariableBool window_inverted;
extern EXPCL_PANDA ConfigVariableBool depth_offset_decals;
extern EXPCL_PANDA ConfigVariableBool auto_generate_mipmaps;
extern EXPCL_PANDA ConfigVariableBool color_scale_via_lighting;
extern EXPCL_PANDA ConfigVariableInt win_size;
extern EXPCL_PANDA ConfigVariableInt win_origin;

View File

@ -316,6 +316,19 @@ get_supports_render_texture() const {
return _supports_render_texture;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_color_scale_via_lighting
// Access: Published
// Description: Returns true if this particular GSG can implement (or
// would prefer to implement) set color and/or color
// scale using materials and/or ambient lights, or
// false if we need to actually munge the color.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_color_scale_via_lighting() const {
return _color_scale_via_lighting;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::set_scene

View File

@ -131,6 +131,17 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_supports_render_texture = false;
_supported_geom_rendering = 0;
// If this is true, then we can apply a color and/or color scale by
// twiddling the material and/or ambient light (which could mean
// enabling lighting even without a LightAttrib).
_color_scale_via_lighting = color_scale_via_lighting;
if (!use_qpgeom) {
// The old Geom interface doesn't really work too well with the
// color_scale_via_lighting trick.
_color_scale_via_lighting = false;
}
}
////////////////////////////////////////////////////////////////////
@ -223,6 +234,14 @@ reset() {
_blend_mode_stale = false;
_pending_texture = NULL;
_texture_stale = false;
_pending_light = NULL;
_light_stale = false;
_pending_material = NULL;
_material_stale = false;
_has_material_force_color = false;
_material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
}
////////////////////////////////////////////////////////////////////
@ -356,7 +375,7 @@ release_index_buffer(IndexBufferContext *) {
// Description: Creates a new GeomMunger object to munge vertices
// appropriate to this GSG for the indicated state.
////////////////////////////////////////////////////////////////////
CPT(qpGeomMunger) GraphicsStateGuardian::
PT(qpGeomMunger) GraphicsStateGuardian::
get_geom_munger(const RenderState *state) {
// The default implementation returns no munger at all, but
// presumably, every kind of GSG needs some special munging action,
@ -886,6 +905,12 @@ issue_color_scale(const ColorScaleAttrib *attrib) {
if (_texture_involves_color_scale) {
_texture_stale = true;
}
if (_color_scale_via_lighting) {
_light_stale = true;
_material_stale = true;
determine_light_color_scale();
}
}
////////////////////////////////////////////////////////////////////
@ -929,153 +954,39 @@ issue_color(const ColorAttrib *attrib) {
_vertex_colors_enabled = true;
break;
}
if (_color_scale_via_lighting) {
_light_stale = true;
_material_stale = true;
determine_light_color_scale();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::issue_light
// Access: Public, Virtual
// Description: The default implementation of issue_light() assumes
// we have a limited number of hardware lights
// available. This function assigns each light to a
// different hardware light id, trying to keep each
// light associated with the same id where possible, but
// reusing id's when necessary. When it is no longer
// possible to reuse existing id's (e.g. all id's are in
// use), slot_new_light() is called to prepare the next
// sequential light id.
//
// It will call apply_light() each time a light is
// assigned to a particular id for the first time in a
// given frame, and it will subsequently call
// enable_light() to enable or disable each light as the
// frame is rendered, as well as enable_lighting() to
// enable or disable overall lighting.
//
// If this model of hardware lights with id's does not
// apply to a particular graphics engine, it should
// override this function to do something more
// appropriate instead.
// Description:
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
issue_light(const LightAttrib *attrib) {
// Initialize the current ambient light total and newly enabled
// light list
Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f);
int i;
int max_lights = (int)_light_info.size();
for (i = 0; i < max_lights; i++) {
_light_info[i]._next_enabled = false;
}
// By default, we don't apply the light attrib right away, since
// it might have a dependency on the current ColorScaleAttrib.
_pending_light = attrib;
_light_stale = true;
}
bool any_bound = false;
int num_enabled = 0;
int num_on_lights = attrib->get_num_on_lights();
for (int li = 0; li < num_on_lights; li++) {
NodePath light = attrib->get_on_light(li);
nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL);
Light *light_obj = light.node()->as_light();
num_enabled++;
// Lighting should be enabled before we apply any lights.
enable_lighting(true);
_lighting_enabled = true;
_lighting_enabled_this_frame = true;
if (light_obj->get_type() == AmbientLight::get_class_type()) {
// Ambient lights don't require specific light ids; simply add
// in the ambient contribution to the current total
cur_ambient_light += light_obj->get_color();
} else {
// Check to see if this light has already been bound to an id
int cur_light_id = -1;
for (i = 0; i < max_lights; i++) {
if (_light_info[i]._light == light) {
// Light has already been bound to an id, we only need to
// enable the light, not reapply it.
cur_light_id = -2;
enable_light(i, true);
_light_info[i]._enabled = true;
_light_info[i]._next_enabled = true;
break;
}
}
// See if there are any unbound light ids
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (_light_info[i]._light.is_empty()) {
_light_info[i]._light = light;
cur_light_id = i;
break;
}
}
}
// If there were no unbound light ids, see if we can replace
// a currently unused but previously bound id
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (!attrib->has_on_light(_light_info[i]._light)) {
_light_info[i]._light = light;
cur_light_id = i;
break;
}
}
}
// If we *still* don't have a light id, slot a new one.
if (cur_light_id == -1) {
if (slot_new_light(max_lights)) {
cur_light_id = max_lights;
_light_info.push_back(LightInfo());
max_lights++;
nassertv(max_lights == (int)_light_info.size());
}
}
if (cur_light_id >= 0) {
enable_light(cur_light_id, true);
_light_info[cur_light_id]._enabled = true;
_light_info[cur_light_id]._next_enabled = true;
if (!any_bound) {
begin_bind_lights();
any_bound = true;
}
// This is the first time this frame that this light has been
// bound to this particular id.
light_obj->bind(this, light, cur_light_id);
} else if (cur_light_id == -1) {
gsg_cat.warning()
<< "Failed to bind " << light << " to id.\n";
}
}
}
// Disable all unused lights
for (i = 0; i < max_lights; i++) {
if (!_light_info[i]._next_enabled) {
enable_light(i, false);
_light_info[i]._enabled = false;
}
}
// If no lights were enabled, disable lighting
if (num_enabled == 0) {
enable_lighting(false);
_lighting_enabled = false;
} else {
set_ambient_light(cur_ambient_light);
}
if (any_bound) {
end_bind_lights();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::issue_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
issue_material(const MaterialAttrib *attrib) {
// By default, we don't apply the material attrib right away, since
// it might have a dependency on the current ColorScaleAttrib.
_pending_material = attrib;
_material_stale = true;
}
////////////////////////////////////////////////////////////////////
@ -1278,6 +1189,181 @@ void GraphicsStateGuardian::
bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::do_issue_light
// Access: Protected
// Description: This implementation of issue_light() assumes
// we have a limited number of hardware lights
// available. This function assigns each light to a
// different hardware light id, trying to keep each
// light associated with the same id where possible, but
// reusing id's when necessary. When it is no longer
// possible to reuse existing id's (e.g. all id's are in
// use), slot_new_light() is called to prepare the next
// sequential light id.
//
// It will call apply_light() each time a light is
// assigned to a particular id for the first time in a
// given frame, and it will subsequently call
// enable_light() to enable or disable each light as the
// frame is rendered, as well as enable_lighting() to
// enable or disable overall lighting.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
do_issue_light() {
// Initialize the current ambient light total and newly enabled
// light list
Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
int i;
int max_lights = (int)_light_info.size();
for (i = 0; i < max_lights; i++) {
_light_info[i]._next_enabled = false;
}
bool any_bound = false;
int num_enabled = 0;
if (_pending_light != (LightAttrib *)NULL) {
int num_on_lights = _pending_light->get_num_on_lights();
for (int li = 0; li < num_on_lights; li++) {
NodePath light = _pending_light->get_on_light(li);
nassertv(!light.is_empty() && light.node()->as_light() != (Light *)NULL);
Light *light_obj = light.node()->as_light();
num_enabled++;
// Lighting should be enabled before we apply any lights.
enable_lighting(true);
_lighting_enabled = true;
_lighting_enabled_this_frame = true;
if (light_obj->get_type() == AmbientLight::get_class_type()) {
// Ambient lights don't require specific light ids; simply add
// in the ambient contribution to the current total
cur_ambient_light += light_obj->get_color();
} else {
// Check to see if this light has already been bound to an id
int cur_light_id = -1;
for (i = 0; i < max_lights; i++) {
if (_light_info[i]._light == light) {
// Light has already been bound to an id; reuse the same id.
cur_light_id = -2;
enable_light(i, true);
_light_info[i]._enabled = true;
_light_info[i]._next_enabled = true;
light_obj->bind(this, light, i);
break;
}
}
// See if there are any unbound light ids
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (_light_info[i]._light.is_empty()) {
_light_info[i]._light = light;
cur_light_id = i;
break;
}
}
}
// If there were no unbound light ids, see if we can replace
// a currently unused but previously bound id
if (cur_light_id == -1) {
for (i = 0; i < max_lights; i++) {
if (!_pending_light->has_on_light(_light_info[i]._light)) {
_light_info[i]._light = light;
cur_light_id = i;
break;
}
}
}
// If we *still* don't have a light id, slot a new one.
if (cur_light_id == -1) {
if (slot_new_light(max_lights)) {
cur_light_id = max_lights;
_light_info.push_back(LightInfo());
max_lights++;
nassertv(max_lights == (int)_light_info.size());
}
}
if (cur_light_id >= 0) {
enable_light(cur_light_id, true);
_light_info[cur_light_id]._enabled = true;
_light_info[cur_light_id]._next_enabled = true;
if (!any_bound) {
begin_bind_lights();
any_bound = true;
}
// This is the first time this frame that this light has been
// bound to this particular id.
light_obj->bind(this, light, cur_light_id);
} else if (cur_light_id == -1) {
gsg_cat.warning()
<< "Failed to bind " << light << " to id.\n";
}
}
}
}
// Disable all unused lights
for (i = 0; i < max_lights; i++) {
if (!_light_info[i]._next_enabled) {
enable_light(i, false);
_light_info[i]._enabled = false;
}
}
// If no lights were enabled, disable lighting
if (num_enabled == 0) {
if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f))) {
// Unless we need lighting anyway to apply a color or color
// scale.
enable_lighting(true);
_lighting_enabled = true;
_lighting_enabled_this_frame = true;
set_ambient_light(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
} else {
enable_lighting(false);
_lighting_enabled = false;
}
} else {
set_ambient_light(cur_ambient_light);
}
if (any_bound) {
end_bind_lights();
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::do_issue_material
// Access: Protected, Virtual
// Description: Should be overridden by derived classes to actually
// apply the material saved in _pending_material.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
do_issue_material() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::do_issue_texture
// Access: Protected, Virtual
// Description: Should be overridden by derived classes to actually
// apply the texture saved in _pending_texture.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
do_issue_texture() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::slot_new_light
// Access: Protected, Virtual
@ -1470,6 +1556,21 @@ finish_modify_state() {
_blend_mode_stale = false;
set_blend_mode();
}
if (_texture_stale) {
_texture_stale = false;
do_issue_texture();
}
if (_material_stale) {
_material_stale = false;
do_issue_material();
}
if (_light_stale) {
_light_stale = false;
do_issue_light();
}
}
////////////////////////////////////////////////////////////////////
@ -1529,6 +1630,41 @@ panic_deactivate() {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::determine_light_color_scale
// Access: Protected
// Description: Called whenever the color or color scale is changed,
// if _color_scale_via_lighting is true. This will
// rederive _material_force_color and _light_color_scale
// appropriately.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
determine_light_color_scale() {
if (_has_scene_graph_color) {
// If we have a scene graph color, it, plus the color scale, goes
// directly into the material; we don't color scale the
// lights--this allows an alpha color scale to work properly.
_has_material_force_color = true;
_material_force_color = _scene_graph_color;
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
if (!_color_blend_involves_color_scale && _color_scale_enabled) {
_material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
_scene_graph_color[1] * _current_color_scale[1],
_scene_graph_color[2] * _current_color_scale[2],
_scene_graph_color[3] * _current_color_scale[3]);
}
} else {
// Otherise, leave the materials alone, but we might still scale
// the lights.
_has_material_force_color = false;
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
if (!_color_blend_involves_color_scale && _color_scale_enabled) {
_light_color_scale = _current_color_scale;
}
}
}
#ifdef DO_PSTATS
////////////////////////////////////////////////////////////////////

View File

@ -41,6 +41,8 @@
#include "colorWriteAttrib.h"
#include "colorBlendAttrib.h"
#include "textureAttrib.h"
#include "materialAttrib.h"
#include "lightAttrib.h"
#include "transparencyAttrib.h"
#include "config_display.h"
#include "qpgeomMunger.h"
@ -100,6 +102,8 @@ PUBLISHED:
virtual int get_supported_geom_rendering() const;
INLINE bool get_color_scale_via_lighting() const;
public:
INLINE bool set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
@ -118,7 +122,7 @@ public:
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual void set_state_and_transform(const RenderState *state,
const TransformState *transform);
@ -193,6 +197,7 @@ public:
virtual void issue_color_scale(const ColorScaleAttrib *attrib);
virtual void issue_color(const ColorAttrib *attrib);
virtual void issue_light(const LightAttrib *attrib);
virtual void issue_material(const MaterialAttrib *attrib);
virtual void issue_color_write(const ColorWriteAttrib *attrib);
virtual void issue_transparency(const TransparencyAttrib *attrib);
virtual void issue_color_blend(const ColorBlendAttrib *attrib);
@ -207,6 +212,10 @@ public:
int light_id);
protected:
void do_issue_light();
virtual void do_issue_material();
virtual void do_issue_texture();
INLINE NodePath get_light(int light_id) const;
virtual bool slot_new_light(int light_id);
virtual void enable_lighting(bool enable);
@ -231,6 +240,8 @@ protected:
virtual void close_gsg();
void panic_deactivate();
void determine_light_color_scale();
INLINE void set_properties(const FrameBufferProperties &properties);
#ifdef DO_PSTATS
@ -313,6 +324,14 @@ protected:
CPT(TextureAttrib) _pending_texture;
bool _texture_stale;
CPT(LightAttrib) _pending_light;
bool _light_stale;
CPT(MaterialAttrib) _pending_material;
bool _material_stale;
bool _has_material_force_color;
Colorf _material_force_color;
LVecBase4f _light_color_scale;
bool _needs_reset;
bool _closing_gsg;
@ -332,6 +351,7 @@ protected:
bool _supports_generate_mipmap;
bool _supports_render_texture;
int _supported_geom_rendering;
bool _color_scale_via_lighting;
public:
// Statistics

View File

@ -37,15 +37,56 @@ StandardMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
int num_components,
StandardMunger::NumericType numeric_type,
StandardMunger::Contents contents) :
qpGeomMunger(gsg, state),
_num_components(num_components),
_numeric_type(numeric_type),
_contents(contents)
{
_gsg = DCAST(GraphicsStateGuardian, gsg);
_color = state->get_color();
_color_scale = state->get_color_scale();
_render_mode = state->get_render_mode();
_munge_color = false;
_munge_color_scale = false;
CPT(ColorAttrib) color_attrib = state->get_color();
CPT(ColorScaleAttrib) color_scale_attrib = state->get_color_scale();
if (color_attrib != (ColorAttrib *)NULL &&
color_attrib->get_color_type() == ColorAttrib::T_flat) {
if (!_gsg->get_color_scale_via_lighting()) {
// We only need to munge the color directly if the GSG says it
// can't cheat the color via lighting (presumably, in this case,
// by applying a material).
_color = color_attrib->get_color();
if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
color_scale_attrib->has_scale()) {
const LVecBase4f &cs = color_scale_attrib->get_scale();
_color.set(_color[0] * cs[0],
_color[1] * cs[1],
_color[2] * cs[2],
_color[3] * cs[3]);
}
_munge_color = true;
}
} else if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
color_scale_attrib->has_scale()) {
_color_scale = color_scale_attrib->get_scale();
if (!_gsg->get_color_scale_via_lighting() || _color_scale[3] != 1.0f) {
// We only need to apply the color scale by directly munging the
// color if the GSG says it can't cheat this via lighting (for
// instance, by applying an ambient light). Or, since we assume
// lighting can't scale the alpha component, if the color scale
// involves alpha.
// Known bug: if there is a material on an object that would
// obscure the effect of color_scale, we scale the lighting
// anyway, thus applying the effect even if it should be
// obscured. It doesn't seem worth the effort to detect this
// contrived situation and handle it correctly.
_munge_color_scale = true;
}
}
}
////////////////////////////////////////////////////////////////////
@ -67,25 +108,12 @@ CPT(qpGeomVertexData) StandardMunger::
munge_data_impl(const qpGeomVertexData *data) {
CPT(qpGeomVertexData) new_data = data;
if (_color != (ColorAttrib *)NULL &&
_color->get_color_type() == ColorAttrib::T_flat) {
Colorf color = _color->get_color();
if (_color_scale != (ColorScaleAttrib *)NULL &&
_color_scale->has_scale()) {
const LVecBase4f &cs = _color_scale->get_scale();
color.set(color[0] * cs[0],
color[1] * cs[1],
color[2] * cs[2],
color[3] * cs[3]);
}
new_data = new_data->set_color(color, _num_components, _numeric_type,
if (_munge_color) {
new_data = new_data->set_color(_color, _num_components, _numeric_type,
_contents);
} else if (_color_scale != (ColorScaleAttrib *)NULL &&
_color_scale->has_scale()) {
const LVecBase4f &cs = _color_scale->get_scale();
new_data = new_data->scale_color(cs, _num_components, _numeric_type,
_contents);
} else if (_munge_color_scale) {
new_data = new_data->scale_color(_color_scale, _num_components,
_numeric_type, _contents);
}
qpGeomVertexAnimationSpec animation = new_data->get_format()->get_animation();
@ -189,17 +217,30 @@ munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &vertex_data) {
int StandardMunger::
compare_to_impl(const qpGeomMunger *other) const {
const StandardMunger *om = DCAST(StandardMunger, other);
if (_color != om->_color) {
return _color < om->_color ? -1 : 1;
}
if (_color_scale != om->_color_scale) {
return _color_scale < om->_color_scale ? -1 : 1;
}
if (_render_mode != om->_render_mode) {
return _render_mode < om->_render_mode ? -1 : 1;
}
return qpGeomMunger::compare_to_impl(other);
if (_munge_color != om->_munge_color) {
return (int)_munge_color - (int)om->_munge_color;
}
if (_munge_color_scale != om->_munge_color_scale) {
return (int)_munge_color_scale - (int)om->_munge_color_scale;
}
if (_munge_color) {
int compare = _color.compare_to(om->_color);
if (compare != 0) {
return compare;
}
}
if (_munge_color_scale) {
int compare = _color_scale.compare_to(om->_color_scale);
if (compare != 0) {
return compare;
}
}
return StateMunger::compare_to_impl(other);
}
////////////////////////////////////////////////////////////////////
@ -215,12 +256,43 @@ compare_to_impl(const qpGeomMunger *other) const {
int StandardMunger::
geom_compare_to_impl(const qpGeomMunger *other) const {
const StandardMunger *om = DCAST(StandardMunger, other);
if (_color != om->_color) {
return _color < om->_color ? -1 : 1;
if (_munge_color != om->_munge_color) {
return (int)_munge_color - (int)om->_munge_color;
}
if (_color_scale != om->_color_scale) {
return _color_scale < om->_color_scale ? -1 : 1;
if (_munge_color_scale != om->_munge_color_scale) {
return (int)_munge_color_scale - (int)om->_munge_color_scale;
}
if (_munge_color) {
int compare = _color.compare_to(om->_color);
if (compare != 0) {
return compare;
}
}
if (_munge_color_scale) {
int compare = _color_scale.compare_to(om->_color_scale);
if (compare != 0) {
return compare;
}
}
return qpGeomMunger::geom_compare_to_impl(other);
return StateMunger::geom_compare_to_impl(other);
}
////////////////////////////////////////////////////////////////////
// Function: StandardMunger::munge_state_impl
// Access: Protectes, Virtual
// Description: Given an input state, returns the munged state.
////////////////////////////////////////////////////////////////////
CPT(RenderState) StandardMunger::
munge_state_impl(const RenderState *state) {
CPT(RenderState) munged_state = state;
if (_munge_color) {
munged_state = munged_state->remove_attrib(ColorAttrib::get_class_type());
munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_type());
} else if (_munge_color_scale) {
munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_type());
}
return munged_state;
}

View File

@ -20,7 +20,7 @@
#define STANDARDMUNGER_H
#include "pandabase.h"
#include "qpgeomMunger.h"
#include "stateMunger.h"
#include "graphicsStateGuardian.h"
#include "colorAttrib.h"
#include "colorScaleAttrib.h"
@ -36,7 +36,7 @@
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA StandardMunger : public qpGeomMunger {
class EXPCL_PANDA StandardMunger : public StateMunger {
public:
StandardMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state,
int num_components, NumericType numeric_type,
@ -48,24 +48,29 @@ protected:
virtual int compare_to_impl(const qpGeomMunger *other) const;
virtual bool munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
virtual int geom_compare_to_impl(const qpGeomMunger *other) const;
virtual CPT(RenderState) munge_state_impl(const RenderState *state);
private:
int _num_components;
NumericType _numeric_type;
Contents _contents;
CPT(GraphicsStateGuardian) _gsg;
CPT(ColorAttrib) _color;
CPT(ColorScaleAttrib) _color_scale;
CPT(RenderModeAttrib) _render_mode;
bool _munge_color;
bool _munge_color_scale;
Colorf _color;
LVecBase4f _color_scale;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomMunger::init_type();
StateMunger::init_type();
register_type(_type_handle, "StandardMunger",
qpGeomMunger::get_class_type());
StateMunger::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -33,7 +33,6 @@
#include "spotlight.h"
#include "textureAttrib.h"
#include "texGenAttrib.h"
#include "lightAttrib.h"
#include "shadeModelAttrib.h"
#include "cullFaceAttrib.h"
#include "transparencyAttrib.h"
@ -413,8 +412,8 @@ dx_init(void) {
_has_scene_graph_color = false;
// Apply a default material when materials are turned off.
Material empty;
apply_material(&empty);
_pending_material = NULL;
do_issue_material();
// GL stuff that hasnt been translated to DX
// none of these are implemented
@ -3556,7 +3555,7 @@ release_index_buffer(IndexBufferContext *ibc) {
// Description: Creates a new GeomMunger object to munge vertices
// appropriate to this GSG for the indicated state.
////////////////////////////////////////////////////////////////////
CPT(qpGeomMunger) DXGraphicsStateGuardian8::
PT(qpGeomMunger) DXGraphicsStateGuardian8::
get_geom_munger(const RenderState *state) {
PT(DXGeomMunger8) munger = new DXGeomMunger8(this, state);
return qpGeomMunger::register_munger(munger);
@ -3704,44 +3703,6 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::apply_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
apply_material(const Material *material) {
D3DMATERIAL8 cur_material;
cur_material.Diffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
cur_material.Ambient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
cur_material.Specular = *(D3DCOLORVALUE *)(material->get_specular().get_data());
cur_material.Emissive = *(D3DCOLORVALUE *)(material->get_emission().get_data());
cur_material.Power = material->get_shininess();
_pD3DDevice->SetMaterial(&cur_material);
if (material->has_diffuse()) {
// If the material specifies an diffuse color, use it.
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
// Otherwise, the diffuse color comes from the object color.
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
}
if (material->has_ambient()) {
// If the material specifies an ambient color, use it.
_pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
// Otherwise, the ambient color comes from the object color.
_pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
}
if (material->get_local()) {
_pD3DDevice->SetRenderState(D3DRS_LOCALVIEWER, TRUE);
} else {
_pD3DDevice->SetRenderState(D3DRS_LOCALVIEWER, FALSE);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::apply_fog
// Access: Public, Virtual
@ -3977,42 +3938,6 @@ issue_shade_model(const ShadeModelAttrib *attrib) {
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::issue_texture
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
issue_texture(const TextureAttrib *attrib) {
DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
if (attrib->is_off()) {
enable_texturing(false);
} else {
Texture *tex = attrib->get_texture();
nassertv(tex != (Texture *)NULL);
TextureContext *tc = tex->prepare_now(_prepared_objects, this);
apply_texture(tc);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::issue_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
issue_material(const MaterialAttrib *attrib) {
const Material *material = attrib->get_material();
if (material != (const Material *)NULL) {
apply_material(material);
} else {
// Apply a default material when materials are turned off.
Material empty;
apply_material(&empty);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::issue_render_mode
// Access: Public, Virtual
@ -4218,7 +4143,7 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
black.r = black.g = black.b = black.a = 0.0f;
D3DLIGHT8 alight;
alight.Type = D3DLIGHT_POINT;
alight.Diffuse = *(D3DCOLORVALUE *)(light_obj->get_color().get_data());
alight.Diffuse = get_light_color(light_obj);
alight.Ambient = black ;
alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
@ -4267,7 +4192,7 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
ZeroMemory(&alight, sizeof(D3DLIGHT8));
alight.Type = D3DLIGHT_DIRECTIONAL;
alight.Diffuse = *(D3DCOLORVALUE *)(light_obj->get_color().get_data());
alight.Diffuse = get_light_color(light_obj);
alight.Ambient = black ;
alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
@ -4318,7 +4243,7 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
alight.Type = D3DLIGHT_SPOT;
alight.Ambient = black ;
alight.Diffuse = *(D3DCOLORVALUE *)(light_obj->get_color().get_data());
alight.Diffuse = get_light_color(light_obj);
alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
alight.Position = *(D3DVECTOR *)pos.get_data();
@ -4531,6 +4456,25 @@ get_index_type(qpGeom::NumericType numeric_type) {
return D3DFMT_INDEX16;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::get_light_color
// Access: Public
// Description: Returns the array of four floats that should be
// issued as the light's color, as scaled by the current
// value of _light_color_scale, in the case of
// color_scale_via_lighting.
////////////////////////////////////////////////////////////////////
const D3DCOLORVALUE &DXGraphicsStateGuardian8::
get_light_color(Light *light) const {
static Colorf c;
c = light->get_color();
c.set(c[0] * _light_color_scale[0],
c[1] * _light_color_scale[1],
c[2] * _light_color_scale[2],
c[3] * _light_color_scale[3]);
return *(D3DCOLORVALUE *)c.get_data();
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::set_draw_buffer
// Access: Protected
@ -4652,6 +4596,86 @@ do_auto_rescale_normal() {
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::do_issue_texture
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
do_issue_texture() {
DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1));
CPT(TextureAttrib) new_texture = _pending_texture->filter_to_max(_max_texture_stages);
if (new_texture->is_off()) {
enable_texturing(false);
} else {
Texture *tex = new_texture->get_texture();
nassertv(tex != (Texture *)NULL);
TextureContext *tc = tex->prepare_now(_prepared_objects, this);
apply_texture(tc);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::do_issue_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
do_issue_material() {
static Material empty;
const Material *material;
if (_pending_material == (MaterialAttrib *)NULL ||
_pending_material->is_off()) {
material = &empty;
} else {
material = _pending_material->get_material();
}
D3DMATERIAL8 cur_material;
cur_material.Diffuse = *(D3DCOLORVALUE *)(material->get_diffuse().get_data());
cur_material.Ambient = *(D3DCOLORVALUE *)(material->get_ambient().get_data());
cur_material.Specular = *(D3DCOLORVALUE *)(material->get_specular().get_data());
cur_material.Emissive = *(D3DCOLORVALUE *)(material->get_emission().get_data());
cur_material.Power = material->get_shininess();
if (material->has_diffuse()) {
// If the material specifies an diffuse color, use it.
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
// Otherwise, the diffuse color comes from the object color.
if (_has_material_force_color) {
cur_material.Diffuse = *(D3DCOLORVALUE *)_material_force_color.get_data();
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
}
}
if (material->has_ambient()) {
// If the material specifies an ambient color, use it.
_pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
// Otherwise, the ambient color comes from the object color.
if (_has_material_force_color) {
cur_material.Ambient = *(D3DCOLORVALUE *)_material_force_color.get_data();
_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
} else {
_pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
}
}
_pD3DDevice->SetMaterial(&cur_material);
if (material->get_local()) {
_pD3DDevice->SetRenderState(D3DRS_LOCALVIEWER, TRUE);
} else {
_pD3DDevice->SetRenderState(D3DRS_LOCALVIEWER, FALSE);
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::slot_new_light
// Access: Protected, Virtual
@ -4693,7 +4717,13 @@ enable_lighting(bool enable) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
set_ambient_light(const Colorf &color) {
_pD3DDevice->SetRenderState(D3DRS_AMBIENT, Colorf_to_D3DCOLOR(color));
Colorf c = color;
c.set(c[0] * _light_color_scale[0],
c[1] * _light_color_scale[1],
c[2] * _light_color_scale[2],
c[3] * _light_color_scale[3]);
_pD3DDevice->SetRenderState(D3DRS_AMBIENT, Colorf_to_D3DCOLOR(c));
}
////////////////////////////////////////////////////////////////////

View File

@ -115,20 +115,17 @@ public:
void apply_index_buffer(IndexBufferContext *ibc);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
const RenderBuffer &rb);
virtual bool framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
const RenderBuffer &rb);
virtual void apply_material(const Material *material);
virtual void apply_fog(Fog *fog);
virtual void issue_transform(const TransformState *transform);
virtual void issue_tex_matrix(const TexMatrixAttrib *attrib);
virtual void issue_texture(const TextureAttrib *attrib);
virtual void issue_material(const MaterialAttrib *attrib);
virtual void issue_render_mode(const RenderModeAttrib *attrib);
virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib);
virtual void issue_alpha_test(const AlphaTestAttrib *attrib);
@ -160,6 +157,8 @@ public:
static D3DFORMAT get_index_type(qpGeom::NumericType numeric_type);
const D3DCOLORVALUE &get_light_color(Light *light) const;
public:
// recreate_tex_callback needs these to be public
DXScreenData *_pScrn;
@ -168,6 +167,8 @@ public:
D3DPRESENT_PARAMETERS _PresReset; // This is built during reset device
protected:
virtual void do_issue_material();
virtual bool slot_new_light(int light_id);
virtual void enable_lighting(bool enable);
virtual void set_ambient_light(const Colorf &color);
@ -192,6 +193,7 @@ protected:
static CPT(RenderState) get_flat_state();
void do_auto_rescale_normal();
virtual void do_issue_texture();
bool _bDXisReady;
HRESULT _last_testcooplevel_result;
@ -204,10 +206,10 @@ protected:
bool _auto_rescale_normal;
void GenerateSphere(void *pVertexSpace,DWORD dwVertSpaceByteSize,
void *pIndexSpace,DWORD dwIndexSpaceByteSize,
D3DXVECTOR3 *pCenter, float fRadius,
DWORD wNumRings, DWORD wNumSections, float sx, float sy, float sz,
DWORD *pNumVertices,DWORD *pNumTris,DWORD fvfFlags,DWORD dwVertSize);
void *pIndexSpace,DWORD dwIndexSpaceByteSize,
D3DXVECTOR3 *pCenter, float fRadius,
DWORD wNumRings, DWORD wNumSections, float sx, float sy, float sz,
DWORD *pNumVertices,DWORD *pNumTris,DWORD fvfFlags,DWORD dwVertSize);
HRESULT ReleaseAllDeviceObjects(void);
HRESULT RecreateAllDeviceObjects(void);
HRESULT DeleteAllDeviceObjects(void);

View File

@ -861,8 +861,8 @@ reset() {
cfa->issue(this);
ta->issue(this);
Material empty;
apply_material(&empty);
_pending_material = NULL;
do_issue_material();
if (CLP(cheap_textures)) {
GLCAT.info()
@ -1157,7 +1157,8 @@ draw_point(GeomPoint *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1227,7 +1228,8 @@ draw_line(GeomLine *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1304,7 +1306,8 @@ draw_linestrip(GeomLinestrip *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1677,7 +1680,8 @@ draw_polygon(GeomPolygon *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1758,7 +1762,8 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1837,7 +1842,8 @@ draw_quad(GeomQuad *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -1920,7 +1926,8 @@ draw_tristrip(GeomTristrip *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -2021,7 +2028,8 @@ draw_trifan(GeomTrifan *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -2119,7 +2127,8 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
GeomIssuer::IssueColor *issue_color;
if (_color_blend_involves_color_scale || !_color_scale_enabled) {
if (_color_blend_involves_color_scale || !_color_scale_enabled ||
_color_scale_via_lighting) {
issue_color = issue_color_gl;
} else {
issue_color = issue_scaled_color_gl;
@ -3206,7 +3215,7 @@ setup_primitive(const qpGeomPrimitive *data) {
// Description: Creates a new GeomMunger object to munge vertices
// appropriate to this GSG for the indicated state.
////////////////////////////////////////////////////////////////////
CPT(qpGeomMunger) CLP(GraphicsStateGuardian)::
PT(qpGeomMunger) CLP(GraphicsStateGuardian)::
get_geom_munger(const RenderState *state) {
PT(CLP(GeomMunger)) munger = new CLP(GeomMunger)(this, state);
return qpGeomMunger::register_munger(munger);
@ -3403,52 +3412,6 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::apply_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
apply_material(const Material *material) {
GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT;
GLP(Materialfv)(face, GL_SPECULAR, material->get_specular().get_data());
GLP(Materialfv)(face, GL_EMISSION, material->get_emission().get_data());
GLP(Materialf)(face, GL_SHININESS, material->get_shininess());
if (material->has_ambient() && material->has_diffuse()) {
// The material has both an ambient and diffuse specified. This
// means we do not need glMaterialColor().
GLP(Disable)(GL_COLOR_MATERIAL);
GLP(Materialfv)(face, GL_AMBIENT, material->get_ambient().get_data());
GLP(Materialfv)(face, GL_DIFFUSE, material->get_diffuse().get_data());
} else if (material->has_ambient()) {
// The material specifies an ambient, but not a diffuse component.
// The diffuse component comes from the object's color.
GLP(Materialfv)(face, GL_AMBIENT, material->get_ambient().get_data());
GLP(ColorMaterial)(face, GL_DIFFUSE);
GLP(Enable)(GL_COLOR_MATERIAL);
} else if (material->has_diffuse()) {
// The material specifies a diffuse, but not an ambient component.
// The ambient component comes from the object's color.
GLP(Materialfv)(face, GL_DIFFUSE, material->get_diffuse().get_data());
GLP(ColorMaterial)(face, GL_AMBIENT);
GLP(Enable)(GL_COLOR_MATERIAL);
} else {
// The material specifies neither a diffuse nor an ambient
// component. Both components come from the object's color.
GLP(ColorMaterial)(face, GL_AMBIENT_AND_DIFFUSE);
GLP(Enable)(GL_COLOR_MATERIAL);
}
GLP(LightModeli)(GL_LIGHT_MODEL_LOCAL_VIEWER, material->get_local());
GLP(LightModeli)(GL_LIGHT_MODEL_TWO_SIDE, material->get_twoside());
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::apply_fog
// Access: Public, Virtual
@ -3594,24 +3557,6 @@ issue_cg_shader_bind(const CgShaderAttrib *attrib) {
}
#endif
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::issue_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
issue_material(const MaterialAttrib *attrib) {
const Material *material = attrib->get_material();
if (material != (const Material *)NULL) {
apply_material(material);
} else {
// Apply a default material when materials are turned off.
Material empty;
apply_material(&empty);
}
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::issue_render_mode
// Access: Public, Virtual
@ -3903,6 +3848,77 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) {
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::do_issue_material
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
do_issue_material() {
static Material empty;
const Material *material;
if (_pending_material == (MaterialAttrib *)NULL ||
_pending_material->is_off()) {
material = &empty;
} else {
material = _pending_material->get_material();
}
GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT;
GLP(Materialfv)(face, GL_SPECULAR, material->get_specular().get_data());
GLP(Materialfv)(face, GL_EMISSION, material->get_emission().get_data());
GLP(Materialf)(face, GL_SHININESS, material->get_shininess());
if (material->has_ambient() && material->has_diffuse()) {
// The material has both an ambient and diffuse specified. This
// means we do not need glMaterialColor().
GLP(Disable)(GL_COLOR_MATERIAL);
GLP(Materialfv)(face, GL_AMBIENT, material->get_ambient().get_data());
GLP(Materialfv)(face, GL_DIFFUSE, material->get_diffuse().get_data());
} else if (material->has_ambient()) {
// The material specifies an ambient, but not a diffuse component.
// The diffuse component comes from the object's color.
GLP(Materialfv)(face, GL_AMBIENT, material->get_ambient().get_data());
if (_has_material_force_color) {
GLP(Disable)(GL_COLOR_MATERIAL);
GLP(Materialfv)(face, GL_DIFFUSE, _material_force_color.get_data());
} else {
GLP(ColorMaterial)(face, GL_DIFFUSE);
GLP(Enable)(GL_COLOR_MATERIAL);
}
} else if (material->has_diffuse()) {
// The material specifies a diffuse, but not an ambient component.
// The ambient component comes from the object's color.
GLP(Materialfv)(face, GL_DIFFUSE, material->get_diffuse().get_data());
if (_has_material_force_color) {
GLP(Disable)(GL_COLOR_MATERIAL);
GLP(Materialfv)(face, GL_AMBIENT, _material_force_color.get_data());
} else {
GLP(ColorMaterial)(face, GL_AMBIENT);
GLP(Enable)(GL_COLOR_MATERIAL);
}
} else {
// The material specifies neither a diffuse nor an ambient
// component. Both components come from the object's color.
if (_has_material_force_color) {
GLP(Disable)(GL_COLOR_MATERIAL);
GLP(Materialfv)(face, GL_AMBIENT, _material_force_color.get_data());
GLP(Materialfv)(face, GL_DIFFUSE, _material_force_color.get_data());
} else {
GLP(ColorMaterial)(face, GL_AMBIENT_AND_DIFFUSE);
GLP(Enable)(GL_COLOR_MATERIAL);
}
}
GLP(LightModeli)(GL_LIGHT_MODEL_LOCAL_VIEWER, material->get_local());
GLP(LightModeli)(GL_LIGHT_MODEL_TWO_SIDE, material->get_twoside());
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::bind_light
// Access: Public, Virtual
@ -3916,7 +3932,7 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
GLenum id = get_light_id(light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, get_light_color(light_obj));
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
@ -3956,7 +3972,7 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
GLenum id = get_light_id( light_id );
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, get_light_color(light_obj));
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w.
@ -4000,7 +4016,7 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
GLenum id = get_light_id(light_id);
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
GLP(Lightfv)(id, GL_AMBIENT, black.get_data());
GLP(Lightfv)(id, GL_DIFFUSE, light_obj->get_color().get_data());
GLP(Lightfv)(id, GL_DIFFUSE, get_light_color(light_obj));
GLP(Lightfv)(id, GL_SPECULAR, light_obj->get_specular_color().get_data());
// Position needs to specify x, y, z, and w
@ -4984,6 +5000,25 @@ issue_scaled_color(const Colorf &color) const {
GLP(Color4fv)(transformed.get_data());
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::get_light_color
// Access: Public
// Description: Returns the array of four floats that should be
// issued as the light's color, as scaled by the current
// value of _light_color_scale, in the case of
// color_scale_via_lighting.
////////////////////////////////////////////////////////////////////
const float *CLP(GraphicsStateGuardian)::
get_light_color(Light *light) const {
static Colorf c;
c = light->get_color();
c.set(c[0] * _light_color_scale[0],
c[1] * _light_color_scale[1],
c[2] * _light_color_scale[2],
c[3] * _light_color_scale[3]);
return c.get_data();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::slot_new_light
// Access: Protected, Virtual
@ -5029,7 +5064,12 @@ enable_lighting(bool enable) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
set_ambient_light(const Colorf &color) {
GLP(LightModelfv)(GL_LIGHT_MODEL_AMBIENT, color.get_data());
Colorf c = color;
c.set(c[0] * _light_color_scale[0],
c[1] * _light_color_scale[1],
c[2] * _light_color_scale[2],
c[3] * _light_color_scale[3]);
GLP(LightModelfv)(GL_LIGHT_MODEL_AMBIENT, c.get_data());
}
////////////////////////////////////////////////////////////////////
@ -5306,12 +5346,6 @@ void CLP(GraphicsStateGuardian)::
finish_modify_state() {
GraphicsStateGuardian::finish_modify_state();
// Apply the texture, if it needs to be reapplied.
if (_texture_stale) {
_texture_stale = false;
do_issue_texture();
}
// If one of the previously-loaded TexGen modes modified the texture
// matrix, then if either state changed, we have to change both of
// them now.
@ -5656,7 +5690,7 @@ do_auto_rescale_normal() {
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::do_issue_texture
// Access: Protected
// Access: Protected, Virtual
// Description: This is called by finish_modify_state() when the
// texture state has changed.
////////////////////////////////////////////////////////////////////

View File

@ -123,19 +123,17 @@ public:
virtual void release_index_buffer(IndexBufferContext *ibc);
const unsigned char *setup_primitive(const qpGeomPrimitive *data);
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
virtual void framebuffer_copy_to_texture
(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb);
virtual bool framebuffer_copy_to_ram
(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb);
virtual void apply_material(const Material *material);
void apply_fog(Fog *fog);
virtual void issue_transform(const TransformState *transform);
virtual void issue_tex_matrix(const TexMatrixAttrib *attrib);
virtual void issue_material(const MaterialAttrib *attrib);
virtual void issue_render_mode(const RenderModeAttrib *attrib);
virtual void issue_antialias(const AntialiasAttrib *);
virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib);
@ -152,6 +150,8 @@ public:
virtual void issue_cg_shader_bind(const CgShaderAttrib *attrib);
#endif
virtual void do_issue_material();
virtual void bind_light(PointLight *light_obj, const NodePath &light,
int light_id);
virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
@ -170,6 +170,7 @@ public:
void dump_state(void);
void issue_scaled_color(const Colorf &color) const;
const float *get_light_color(Light *light) const;
INLINE static bool report_errors(int line, const char *source_file);
INLINE void report_my_errors(int line, const char *source_file);
@ -256,7 +257,7 @@ protected:
static CPT(RenderState) get_flat_state();
void do_auto_rescale_normal();
void do_issue_texture();
virtual void do_issue_texture();
void specify_texture(Texture *tex);
void apply_texture(TextureContext *tc);
bool upload_texture(CLP(TextureContext) *gtc);

View File

@ -162,11 +162,11 @@ ConfigVariableBool display_list_animation
ConfigVariableBool connect_triangle_strips
("connect-triangle-strips", true,
PRC_DESC("Set this true to set a batch of triangle strips to the graphics "
PRC_DESC("Set this true to send a batch of triangle strips to the graphics "
"card as one long triangle strip, connected by degenerate "
"triangles, or false to send them as separate triangle strips "
"with no degenerate triangles. In many cases, using one long "
"triangle strip can help performance by reducing the number "
"with no degenerate triangles. On PC hardware, using one long "
"triangle strip may help performance by reducing the number "
"of separate graphics calls that have to be made."));
ConfigVariableBool use_qpgeom

View File

@ -24,10 +24,10 @@
////////////////////////////////////////////////////////////////////
INLINE Material::
Material() {
_ambient.set(0.0f, 0.0f, 0.0f, 0.0f);
_ambient.set(1.0f, 1.0f, 1.0f, 1.0f);
_diffuse.set(1.0f, 1.0f, 1.0f, 1.0f);
_specular.set(0.0f, 0.0f, 0.0f, 0.0f);
_emission.set(0.0f, 0.0f, 0.0f, 0.0f);
_specular.set(0.0f, 0.0f, 0.0f, 1.0f);
_emission.set(0.0f, 0.0f, 0.0f, 1.0f);
_shininess = 0.0;
_flags = 0;
}

View File

@ -633,81 +633,6 @@ transform_vertices(const LMatrix4f &mat) {
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::munge_geom
// Access: Published
// Description: Applies the indicated munger to the geom and its
// data, and returns a (possibly different) geom and
// data, according to the munger's whim.
//
// The assumption is that for a particular geom and a
// particular munger, the result will always be the
// same; so this result may be cached.
////////////////////////////////////////////////////////////////////
void qpGeom::
munge_geom(const qpGeomMunger *munger,
CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const {
CPT(qpGeomVertexData) source_data = data;
// Look up the munger in our cache--maybe we've recently applied it.
{
CDReader cdata(_cycler);
CacheEntry temp_entry(source_data, munger);
temp_entry.local_object();
Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
if (ci != cdata->_cache.end()) {
CacheEntry *entry = (*ci);
if (get_modified() <= entry->_geom_result->get_modified() &&
data->get_modified() <= entry->_data_result->get_modified()) {
// The cache entry is still good; use it.
// Record a cache hit, so this element will stay in the cache a
// while longer.
entry->refresh();
result = entry->_geom_result;
data = entry->_data_result;
return;
}
// The cache entry is stale, remove it.
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Cache entry " << *entry << " is stale, removing.\n";
}
entry->erase();
CDWriter cdataw(((qpGeom *)this)->_cycler, cdata);
cdataw->_cache.erase(entry);
}
}
// Ok, invoke the munger.
PStatTimer timer(qpGeomMunger::_munge_pcollector);
result = this;
if (munger != (qpGeomMunger *)NULL) {
data = munger->munge_data(data);
((qpGeomMunger *)munger)->munge_geom_impl(result, data);
}
{
// Record the new result in the cache.
CacheEntry *entry;
{
CDWriter cdata(((qpGeom *)this)->_cycler);
entry = new CacheEntry((qpGeom *)this, source_data, munger,
result, data);
bool inserted = cdata->_cache.insert(entry).second;
nassertv(inserted);
}
// And tell the cache manager about the new entry. (It might
// immediately request a delete from the cache of the thing we
// just added.)
entry->record();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::check_valid
// Access: Published

View File

@ -105,9 +105,6 @@ PUBLISHED:
// Temporarily virtual.
virtual void transform_vertices(const LMatrix4f &mat);
void munge_geom(const qpGeomMunger *munger,
CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const;
// Temporarily virtual.
virtual bool check_valid() const;
@ -227,6 +224,7 @@ private:
static TypeHandle _type_handle;
friend class CacheEntry;
friend class qpGeomMunger;
};
INLINE ostream &operator << (ostream &out, const qpGeom &obj);

View File

@ -45,7 +45,7 @@ is_registered() const {
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomMunger) qpGeomMunger::
INLINE PT(qpGeomMunger) qpGeomMunger::
register_munger(qpGeomMunger *munger) {
return get_registry()->register_munger(munger);
}

View File

@ -32,7 +32,7 @@ PStatCollector qpGeomMunger::_munge_pcollector("*:Munge");
// Description:
////////////////////////////////////////////////////////////////////
qpGeomMunger::
qpGeomMunger(const GraphicsStateGuardianBase *, const RenderState *) :
qpGeomMunger() :
_is_registered(false)
{
#ifndef NDEBUG
@ -92,6 +92,79 @@ remove_data(const qpGeomVertexData *data) {
nassertv(_is_registered);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::munge_geom
// Access: Published
// Description: Applies the indicated munger to the geom and its
// data, and returns a (possibly different) geom and
// data, according to the munger's whim.
//
// The assumption is that for a particular geom and a
// particular munger, the result will always be the
// same; so this result may be cached.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
munge_geom(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data) {
CPT(qpGeomVertexData) source_data = data;
// Look up the munger in the geom's cache--maybe we've recently
// applied it.
{
qpGeom::CDReader cdata(geom->_cycler);
qpGeom::CacheEntry temp_entry(source_data, this);
temp_entry.local_object();
qpGeom::Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
if (ci != cdata->_cache.end()) {
qpGeom::CacheEntry *entry = (*ci);
if (geom->get_modified() <= entry->_geom_result->get_modified() &&
data->get_modified() <= entry->_data_result->get_modified()) {
// The cache entry is still good; use it.
// Record a cache hit, so this element will stay in the cache a
// while longer.
entry->refresh();
geom = entry->_geom_result;
data = entry->_data_result;
return;
}
// The cache entry is stale, remove it.
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Cache entry " << *entry << " is stale, removing.\n";
}
entry->erase();
qpGeom::CDWriter cdataw(((qpGeom *)geom.p())->_cycler, cdata);
cdataw->_cache.erase(entry);
}
}
// Ok, invoke the munger.
PStatTimer timer(_munge_pcollector);
CPT(qpGeom) orig_geom = geom;
data = munge_data(data);
munge_geom_impl(geom, data);
{
// Record the new result in the cache.
qpGeom::CacheEntry *entry;
{
qpGeom::CDWriter cdata(((qpGeom *)orig_geom.p())->_cycler);
entry = new qpGeom::CacheEntry((qpGeom *)orig_geom.p(), source_data, this,
geom, data);
bool inserted = cdata->_cache.insert(entry).second;
nassertv(inserted);
}
// And tell the cache manager about the new entry. (It might
// immediately request a delete from the cache of the thing we
// just added.)
entry->record();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::do_munge_format
// Access: Protected
@ -286,7 +359,7 @@ Registry() {
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
CPT(qpGeomMunger) qpGeomMunger::Registry::
PT(qpGeomMunger) qpGeomMunger::Registry::
register_munger(qpGeomMunger *munger) {
if (munger->is_registered()) {
return munger;

View File

@ -60,13 +60,13 @@ class qpGeom;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomMunger : public TypedReferenceCount, public qpGeomEnums {
public:
qpGeomMunger(const GraphicsStateGuardianBase *gsg, const RenderState *state);
qpGeomMunger();
qpGeomMunger(const qpGeomMunger &copy);
void operator = (const qpGeomMunger &copy);
virtual ~qpGeomMunger();
INLINE bool is_registered() const;
INLINE static CPT(qpGeomMunger) register_munger(qpGeomMunger *munger);
INLINE static PT(qpGeomMunger) register_munger(qpGeomMunger *munger);
INLINE CPT(qpGeomVertexFormat) munge_format(const qpGeomVertexFormat *format,
const qpGeomVertexAnimationSpec &animation) const;
@ -74,7 +74,7 @@ public:
INLINE CPT(qpGeomVertexData) munge_data(const qpGeomVertexData *data) const;
void remove_data(const qpGeomVertexData *data);
// Also see Geom::munge_geom() for the primary interface.
void munge_geom(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
public:
INLINE int compare_to(const qpGeomMunger &other) const;
@ -132,7 +132,7 @@ private:
class EXPCL_PANDA Registry {
public:
Registry();
CPT(qpGeomMunger) register_munger(qpGeomMunger *munger);
PT(qpGeomMunger) register_munger(qpGeomMunger *munger);
void unregister_munger(qpGeomMunger *munger);
Mungers _mungers;

View File

@ -145,7 +145,7 @@ public:
virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data)=0;
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
virtual CPT(qpGeomMunger) get_geom_munger(const RenderState *state)=0;
virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state)=0;
virtual void set_state_and_transform(const RenderState *state,
const TransformState *transform)=0;
@ -205,8 +205,6 @@ public:
virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex)=0;
virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex)=0;
virtual void apply_material(const Material *material)=0;
virtual CoordinateSystem get_internal_coordinate_system() const=0;
virtual void issue_transform(const TransformState *) { }

View File

@ -91,6 +91,7 @@
shadeModelAttrib.I shadeModelAttrib.h \
showBoundsEffect.I showBoundsEffect.h \
spotlight.I spotlight.h \
stateMunger.I stateMunger.h \
switchNode.I switchNode.h \
texMatrixAttrib.I texMatrixAttrib.h \
texProjectorEffect.I texProjectorEffect.h \
@ -188,6 +189,7 @@
shadeModelAttrib.cxx \
showBoundsEffect.cxx \
spotlight.cxx \
stateMunger.cxx \
switchNode.cxx \
texMatrixAttrib.cxx \
texProjectorEffect.cxx \
@ -281,6 +283,7 @@
shadeModelAttrib.I shadeModelAttrib.h \
showBoundsEffect.I showBoundsEffect.h \
spotlight.I spotlight.h \
stateMunger.I stateMunger.h \
switchNode.I switchNode.h \
texMatrixAttrib.I texMatrixAttrib.h \
texProjectorEffect.I texProjectorEffect.h \

View File

@ -82,6 +82,7 @@
#include "shadeModelAttrib.h"
#include "showBoundsEffect.h"
#include "spotlight.h"
#include "stateMunger.h"
#include "switchNode.h"
#include "texMatrixAttrib.h"
#include "texProjectorEffect.h"
@ -320,6 +321,7 @@ init_libpgraph() {
ShadeModelAttrib::init_type();
ShowBoundsEffect::init_type();
Spotlight::init_type();
StateMunger::init_type();
SwitchNode::init_type();
TexMatrixAttrib::init_type();
TexProjectorEffect::init_type();

View File

@ -63,13 +63,13 @@ get_bin(int bin_index) {
// if we haven't already created one for this state;
// otherwise, it will return the existing one.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomMunger) CullResult::
INLINE PT(qpGeomMunger) CullResult::
get_geom_munger(const RenderState *state) {
Mungers::iterator mi = _mungers.find(state);
if (mi != _mungers.end()) {
return (*mi).second;
}
CPT(qpGeomMunger) munger = _gsg->get_geom_munger(state);
PT(qpGeomMunger) munger = _gsg->get_geom_munger(state);
_mungers.insert(Mungers::value_type(state, munger));
return munger;
}

View File

@ -66,7 +66,7 @@ public:
private:
CullBin *make_new_bin(int bin_index);
INLINE CPT(qpGeomMunger) get_geom_munger(const RenderState *state);
INLINE PT(qpGeomMunger) get_geom_munger(const RenderState *state);
static CPT(RenderState) get_binary_state();
static CPT(RenderState) get_dual_transparent_state();
@ -75,7 +75,7 @@ private:
GraphicsStateGuardianBase *_gsg;
typedef pmap<CPT(RenderState), CPT(qpGeomMunger) > Mungers;
typedef pmap<CPT(RenderState), PT(qpGeomMunger) > Mungers;
Mungers _mungers;
typedef pvector< PT(CullBin) > Bins;

View File

@ -23,6 +23,7 @@
#include "cullTraverser.h"
#include "sceneSetup.h"
#include "lens.h"
#include "stateMunger.h"
#include "pStatTimer.h"
#include "qpgeomVertexWriter.h"
#include "qpgeomVertexReader.h"
@ -42,7 +43,7 @@ TypeHandle CullableObject::_type_handle;
////////////////////////////////////////////////////////////////////
void CullableObject::
munge_geom(GraphicsStateGuardianBase *gsg,
const qpGeomMunger *munger, const CullTraverser *traverser) {
qpGeomMunger *munger, const CullTraverser *traverser) {
if (_geom != (Geom *)NULL) {
// Temporary test and dcast until the experimental Geom rewrite
// becomes the actual Geom rewrite.
@ -73,7 +74,12 @@ munge_geom(GraphicsStateGuardianBase *gsg,
// Now invoke the munger to ensure the resulting geometry is in
// a GSG-friendly form.
qpgeom->munge_geom(munger, qpgeom, _munged_data);
munger->munge_geom(qpgeom, _munged_data);
StateMunger *state_munger;
DCAST_INTO_V(state_munger, munger);
_state = state_munger->munge_state(_state);
CPT(qpGeomVertexData) animated_vertices =
_munged_data->animate_vertices();
#ifndef NDEBUG

View File

@ -58,7 +58,7 @@ public:
INLINE bool has_decals() const;
void munge_geom(GraphicsStateGuardianBase *gsg,
const qpGeomMunger *munger, const CullTraverser *traverser);
qpGeomMunger *munger, const CullTraverser *traverser);
INLINE void draw(GraphicsStateGuardianBase *gsg);
public:
@ -77,7 +77,7 @@ PUBLISHED:
public:
CPT(Geom) _geom;
CPT(qpGeomMunger) _munger;
PT(qpGeomMunger) _munger;
CPT(qpGeomVertexData) _munged_data;
CPT(RenderState) _state;
CPT(TransformState) _transform;

View File

@ -11,6 +11,7 @@
#include "shadeModelAttrib.cxx"
#include "showBoundsEffect.cxx"
#include "spotlight.cxx"
#include "stateMunger.cxx"
#include "switchNode.cxx"
#include "texMatrixAttrib.cxx"
#include "texProjectorEffect.cxx"

View File

@ -0,0 +1,18 @@
// Filename: stateMunger.I
// Created by: drose (04May05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,50 @@
// Filename: stateMunger.cxx
// Created by: drose (04May05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "stateMunger.h"
TypeHandle StateMunger::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: StateMunger::munge_state
// Access: Public
// Description: Given an input state, returns the munged state.
////////////////////////////////////////////////////////////////////
CPT(RenderState) StateMunger::
munge_state(const RenderState *state) {
CPT(RenderState) ptstate = state;
StateMap::iterator mi = _state_map.find(ptstate);
if (mi != _state_map.end()) {
return (*mi).second;
}
CPT(RenderState) result = munge_state_impl(state);
_state_map[ptstate] = result;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: StateMunger::munge_state_impl
// Access: Protected, Virtual
// Description: Given an input state, returns the munged state.
////////////////////////////////////////////////////////////////////
CPT(RenderState) StateMunger::
munge_state_impl(const RenderState *state) {
return state;
}

View File

@ -0,0 +1,65 @@
// Filename: stateMunger.h
// Created by: drose (04May05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef STATEMUNGER_H
#define STATEMUNGER_H
#include "pandabase.h"
#include "qpgeomMunger.h"
////////////////////////////////////////////////////////////////////
// Class : StateMunger
// Description : This is just a simple derivative of GeomMunger that
// adds the ability to munge states. That functionality
// can't be declared in the base class, since it doesn't
// really know about RenderState.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA StateMunger : public qpGeomMunger {
public:
CPT(RenderState) munge_state(const RenderState *state);
protected:
CPT(RenderState) munge_state_impl(const RenderState *state);
typedef pmap<CPT(RenderState), CPT(RenderState) > StateMap;
StateMap _state_map;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomMunger::init_type();
register_type(_type_handle, "StateMunger",
qpGeomMunger::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "stateMunger.I"
#endif