implement M_dual

This commit is contained in:
David Rose 2002-05-14 21:35:56 +00:00
parent 7d20aff6f6
commit 2fc1dfb8a3
16 changed files with 216 additions and 56 deletions

View File

@ -3480,7 +3480,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(true);
enable_alpha_test(false);
call_glBlendFunc(GL_ZERO, GL_ONE);
return;
}
@ -3494,7 +3493,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(true);
enable_alpha_test(false);
call_glBlendFunc(GL_DST_COLOR, GL_ZERO);
return;
@ -3502,7 +3500,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(true);
enable_alpha_test(false);
call_glBlendFunc(GL_ONE, GL_ONE);
return;
@ -3510,7 +3507,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(true);
enable_alpha_test(false);
call_glBlendFunc(GL_DST_COLOR, GL_ONE);
return;
@ -3523,10 +3519,12 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
// No color blend; is there a transparency set?
switch (transparency_mode) {
case TransparencyAttrib::M_none:
case TransparencyAttrib::M_binary:
break;
case TransparencyAttrib::M_alpha:
case TransparencyAttrib::M_alpha_sorted:
case TransparencyAttrib::M_dual:
// Should we really have an "alpha" and an "alpha_sorted" mode,
// like Performer does? (The difference is that "alpha" is with
// the write to the depth buffer disabled.) Or should we just use
@ -3537,30 +3535,19 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(true);
enable_alpha_test(false);
call_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return;
case TransparencyAttrib::M_binary:
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(false);
enable_alpha_test(true);
call_glAlphaFunc(GL_EQUAL, 1);
return;
case TransparencyAttrib::M_multisample:
enable_multisample_alpha_one(true);
enable_multisample_alpha_mask(true);
enable_blend(false);
enable_alpha_test(false);
return;
case TransparencyAttrib::M_multisample_mask:
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(true);
enable_blend(false);
enable_alpha_test(false);
return;
default:
@ -3573,7 +3560,6 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
enable_multisample_alpha_one(false);
enable_multisample_alpha_mask(false);
enable_blend(false);
enable_alpha_test(false);
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,8 @@
// AlphaTestAttrib object.
////////////////////////////////////////////////////////////////////
INLINE AlphaTestAttrib::
AlphaTestAttrib(AlphaTestAttrib::PandaCompareFunc mode,float reference_alpha) :
AlphaTestAttrib(AlphaTestAttrib::PandaCompareFunc mode,
float reference_alpha) :
_mode(mode), _reference_alpha(reference_alpha)
{
}
@ -35,7 +36,7 @@ AlphaTestAttrib(AlphaTestAttrib::PandaCompareFunc mode,float reference_alpha) :
// Description: Returns the alpha write mode.
////////////////////////////////////////////////////////////////////
INLINE AlphaTestAttrib::PandaCompareFunc AlphaTestAttrib::
get_mode(void) const {
get_mode() const {
return _mode;
}
@ -45,6 +46,6 @@ get_mode(void) const {
// Description: Returns the alpha reference value.
////////////////////////////////////////////////////////////////////
INLINE float AlphaTestAttrib::
get_reference_alpha(void) const {
get_reference_alpha() const {
return _reference_alpha;
}

View File

@ -83,9 +83,11 @@ compare_to_impl(const RenderAttrib *other) const {
const AlphaTestAttrib *ta;
DCAST_INTO_R(ta, other, 0);
int compare_result = ((int)_mode - (int)ta->_mode) ;
if(compare_result!=0)
return compare_result;
else return (int) (255.0f*(_reference_alpha - ta->_reference_alpha));
if (compare_result!=0) {
return compare_result;
} else {
return (int) (255.0f*(_reference_alpha - ta->_reference_alpha));
}
}
////////////////////////////////////////////////////////////////////

View File

@ -31,10 +31,12 @@ class FactoryParams;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AlphaTestAttrib : public RenderAttrib {
private:
INLINE AlphaTestAttrib(PandaCompareFunc mode = M_always,float reference_alpha = 1.0f);
INLINE AlphaTestAttrib(PandaCompareFunc mode = M_always,
float reference_alpha = 1.0f);
PUBLISHED:
static CPT(RenderAttrib) make(PandaCompareFunc mode,float reference_alpha);
static CPT(RenderAttrib) make(PandaCompareFunc mode,
float reference_alpha);
INLINE float get_reference_alpha() const;
INLINE PandaCompareFunc get_mode() const;

View File

@ -18,6 +18,7 @@
#include "config_pgraph.h"
#include "alphaTestAttrib.h"
#include "ambientLight.h"
#include "billboardEffect.h"
#include "camera.h"
@ -104,6 +105,7 @@ init_libpgraph() {
}
initialized = true;
AlphaTestAttrib::init_type();
AmbientLight::init_type();
BillboardEffect::init_type();
Camera::init_type();
@ -162,6 +164,7 @@ init_libpgraph() {
ColorLerpFunctor::init_type();
ColorScaleLerpFunctor::init_type();
AlphaTestAttrib::register_with_read_factory();
AmbientLight::register_with_read_factory();
BillboardEffect::register_with_read_factory();
Camera::register_with_read_factory();

View File

@ -54,18 +54,3 @@ get_bin(int bin_index) {
}
return make_new_bin(bin_index);
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::add_object
// Access: Public
// Description: Adds the indicated CullableObject to the appropriate
// bin. The bin becomes the owner of the object
// pointer, and will eventually delete it.
////////////////////////////////////////////////////////////////////
INLINE void CullResult::
add_object(CullableObject *object) {
nassertv(object->_state != (const RenderState *)NULL);
CullBin *bin = get_bin(object->_state->get_bin_index());
nassertv(bin != (CullBin *)NULL);
bin->add_object(object);
}

View File

@ -18,6 +18,9 @@
#include "cullResult.h"
#include "cullBinManager.h"
#include "alphaTestAttrib.h"
#include "transparencyAttrib.h"
#include "renderState.h"
////////////////////////////////////////////////////////////////////
// Function: CullResult::make_next
@ -44,6 +47,64 @@ make_next() const {
return new_result;
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::add_object
// Access: Public
// Description: Adds the indicated CullableObject to the appropriate
// bin. The bin becomes the owner of the object
// pointer, and will eventually delete it.
////////////////////////////////////////////////////////////////////
void CullResult::
add_object(CullableObject *object) {
// Check to see if there's a special transparency setting.
const RenderState *state = object->_state;
nassertv(state != (const RenderState *)NULL);
const TransparencyAttrib *trans = state->get_transparency();
if (trans != (const TransparencyAttrib *)NULL) {
switch (trans->get_mode()) {
case TransparencyAttrib::M_binary:
// M_binary is implemented by explicitly setting the alpha test.
object->_state = state->compose(get_binary_state());
break;
case TransparencyAttrib::M_dual:
{
// M_dual is implemented by drawing the opaque parts first,
// without transparency, then drawing the transparent parts
// later. This means we must copy the object and add it to
// both bins. We can only do this if we do not have an
// explicit bin already applied; otherwise, M_dual falls back
// to M_alpha.
const CullBinAttrib *bin_attrib = state->get_bin();
if (bin_attrib == (CullBinAttrib *)NULL ||
bin_attrib->get_bin_name().empty()) {
// We make a copy of the object to draw the transparent part
// without decals; this gets placed in the transparent bin.
CullableObject *transparent_part = new CullableObject(*object);
transparent_part->_state = state->compose(get_dual_transparent_state());
CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
nassertv(bin != (CullBin *)NULL);
bin->add_object(transparent_part);
// Now we can draw the opaque part, with decals. This will
// end up in the opaque bin.
object->_state = state->compose(get_dual_opaque_state());
}
}
break;
default:
// Other kinds of transparency need no special handling.
break;
}
}
CullBin *bin = get_bin(object->_state->get_bin_index());
nassertv(bin != (CullBin *)NULL);
bin->add_object(object);
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::finish_cull
// Access: Public
@ -119,3 +180,52 @@ make_new_bin(int bin_index) {
return bin;
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::get_binary_state
// Access: Private
// Description: Returns a RenderState that applies the effects of
// M_binary.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_binary_state() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_equal, 1.0f),
RenderState::get_max_priority());
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::get_dual_transparent_state
// Access: Private
// Description: Returns a RenderState that renders only the
// transparent parts of an object, in support of M_dual.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_dual_transparent_state() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
RenderState::get_max_priority());
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::get_dual_opaque_state
// Access: Private
// Description: Returns a RenderState that renders only the
// opaque parts of an object, in support of M_dual.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_dual_opaque_state() {
static CPT(RenderState) state = NULL;
if (state == (const RenderState *)NULL) {
state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_equal, 1.0f),
TransparencyAttrib::make(TransparencyAttrib::M_none),
RenderState::get_max_priority());
}
return state;
}

View File

@ -53,7 +53,7 @@ public:
INLINE CullBin *get_bin(int bin_index);
INLINE void add_object(CullableObject *object);
void add_object(CullableObject *object);
void finish_cull();
void draw();
@ -63,6 +63,10 @@ public:
private:
CullBin *make_new_bin(int bin_index);
static CPT(RenderState) get_binary_state();
static CPT(RenderState) get_dual_transparent_state();
static CPT(RenderState) get_dual_opaque_state();
GraphicsStateGuardianBase *_gsg;
typedef pvector< PT(CullBin) > Bins;

View File

@ -156,7 +156,7 @@ get_fake_view_frustum_cull_state() {
(ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)),
TextureAttrib::make_off(),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
1000);
RenderState::get_max_priority());
}
return state;
}

View File

@ -66,22 +66,31 @@ CullableObject(Geom *geom, const RenderState *state,
////////////////////////////////////////////////////////////////////
// Function: CullableObject::Copy Constructor
// Access: Private
// Description: CullableObjects should not be copied.
// Access: Public
// Description: Copies the CullableObject, but does not copy its
// children (decals).
////////////////////////////////////////////////////////////////////
INLINE CullableObject::
CullableObject(const CullableObject &copy) {
nassertv(false);
CullableObject(const CullableObject &copy) :
_geom(copy._geom),
_state(copy._state),
_transform(copy._transform),
_next((CullableObject *)NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: CullableObject::Copy Assignment Operator
// Access: Private
// Description: CullableObjects should not be copied.
// Access: Public
// Description: Copies the CullableObject, but does not copy its
// children (decals).
////////////////////////////////////////////////////////////////////
INLINE void CullableObject::
operator = (const CullableObject &copy) {
nassertv(false);
_geom = copy._geom;
_state = copy._state;
_transform = copy._transform;
}
////////////////////////////////////////////////////////////////////

View File

@ -46,7 +46,6 @@ public:
const TransformState *transform,
CullableObject *next = NULL);
private:
INLINE CullableObject(const CullableObject &copy);
INLINE void operator = (const CullableObject &copy);

View File

@ -237,6 +237,25 @@ get_fog() const {
return _fog;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_bin
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a BinAttrib on this state. It returns a
// pointer to the BinAttrib, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const CullBinAttrib *RenderState::
get_bin() const {
if ((_flags & F_checked_bin) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal bin cache.
((RenderState *)this)->determine_bin();
}
return _bin;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_transparency
// Access: Public

View File

@ -608,6 +608,21 @@ write(ostream &out, int indent_level) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_max_priority
// Access: Published, Static
// Description: Returns the maximum priority number (sometimes called
// override) that may be set on any node. This may or
// may not be enforced, but the scene graph code assumes
// that no priority numbers will be larger than this,
// and some effects may not work properly if you use a
// larger number.
////////////////////////////////////////////////////////////////////
int RenderState::
get_max_priority() {
return 1000000000;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::issue_delta_modify
// Access: Public
@ -934,9 +949,8 @@ determine_bin_index() {
string bin_name;
_draw_order = 0;
const RenderAttrib *attrib = get_attrib(CullBinAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, attrib);
const CullBinAttrib *bin_attrib = get_bin();
if (bin_attrib != (const CullBinAttrib *)NULL) {
bin_name = bin_attrib->get_bin_name();
_draw_order = bin_attrib->get_draw_order();
}
@ -946,13 +960,12 @@ determine_bin_index() {
// either opaque or transparent, based on the transparency
// setting.
bin_name = "opaque";
const RenderAttrib *attrib = get_attrib(TransparencyAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
const TransparencyAttrib *trans = DCAST(TransparencyAttrib, attrib);
const TransparencyAttrib *trans = get_transparency();
if (trans != (const TransparencyAttrib *)NULL) {
switch (trans->get_mode()) {
case TransparencyAttrib::M_alpha:
case TransparencyAttrib::M_alpha_sorted:
case TransparencyAttrib::M_binary:
case TransparencyAttrib::M_dual:
// These transparency modes require special back-to-front sorting.
bin_name = "transparent";
break;
@ -988,6 +1001,21 @@ determine_fog() {
_flags |= F_checked_fog;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_bin
// Access: Private
// Description: This is the private implementation of get_bin().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_bin() {
const RenderAttrib *attrib = get_attrib(CullBinAttrib::get_class_type());
_bin = (const CullBinAttrib *)NULL;
if (attrib != (const RenderAttrib *)NULL) {
_bin = DCAST(CullBinAttrib, attrib);
}
_flags |= F_checked_bin;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_transparency
// Access: Private

View File

@ -29,6 +29,7 @@
class GraphicsStateGuardianBase;
class FogAttrib;
class CullBinAttrib;
class TransparencyAttrib;
class FactoryParams;
@ -92,10 +93,13 @@ PUBLISHED:
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
static int get_max_priority();
public:
INLINE int get_bin_index() const;
INLINE int get_draw_order() const;
INLINE const FogAttrib *get_fog() const;
INLINE const CullBinAttrib *get_bin() const;
INLINE const TransparencyAttrib *get_transparency() const;
CPT(RenderState) issue_delta_modify(const RenderState *other,
@ -111,6 +115,7 @@ private:
CPT(RenderState) do_invert_compose(const RenderState *other) const;
void determine_bin_index();
void determine_fog();
void determine_bin();
void determine_transparency();
INLINE void set_destructing();
@ -179,12 +184,14 @@ private:
// We also cache the pointer to some critical attribs stored in the
// state, if they exist.
const FogAttrib *_fog;
const CullBinAttrib *_bin;
const TransparencyAttrib *_transparency;
enum Flags {
F_checked_bin_index = 0x0001,
F_checked_fog = 0x0002,
F_checked_transparency = 0x0004,
F_checked_bin = 0x0004,
F_checked_transparency = 0x0008,
F_is_destructing = 0x8000,
};
unsigned short _flags;

View File

@ -83,6 +83,10 @@ output(ostream &out) const {
case M_binary:
out << "binary";
break;
case M_dual:
out << "dual";
break;
}
}

View File

@ -44,6 +44,7 @@ PUBLISHED:
M_multisample, // Source alpha values modified to 1.0 before writing
M_multisample_mask, // Source alpha values not modified
M_binary, // Only writes pixels with alpha = 1.0
M_dual, // 2-pass: draws opaque, then draws transparent
};
private: