diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ee302529fa..e1dd351f16 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -814,6 +814,7 @@ issue_transparency(const TransparencyAttrib *attrib) { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: issue_color_blend(const ColorBlendAttrib *attrib) { + _color_blend = attrib; _color_blend_mode = attrib->get_mode(); set_blend_mode(_color_write_mode, _color_blend_mode, _transparency_mode); } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 550d6a0b01..639d3a18be 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -269,6 +269,7 @@ protected: ColorWriteAttrib::Mode _color_write_mode; ColorBlendAttrib::Mode _color_blend_mode; TransparencyAttrib::Mode _transparency_mode; + CPT(ColorBlendAttrib) _color_blend; bool _needs_reset; bool _closing_gsg; diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx index 918ffc4150..a56a582940 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx @@ -894,6 +894,70 @@ void INLINE TestDrawPrimFailure(DP_Type dptype,HRESULT hr,LPDIRECTDRAW7 pDD,DWOR #define TestDrawPrimFailure(a,b,c,nVerts,nTris) CountDPs(nVerts,nTris); #endif +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian7::get_blend_func +// Access: Protected, Static +// Description: Maps from ColorBlendAttrib::Operand to D3DBLEND +// value. +//////////////////////////////////////////////////////////////////// +D3DBLEND DXGraphicsStateGuardian7:: +get_blend_func(ColorBlendAttrib::Operand operand) { + switch (operand) { + case ColorBlendAttrib::O_zero: + return D3DBLEND_ZERO; + + case ColorBlendAttrib::O_one: + return D3DBLEND_ONE; + + case ColorBlendAttrib::O_incoming_color: + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_incoming_color: + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_fbuffer_color: + return D3DBLEND_DESTCOLOR; + + case ColorBlendAttrib::O_one_minus_fbuffer_color: + return D3DBLEND_INVDESTCOLOR; + + case ColorBlendAttrib::O_incoming_alpha: + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_incoming_alpha: + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_fbuffer_alpha: + return D3DBLEND_DESTALPHA; + + case ColorBlendAttrib::O_one_minus_fbuffer_alpha: + return D3DBLEND_INVDESTALPHA; + + case ColorBlendAttrib::O_constant_color: + // Not supported by DX. + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_constant_color: + // Not supported by DX. + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_constant_alpha: + // Not supported by DX. + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_constant_alpha: + // Not supported by DX. + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_incoming_color_saturate: + return D3DBLEND_SRCALPHASAT; + } + + dxgsg7_cat.error() + << "Unknown color blend operand " << (int)operand << endl; + return D3DBLEND_ZERO; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::report_texmgr_stats // Access: Protected @@ -4536,31 +4600,18 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, call_dxBlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE); return; } - + // Is there a color blend set? - switch (color_blend_mode) { - case ColorBlendAttrib::M_none: - break; - - case ColorBlendAttrib::M_multiply: + if (color_blend_mode != ColorBlendAttrib::M_none) { enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ZERO); - return; - case ColorBlendAttrib::M_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_ONE, D3DBLEND_ONE); + // DX7 supports only ColorBlendAttrib::M_add. Assume that's what + // we've got; if the user asked for anything else, give him M_add + // instead. + + call_dxBlendFunc(get_blend_func(_color_blend->get_operand_a()), + get_blend_func(_color_blend->get_operand_b())); return; - - case ColorBlendAttrib::M_multiply_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ONE); - return; - - default: - dxgsg7_cat.error() - << "Unknown color blend mode " << (int)color_blend_mode << endl; - break; } // No color blend; is there a transparency set? diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h index 7457a72a41..86c0a70a8c 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h @@ -217,6 +217,7 @@ protected: INLINE void call_dxLightModelAmbient(const Colorf& color); INLINE void call_dxAlphaFunc(D3DCMPFUNC func, float ref); INLINE void call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc); + static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); INLINE void enable_dither(bool val); INLINE void enable_stencil_test(bool val); void report_texmgr_stats(); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 449f347c80..6aab27cbbd 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -1092,6 +1092,70 @@ void DXGraphicsStateGuardian8::set_clipper(RECT cliprect) { } #endif +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian8::get_blend_func +// Access: Protected, Static +// Description: Maps from ColorBlendAttrib::Operand to D3DBLEND +// value. +//////////////////////////////////////////////////////////////////// +D3DBLEND DXGraphicsStateGuardian8:: +get_blend_func(ColorBlendAttrib::Operand operand) { + switch (operand) { + case ColorBlendAttrib::O_zero: + return D3DBLEND_ZERO; + + case ColorBlendAttrib::O_one: + return D3DBLEND_ONE; + + case ColorBlendAttrib::O_incoming_color: + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_incoming_color: + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_fbuffer_color: + return D3DBLEND_DESTCOLOR; + + case ColorBlendAttrib::O_one_minus_fbuffer_color: + return D3DBLEND_INVDESTCOLOR; + + case ColorBlendAttrib::O_incoming_alpha: + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_incoming_alpha: + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_fbuffer_alpha: + return D3DBLEND_DESTALPHA; + + case ColorBlendAttrib::O_one_minus_fbuffer_alpha: + return D3DBLEND_INVDESTALPHA; + + case ColorBlendAttrib::O_constant_color: + // Not supported by DX. + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_constant_color: + // Not supported by DX. + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_constant_alpha: + // Not supported by DX. + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_constant_alpha: + // Not supported by DX. + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_incoming_color_saturate: + return D3DBLEND_SRCALPHASAT; + } + + dxgsg8_cat.error() + << "Unknown color blend operand " << (int)operand << endl; + return D3DBLEND_ZERO; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::report_texmgr_stats // Access: Protected @@ -4241,29 +4305,34 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, } // Is there a color blend set? - switch (color_blend_mode) { - case ColorBlendAttrib::M_none: - break; - - case ColorBlendAttrib::M_multiply: + if (color_blend_mode != ColorBlendAttrib::M_none) { enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ZERO); - return; + + switch (color_blend_mode) { + case ColorBlendAttrib::M_add: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + break; - case ColorBlendAttrib::M_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_ONE, D3DBLEND_ONE); - return; + case ColorBlendAttrib::M_subtract: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); + break; - case ColorBlendAttrib::M_multiply_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ONE); - return; + case ColorBlendAttrib::M_inv_subtract: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); + break; - default: - dxgsg8_cat.error() - << "Unknown color blend mode " << (int)color_blend_mode << endl; - break; + case ColorBlendAttrib::M_min: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); + break; + + case ColorBlendAttrib::M_max: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX); + break; + } + + call_dxBlendFunc(get_blend_func(_color_blend->get_operand_a()), + get_blend_func(_color_blend->get_operand_b())); + return; } // No color blend; is there a transparency set? @@ -4278,6 +4347,7 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, case TransparencyAttrib::M_multisample_mask: case TransparencyAttrib::M_dual: enable_blend(true); + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); call_dxBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); return; diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 23c73e158e..7c51e7d73d 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -217,6 +217,7 @@ protected: INLINE void call_dxLightModelAmbient(const Colorf& color); INLINE void call_dxAlphaFunc(D3DCMPFUNC func, float refval); INLINE void call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc); + static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); INLINE void enable_dither(bool val); INLINE void enable_stencil_test(bool val); void report_texmgr_stats(); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 8bf5c42a61..edfd7284d5 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -769,7 +769,6 @@ dx_init(void) { _alpha_test_enabled = false; _pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, _alpha_test_enabled); - // this is a new DX9 state that lets you do additional operations other than ADD (e.g. subtract/max/min) // must check (_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon8500, no on TNT) _pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD); @@ -1085,6 +1084,70 @@ void DXGraphicsStateGuardian9::set_clipper(RECT cliprect) { } #endif +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian9::get_blend_func +// Access: Protected, Static +// Description: Maps from ColorBlendAttrib::Operand to D3DBLEND +// value. +//////////////////////////////////////////////////////////////////// +D3DBLEND DXGraphicsStateGuardian9:: +get_blend_func(ColorBlendAttrib::Operand operand) { + switch (operand) { + case ColorBlendAttrib::O_zero: + return D3DBLEND_ZERO; + + case ColorBlendAttrib::O_one: + return D3DBLEND_ONE; + + case ColorBlendAttrib::O_incoming_color: + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_incoming_color: + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_fbuffer_color: + return D3DBLEND_DESTCOLOR; + + case ColorBlendAttrib::O_one_minus_fbuffer_color: + return D3DBLEND_INVDESTCOLOR; + + case ColorBlendAttrib::O_incoming_alpha: + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_incoming_alpha: + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_fbuffer_alpha: + return D3DBLEND_DESTALPHA; + + case ColorBlendAttrib::O_one_minus_fbuffer_alpha: + return D3DBLEND_INVDESTALPHA; + + case ColorBlendAttrib::O_constant_color: + // Not supported by DX. + return D3DBLEND_SRCCOLOR; + + case ColorBlendAttrib::O_one_minus_constant_color: + // Not supported by DX. + return D3DBLEND_INVSRCCOLOR; + + case ColorBlendAttrib::O_constant_alpha: + // Not supported by DX. + return D3DBLEND_SRCALPHA; + + case ColorBlendAttrib::O_one_minus_constant_alpha: + // Not supported by DX. + return D3DBLEND_INVSRCALPHA; + + case ColorBlendAttrib::O_incoming_color_saturate: + return D3DBLEND_SRCALPHASAT; + } + + dxgsg9_cat.error() + << "Unknown color blend operand " << (int)operand << endl; + return D3DBLEND_ZERO; +} + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian9::report_texmgr_stats // Access: Protected @@ -4239,34 +4302,40 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, // will come this way, and they should ignore the colorwriteattrib value since it's been // handled separately in set_color_writemask enable_blend(true); + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); call_dxBlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE); return; } // Is there a color blend set? - switch (color_blend_mode) { - case ColorBlendAttrib::M_none: - break; - - case ColorBlendAttrib::M_multiply: + if (color_blend_mode != ColorBlendAttrib::M_none) { enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ZERO); - return; - case ColorBlendAttrib::M_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_ONE, D3DBLEND_ONE); - return; + switch (color_blend_mode) { + case ColorBlendAttrib::M_add: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + break; - case ColorBlendAttrib::M_multiply_add: - enable_blend(true); - call_dxBlendFunc(D3DBLEND_DESTCOLOR, D3DBLEND_ONE); - return; + case ColorBlendAttrib::M_subtract: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); + break; - default: - dxgsg9_cat.error() - << "Unknown color blend mode " << (int)color_blend_mode << endl; - break; + case ColorBlendAttrib::M_inv_subtract: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); + break; + + case ColorBlendAttrib::M_min: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); + break; + + case ColorBlendAttrib::M_max: + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX); + break; + } + + call_dxBlendFunc(get_blend_func(_color_blend->get_operand_a()), + get_blend_func(_color_blend->get_operand_b())); + return; } // No color blend; is there a transparency set? @@ -4281,6 +4350,7 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, case TransparencyAttrib::M_multisample_mask: case TransparencyAttrib::M_dual: enable_blend(true); + _pD3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); call_dxBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); return; diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index d673986fbf..8776cb1a5e 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -218,6 +218,7 @@ protected: INLINE void call_dxLightModelAmbient(const Colorf& color); INLINE void call_dxAlphaFunc(D3DCMPFUNC func, float refval); INLINE void call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc); + static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); INLINE void enable_dither(bool val); INLINE void enable_stencil_test(bool val); void report_texmgr_stats(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index a078f1820c..758e064a05 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -119,9 +119,11 @@ issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator, glgsg->issue_transformed_color(color); } -// This noop function is assigned to _glActiveTexture in case we don't -// have multitexturing support, so it will always be safe to call -// _glActiveTexture(). +// The following noop functions are assigned to the corresponding +// glext function pointers in the class, in case the functions are not +// defined by the GL, just so it will always be safe to call the +// extension functions. + static void APIENTRY null_glActiveTexture(GLenum gl_texture_stage) { // If we don't support multitexture, we'd better not try to request @@ -129,6 +131,14 @@ null_glActiveTexture(GLenum gl_texture_stage) { nassertv(gl_texture_stage == GL_TEXTURE0); } +static void APIENTRY +null_glBlendEquation(GLenum) { +} + +static void APIENTRY +null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) { +} + //////////////////////////////////////////////////////////////////// // Function: uchar_bgr_to_rgb // Description: Recopies the given array of pixels, converting from @@ -335,6 +345,32 @@ reset() { _glActiveTexture = null_glActiveTexture; } + _glBlendEquation = NULL; + if (has_extension("GL_EXT_blend_minmax") || is_at_least_version(1, 2)) { + _glBlendEquation = (PFNGLBLENDEQUATIONEXTPROC) + get_extension_func(GLPREFIX_QUOTED, "BlendEquationEXT"); + if (_glBlendEquation == NULL) { + GLCAT.warning() + << "BlendEquation advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; + } + } + if (_glBlendEquation == NULL) { + _glBlendEquation = null_glBlendEquation; + } + + _glBlendColor = NULL; + if (has_extension("GL_EXT_blend_color") || is_at_least_version(1, 2)) { + _glBlendColor = (PFNGLBLENDCOLOREXTPROC) + get_extension_func(GLPREFIX_QUOTED, "BlendColorEXT"); + if (_glBlendColor == NULL) { + GLCAT.warning() + << "BlendColor advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; + } + } + if (_glBlendColor == NULL) { + _glBlendColor = null_glBlendColor; + } + _edge_clamp = GL_CLAMP; if (has_extension("GL_SGIS_texture_edge_clamp") || is_at_least_version(1, 2)) { @@ -3440,7 +3476,7 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr) { ColorWriteAttrib::make(ColorWriteAttrib::M_on), RenderModeAttrib::make(RenderModeAttrib::M_filled), //TexMatrixAttrib::make(LMatrix4f::ident_mat()), - ColorBlendAttrib::make(ColorBlendAttrib::M_none), + ColorBlendAttrib::make_off(), TransparencyAttrib::make(TransparencyAttrib::M_none), }; basic_state = @@ -3641,7 +3677,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, // GL's. //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: -get_texture_wrap_mode(Texture::WrapMode wm) { +get_texture_wrap_mode(Texture::WrapMode wm) const { if (CLP(ignore_clamp)) { return GL_REPEAT; } @@ -3670,7 +3706,7 @@ get_texture_wrap_mode(Texture::WrapMode wm) { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_filter_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the Texture's internal filter type symbols // to GL's. //////////////////////////////////////////////////////////////////// @@ -3717,7 +3753,7 @@ get_texture_filter_type(Texture::FilterType ft) { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_image_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the PixelBuffer's internal Type symbols // to GL's. //////////////////////////////////////////////////////////////////// @@ -3746,7 +3782,7 @@ get_image_type(PixelBuffer::Type type) { // to GL's. //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_external_image_format(PixelBuffer::Format format) { +get_external_image_format(PixelBuffer::Format format) const { switch (format) { case PixelBuffer::F_color_index: return GL_COLOR_INDEX; @@ -3789,7 +3825,7 @@ get_external_image_format(PixelBuffer::Format format) { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_internal_image_format -// Access: Protected +// Access: Protected, Static // Description: Maps from the PixelBuffer's Format symbols to a // suitable internal format for GL textures. //////////////////////////////////////////////////////////////////// @@ -3841,12 +3877,12 @@ get_internal_image_format(PixelBuffer::Format format) { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_apply_mode_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the texture stage's mode types // to the corresponding OpenGL ids //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_texture_apply_mode_type(TextureStage::Mode am) const { +get_texture_apply_mode_type(TextureStage::Mode am) { switch (am) { case TextureStage::M_modulate: return GL_MODULATE; case TextureStage::M_decal: return GL_DECAL; @@ -3863,12 +3899,12 @@ get_texture_apply_mode_type(TextureStage::Mode am) const { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_combine_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the texture stage's CombineMode types // to the corresponding OpenGL ids //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_texture_combine_type(TextureStage::CombineMode cm) const { +get_texture_combine_type(TextureStage::CombineMode cm) { switch (cm) { case TextureStage::CM_undefined: // fall through case TextureStage::CM_replace: return GL_REPLACE; @@ -3887,12 +3923,12 @@ get_texture_combine_type(TextureStage::CombineMode cm) const { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_src_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the texture stage's CombineSource types // to the corresponding OpenGL ids //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_texture_src_type(TextureStage::CombineSource cs) const { +get_texture_src_type(TextureStage::CombineSource cs) { switch (cs) { case TextureStage::CS_undefined: // fall through case TextureStage::CS_texture: return GL_TEXTURE; @@ -3908,12 +3944,12 @@ get_texture_src_type(TextureStage::CombineSource cs) const { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_texture_operand_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the texture stage's CombineOperand types // to the corresponding OpenGL ids //////////////////////////////////////////////////////////////////// GLint CLP(GraphicsStateGuardian):: -get_texture_operand_type(TextureStage::CombineOperand co) const { +get_texture_operand_type(TextureStage::CombineOperand co) { switch (co) { case TextureStage::CO_undefined: // fall through case TextureStage::CO_src_alpha: return GL_SRC_ALPHA; @@ -3929,11 +3965,11 @@ get_texture_operand_type(TextureStage::CombineOperand co) const { //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::get_fog_mode_type -// Access: Protected +// Access: Protected, Static // Description: Maps from the fog types to gl version //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: -get_fog_mode_type(Fog::Mode m) const { +get_fog_mode_type(Fog::Mode m) { switch(m) { case Fog::M_linear: return GL_LINEAR; case Fog::M_exponential: return GL_EXP; @@ -3948,6 +3984,97 @@ get_fog_mode_type(Fog::Mode m) const { } } +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_blend_equation_type +// Access: Protected, Static +// Description: Maps from ColorBlendAttrib::Mode to glBlendEquation +// value. +//////////////////////////////////////////////////////////////////// +GLenum CLP(GraphicsStateGuardian):: +get_blend_equation_type(ColorBlendAttrib::Mode mode) { + switch (mode) { + case ColorBlendAttrib::M_add: + return GL_FUNC_ADD; + + case ColorBlendAttrib::M_subtract: + return GL_FUNC_SUBTRACT; + + case ColorBlendAttrib::M_inv_subtract: + return GL_FUNC_REVERSE_SUBTRACT; + + case ColorBlendAttrib::M_min: + return GL_MIN; + + case ColorBlendAttrib::M_max: + return GL_MAX; + } + + GLCAT.error() + << "Unknown color blend mode " << (int)mode << endl; + return GL_FUNC_ADD; +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GraphicsStateGuardian)::get_blend_func +// Access: Protected, Static +// Description: Maps from ColorBlendAttrib::Operand to glBlendFunc +// value. +//////////////////////////////////////////////////////////////////// +GLenum CLP(GraphicsStateGuardian):: +get_blend_func(ColorBlendAttrib::Operand operand) { + switch (operand) { + case ColorBlendAttrib::O_zero: + return GL_ZERO; + + case ColorBlendAttrib::O_one: + return GL_ONE; + + case ColorBlendAttrib::O_incoming_color: + return GL_SRC_COLOR; + + case ColorBlendAttrib::O_one_minus_incoming_color: + return GL_ONE_MINUS_SRC_COLOR; + + case ColorBlendAttrib::O_fbuffer_color: + return GL_DST_COLOR; + + case ColorBlendAttrib::O_one_minus_fbuffer_color: + return GL_ONE_MINUS_DST_COLOR; + + case ColorBlendAttrib::O_incoming_alpha: + return GL_SRC_ALPHA; + + case ColorBlendAttrib::O_one_minus_incoming_alpha: + return GL_ONE_MINUS_SRC_ALPHA; + + case ColorBlendAttrib::O_fbuffer_alpha: + return GL_DST_ALPHA; + + case ColorBlendAttrib::O_one_minus_fbuffer_alpha: + return GL_ONE_MINUS_DST_ALPHA; + + case ColorBlendAttrib::O_constant_color: + return GL_CONSTANT_COLOR; + + case ColorBlendAttrib::O_one_minus_constant_color: + return GL_ONE_MINUS_CONSTANT_COLOR; + + case ColorBlendAttrib::O_constant_alpha: + return GL_CONSTANT_ALPHA; + + case ColorBlendAttrib::O_one_minus_constant_alpha: + return GL_ONE_MINUS_CONSTANT_ALPHA; + + case ColorBlendAttrib::O_incoming_color_saturate: + return GL_SRC_ALPHA_SATURATE; + } + + GLCAT.error() + << "Unknown color blend operand " << (int)operand << endl; + return GL_ZERO; +} + + //////////////////////////////////////////////////////////////////// // Function: CLP(GraphicsStateGuardian)::print_gfx_visual // Access: Public @@ -4237,80 +4364,63 @@ set_blend_mode(ColorWriteAttrib::Mode color_write_mode, enable_multisample_alpha_one(false); enable_multisample_alpha_mask(false); enable_blend(true); + _glBlendEquation(GL_FUNC_ADD); GLP(BlendFunc)(GL_ZERO, GL_ONE); return; } // Is there a color blend set? - switch (color_blend_mode) { - case ColorBlendAttrib::M_none: - break; - - case ColorBlendAttrib::M_multiply: + if (color_blend_mode != ColorBlendAttrib::M_none) { enable_multisample_alpha_one(false); enable_multisample_alpha_mask(false); enable_blend(true); - GLP(BlendFunc)(GL_DST_COLOR, GL_ZERO); + _glBlendEquation(get_blend_equation_type(color_blend_mode)); + GLP(BlendFunc)(get_blend_func(_color_blend->get_operand_a()), + get_blend_func(_color_blend->get_operand_b())); + Colorf c = _color_blend->get_color(); + _glBlendColor(c[0], c[1], c[2], c[3]); return; - - case ColorBlendAttrib::M_add: - enable_multisample_alpha_one(false); - enable_multisample_alpha_mask(false); - enable_blend(true); - GLP(BlendFunc)(GL_ONE, GL_ONE); - return; - - case ColorBlendAttrib::M_multiply_add: - enable_multisample_alpha_one(false); - enable_multisample_alpha_mask(false); - enable_blend(true); - GLP(BlendFunc)(GL_DST_COLOR, GL_ONE); - return; - - default: - GLCAT.error() - << "Unknown color blend mode " << (int)color_blend_mode << endl; - break; } // No color blend; is there a transparency set? switch (transparency_mode) { - case TransparencyAttrib::M_none: - case TransparencyAttrib::M_binary: - break; + 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_sorted" is with the write to the depth buffer - // disabled.) Or should we just use the separate depth write - // transition to control this? Doing it implicitly requires a - // bit more logic here and in the state management; for now we - // require the user to explicitly turn off the depth write. - enable_multisample_alpha_one(false); - enable_multisample_alpha_mask(false); - enable_blend(true); - GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - return; + 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_sorted" is with the write to the depth buffer + // disabled.) Or should we just use the separate depth write + // transition to control this? Doing it implicitly requires a + // bit more logic here and in the state management; for now we + // require the user to explicitly turn off the depth write. + enable_multisample_alpha_one(false); + enable_multisample_alpha_mask(false); + enable_blend(true); + _glBlendEquation(GL_FUNC_ADD); + GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return; - case TransparencyAttrib::M_multisample: - enable_multisample_alpha_one(true); - enable_multisample_alpha_mask(true); - enable_blend(false); - return; + case TransparencyAttrib::M_multisample: + enable_multisample_alpha_one(true); + enable_multisample_alpha_mask(true); + enable_blend(false); + return; - case TransparencyAttrib::M_multisample_mask: - enable_multisample_alpha_one(false); - enable_multisample_alpha_mask(true); - enable_blend(false); - return; + case TransparencyAttrib::M_multisample_mask: + enable_multisample_alpha_one(false); + enable_multisample_alpha_mask(true); + enable_blend(false); + return; - default: - GLCAT.error() - << "invalid transparency mode " << (int)transparency_mode << endl; - break; + default: + GLCAT.error() + << "invalid transparency mode " << (int)transparency_mode << endl; + break; } // Nothing's set, so disable blending. diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 7c254913d4..e0ea396bd3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -206,16 +206,18 @@ protected: void draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb); - GLenum get_texture_wrap_mode(Texture::WrapMode wm); - GLenum get_texture_filter_type(Texture::FilterType ft); - GLenum get_image_type(PixelBuffer::Type type); - GLint get_external_image_format(PixelBuffer::Format format); - GLint get_internal_image_format(PixelBuffer::Format format); - GLint get_texture_apply_mode_type(TextureStage::Mode am) const; - GLint get_texture_combine_type(TextureStage::CombineMode cm) const; - GLint get_texture_src_type(TextureStage::CombineSource cs) const; - GLint get_texture_operand_type(TextureStage::CombineOperand co) const; - GLenum get_fog_mode_type(Fog::Mode m) const; + GLenum get_texture_wrap_mode(Texture::WrapMode wm) const; + static GLenum get_texture_filter_type(Texture::FilterType ft); + static GLenum get_image_type(PixelBuffer::Type type); + GLint get_external_image_format(PixelBuffer::Format format) const; + static GLint get_internal_image_format(PixelBuffer::Format format); + static GLint get_texture_apply_mode_type(TextureStage::Mode am); + static GLint get_texture_combine_type(TextureStage::CombineMode cm); + static GLint get_texture_src_type(TextureStage::CombineSource cs); + static GLint get_texture_operand_type(TextureStage::CombineOperand co); + static GLenum get_fog_mode_type(Fog::Mode m); + static GLenum get_blend_equation_type(ColorBlendAttrib::Mode mode); + static GLenum get_blend_func(ColorBlendAttrib::Operand operand); static CPT(RenderState) get_untextured_state(); @@ -277,6 +279,9 @@ public: PFNGLACTIVETEXTUREPROC _glActiveTexture; PFNGLMULTITEXCOORD2FVPROC _glMultiTexCoord2fv; + PFNGLBLENDEQUATIONEXTPROC _glBlendEquation; + PFNGLBLENDCOLOREXTPROC _glBlendColor; + GLenum _edge_clamp; GLenum _border_clamp; GLenum _mirror_repeat; diff --git a/panda/src/pgraph/colorBlendAttrib.I b/panda/src/pgraph/colorBlendAttrib.I index bd25bd65e2..fe12a71140 100644 --- a/panda/src/pgraph/colorBlendAttrib.I +++ b/panda/src/pgraph/colorBlendAttrib.I @@ -24,8 +24,28 @@ // ColorBlendAttrib object. //////////////////////////////////////////////////////////////////// INLINE ColorBlendAttrib:: -ColorBlendAttrib(ColorBlendAttrib::Mode mode) : - _mode(mode) +ColorBlendAttrib() : + _mode(M_none), + _a(O_one), + _b(O_one), + _color(Colorf::zero()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::Constructor +// Access: Private +// Description: Use ColorBlendAttrib::make() to construct a new +// ColorBlendAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE ColorBlendAttrib:: +ColorBlendAttrib(ColorBlendAttrib::Mode mode, + ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + const Colorf &color) : + _mode(mode), + _a(a), + _b(b), + _color(color) { } @@ -38,3 +58,53 @@ INLINE ColorBlendAttrib::Mode ColorBlendAttrib:: get_mode() const { return _mode; } + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::get_operand_a +// Access: Published +// Description: Returns the multiplier for the first component. +//////////////////////////////////////////////////////////////////// +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_operand_a() const { + return _a; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::get_operand_b +// Access: Published +// Description: Returns the multiplier for the second component. +//////////////////////////////////////////////////////////////////// +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_operand_b() const { + return _b; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::get_color +// Access: Published +// Description: Returns the constant color associated with the attrib. +//////////////////////////////////////////////////////////////////// +INLINE Colorf ColorBlendAttrib:: +get_color() const { + return _color; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::involves_constant_color +// Access: Published, Static +// Description: Returns true if the indicated operand uses the +// constant color, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool ColorBlendAttrib:: +involves_constant_color(Operand operand) { + switch (operand) { + case O_constant_color: + case O_one_minus_constant_color: + case O_constant_alpha: + case O_one_minus_constant_alpha: + return true; + + default: + return false; + } +} diff --git a/panda/src/pgraph/colorBlendAttrib.cxx b/panda/src/pgraph/colorBlendAttrib.cxx index d03b702a8f..969f091296 100644 --- a/panda/src/pgraph/colorBlendAttrib.cxx +++ b/panda/src/pgraph/colorBlendAttrib.cxx @@ -26,14 +26,45 @@ TypeHandle ColorBlendAttrib::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::make_off +// Access: Published, Static +// Description: Constructs a new ColorBlendAttrib object that +// disables special-effect blending, allowing normal +// transparency to be used instead. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ColorBlendAttrib:: +make_off() { + ColorBlendAttrib *attrib = new ColorBlendAttrib; + return return_new(attrib); +} + //////////////////////////////////////////////////////////////////// // Function: ColorBlendAttrib::make // Access: Published, Static -// Description: Constructs a new ColorBlendAttrib object. +// Description: Constructs a new ColorBlendAttrib object. This +// constructor is deprecated; use the one below, which +// takes three or four parameters, instead. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ColorBlendAttrib:: make(ColorBlendAttrib::Mode mode) { - ColorBlendAttrib *attrib = new ColorBlendAttrib(mode); + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, O_one, O_one, + Colorf::zero()); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorBlendAttrib::make +// Access: Published, Static +// Description: Constructs a new ColorBlendAttrib object that enables +// special-effect blending. This supercedes +// transparency. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ColorBlendAttrib:: +make(ColorBlendAttrib::Mode mode, + ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + const Colorf &color) { + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, color); return return_new(attrib); } @@ -58,23 +89,16 @@ issue(GraphicsStateGuardianBase *gsg) const { //////////////////////////////////////////////////////////////////// void ColorBlendAttrib:: output(ostream &out) const { - out << get_type() << ":"; - switch (get_mode()) { - case M_none: - out << "none"; - break; + out << get_type() << ":" << get_mode(); - case M_multiply: - out << "multiply"; - break; - - case M_add: - out << "add"; - break; - - case M_multiply_add: - out << "multiply_add"; - break; + if (get_mode() != M_none) { + out << "(" << get_operand_a() + << "," << get_operand_b(); + if (involves_constant_color(get_operand_a()) || + involves_constant_color(get_operand_b())) { + out << "," << get_color(); + } + out << ")"; } } @@ -97,7 +121,20 @@ int ColorBlendAttrib:: compare_to_impl(const RenderAttrib *other) const { const ColorBlendAttrib *ta; DCAST_INTO_R(ta, other, 0); - return (int)_mode - (int)ta->_mode; + + if (_mode != ta->_mode) { + return (int)_mode - (int)ta->_mode; + } + + if (_a != ta->_a) { + return (int)_a - (int)ta->_a; + } + + if (_b != ta->_b) { + return (int)_b - (int)ta->_b; + } + + return _color.compare_to(ta->_color); } //////////////////////////////////////////////////////////////////// @@ -137,7 +174,10 @@ void ColorBlendAttrib:: write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); - dg.add_int8(_mode); + dg.add_uint8(_mode); + dg.add_uint8(_a); + dg.add_uint8(_b); + _color.write_datagram(dg); } //////////////////////////////////////////////////////////////////// @@ -171,5 +211,93 @@ void ColorBlendAttrib:: fillin(DatagramIterator &scan, BamReader *manager) { RenderAttrib::fillin(scan, manager); - _mode = (Mode)scan.get_int8(); + _mode = (Mode)scan.get_uint8(); + _a = (Operand)scan.get_uint8(); + _b = (Operand)scan.get_uint8(); + _color.read_datagram(scan); +} + +//////////////////////////////////////////////////////////////////// +// Function: ostream << ColorBlendAttrib::Mode +// Description: +//////////////////////////////////////////////////////////////////// +ostream & +operator << (ostream &out, ColorBlendAttrib::Mode mode) { + switch (mode) { + case ColorBlendAttrib::M_none: + return out << "none"; + + case ColorBlendAttrib::M_add: + return out << "add"; + + case ColorBlendAttrib::M_subtract: + return out << "subtract"; + + case ColorBlendAttrib::M_inv_subtract: + return out << "inv_subtract"; + + case ColorBlendAttrib::M_min: + return out << "min"; + + case ColorBlendAttrib::M_max: + return out << "max"; + } + + return out << "**invalid ColorBlendAttrib::Mode(" << (int)mode << ")**"; +} + +//////////////////////////////////////////////////////////////////// +// Function: ostream << ColorBlendAttrib::Operand +// Description: +//////////////////////////////////////////////////////////////////// +ostream & +operator << (ostream &out, ColorBlendAttrib::Operand operand) { + switch (operand) { + case ColorBlendAttrib::O_zero: + return out << "0"; + + case ColorBlendAttrib::O_one: + return out << "1"; + + case ColorBlendAttrib::O_incoming_color: + return out << "ic"; + + case ColorBlendAttrib::O_one_minus_incoming_color: + return out << "1-ic"; + + case ColorBlendAttrib::O_fbuffer_color: + return out << "fc"; + + case ColorBlendAttrib::O_one_minus_fbuffer_color: + return out << "1-fc"; + + case ColorBlendAttrib::O_incoming_alpha: + return out << "ia"; + + case ColorBlendAttrib::O_one_minus_incoming_alpha: + return out << "1-ia"; + + case ColorBlendAttrib::O_fbuffer_alpha: + return out << "fa"; + + case ColorBlendAttrib::O_one_minus_fbuffer_alpha: + return out << "1-fa"; + + case ColorBlendAttrib::O_constant_color: + return out << "cc"; + + case ColorBlendAttrib::O_one_minus_constant_color: + return out << "1-cc"; + + case ColorBlendAttrib::O_constant_alpha: + return out << "ca"; + + case ColorBlendAttrib::O_one_minus_constant_alpha: + return out << "1-ca"; + + case ColorBlendAttrib::O_incoming_color_saturate: + return out << "ics"; + } + + return out << "**invalid ColorBlendAttrib::Operand(" << (int)operand << ")**"; } diff --git a/panda/src/pgraph/colorBlendAttrib.h b/panda/src/pgraph/colorBlendAttrib.h index 2437b536c9..3d11e26a46 100644 --- a/panda/src/pgraph/colorBlendAttrib.h +++ b/panda/src/pgraph/colorBlendAttrib.h @@ -20,7 +20,7 @@ #define COLORBLENDATTRIB_H #include "pandabase.h" - +#include "luse.h" #include "renderAttrib.h" class FactoryParams; @@ -35,19 +35,48 @@ class EXPCL_PANDA ColorBlendAttrib : public RenderAttrib { PUBLISHED: enum Mode { M_none, // Blending is disabled - M_multiply, // color already in fbuffer * incoming color - M_add, // color already in fbuffer + incoming color - M_multiply_add, // color already in fbuffer * incoming color + - // color already in fbuffer + M_add, // incoming color * A + fbuffer color * B + M_subtract, // incoming color * A - fbuffer color * B + M_inv_subtract, // fbuffer color * B - incoming color * A + M_min, // min(incoming color, fbuffer color) + M_max // max(incoming color, fbuffer color) + }; + + enum Operand { + O_zero, + O_one, + O_incoming_color, + O_one_minus_incoming_color, + O_fbuffer_color, + O_one_minus_fbuffer_color, + O_incoming_alpha, + O_one_minus_incoming_alpha, + O_fbuffer_alpha, + O_one_minus_fbuffer_alpha, + O_constant_color, + O_one_minus_constant_color, + O_constant_alpha, + O_one_minus_constant_alpha, + O_incoming_color_saturate, // valid only for operand a }; private: - INLINE ColorBlendAttrib(Mode mode = M_none); + INLINE ColorBlendAttrib(); + INLINE ColorBlendAttrib(Mode mode, Operand a, Operand b, + const Colorf &color); PUBLISHED: + static CPT(RenderAttrib) make_off(); static CPT(RenderAttrib) make(Mode mode); + static CPT(RenderAttrib) make(Mode mode, Operand a, Operand b, + const Colorf &color = Colorf::zero()); INLINE Mode get_mode() const; + INLINE Operand get_operand_a() const; + INLINE Operand get_operand_b() const; + INLINE Colorf get_color() const; + + INLINE static bool involves_constant_color(Operand operand); public: virtual void issue(GraphicsStateGuardianBase *gsg) const; @@ -59,6 +88,8 @@ protected: private: Mode _mode; + Operand _a, _b; + Colorf _color; public: static void register_with_read_factory(); @@ -86,6 +117,9 @@ private: static TypeHandle _type_handle; }; +ostream &operator << (ostream &out, ColorBlendAttrib::Mode mode); +ostream &operator << (ostream &out, ColorBlendAttrib::Operand operand); + #include "colorBlendAttrib.I" #endif