support decals on M_dual objects

This commit is contained in:
David Rose 2002-06-12 20:10:29 +00:00
parent 41eb3248cf
commit 8ab41304fd
4 changed files with 65 additions and 2 deletions

View File

@ -87,7 +87,10 @@ add_object(CullableObject *object) {
#endif
{
CullableObject *transparent_part = new CullableObject(*object);
transparent_part->_state = state->compose(get_dual_transparent_state());
CPT(RenderState) transparent_state = object->has_decals() ?
get_dual_transparent_state_decals() :
get_dual_transparent_state();
transparent_part->_state = state->compose(transparent_state);
CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
nassertv(bin != (CullBin *)NULL);
bin->add_object(transparent_part);
@ -219,16 +222,63 @@ static const double m_dual_flash_rate = 1.0; // 1 state change per second
// Access: Private
// Description: Returns a RenderState that renders only the
// transparent parts of an object, in support of M_dual.
// This state is suitable only for objects that do not
// contain decals.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_dual_transparent_state() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
// The alpha test for > 0 prevents us from drawing empty pixels,
// and hence filling up the depth buffer with large empty spaces
// that may obscure other things. However, this does mean we draw
// pixels twice where the alpha == 1.0 (since they were already
// drawn in the opaque pass). This is not normally a problem,
// except when we are using decals; in the case of decals, we
// don't want to draw the 1.0 pixels again, since these are the
// ones that may have been decaled onto.
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
TransparencyAttrib::make(TransparencyAttrib::M_alpha),
RenderState::get_max_priority());
}
#ifndef NDEBUG
if (m_dual_flash) {
int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);
if ((cycle & 1) == 0) {
static CPT(RenderState) flash_state = NULL;
if (flash_state == (const RenderState *)NULL) {
flash_state = state->add_attrib(ColorScaleAttrib::make(LVecBase4f(0.8f, 0.2f, 0.2f, 1.0f)));
flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f));
}
return flash_state;
}
}
#endif // NDEBUG
return state;
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::get_dual_transparent_state_decals
// Access: Private
// Description: Returns a RenderState that renders only the
// transparent parts of an object, but suitable for
// objects that contain decals.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_dual_transparent_state_decals() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
// This is exactly the same as above except here we make the alpha
// test of < 1.0 instead of > 0.0. This makes us draw big empty
// pixels where the alpha values are 0.0, but we don't overwrite
// the decals where the pixels are 1.0.
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
TransparencyAttrib::make(TransparencyAttrib::M_alpha),
RenderState::get_max_priority());
}
#ifndef NDEBUG
if (m_dual_flash) {
int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);

View File

@ -65,6 +65,7 @@ private:
static CPT(RenderState) get_binary_state();
static CPT(RenderState) get_dual_transparent_state();
static CPT(RenderState) get_dual_transparent_state_decals();
static CPT(RenderState) get_dual_opaque_state();
GraphicsStateGuardianBase *_gsg;

View File

@ -81,7 +81,6 @@ CullableObject(const CullableObject &copy) :
////////////////////////////////////////////////////////////////////
// Function: CullableObject::Copy Assignment Operator
// Access: Private
// Access: Public
// Description: Copies the CullableObject, but does not copy its
// children (decals).
@ -93,6 +92,17 @@ operator = (const CullableObject &copy) {
_transform = copy._transform;
}
////////////////////////////////////////////////////////////////////
// Function: CullableObject::has_decals
// Access: Public
// Description: Returns true if the object has one or more decals
// placed on it, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool CullableObject::
has_decals() const {
return (_next != (CullableObject *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: CullableObject::operator new
// Access: Public

View File

@ -49,6 +49,8 @@ public:
INLINE CullableObject(const CullableObject &copy);
INLINE void operator = (const CullableObject &copy);
INLINE bool has_decals() const;
public:
~CullableObject();