diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index db8e1f198fc..ea3a9b61acd 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -684,6 +684,15 @@ get_max_color_targets() const { return _max_color_targets; } +/** + * Returns true if dual source (incoming1_color and incoming1_alpha) blend + * operands are supported by this GSG. + */ +INLINE bool GraphicsStateGuardian:: +get_supports_dual_source_blending() const { + return _supports_dual_source_blending; +} + /** * Deprecated. Use get_max_color_targets() instead, which returns the exact * same value. diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index d294dc47f35..35603fcea6f 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -246,6 +246,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, // Assume a maximum of 1 render target in absence of MRT. _max_color_targets = 1; + _supports_dual_source_blending = false; _supported_geom_rendering = 0; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 401c538b315..825b03286dc 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -172,6 +172,7 @@ class EXPCL_PANDA_DISPLAY GraphicsStateGuardian : public GraphicsStateGuardianBa INLINE int get_max_color_targets() const; INLINE int get_maximum_simultaneous_render_targets() const; + INLINE bool get_supports_dual_source_blending() const; MAKE_PROPERTY(max_vertices_per_array, get_max_vertices_per_array); MAKE_PROPERTY(max_vertices_per_primitive, get_max_vertices_per_primitive); @@ -217,6 +218,7 @@ class EXPCL_PANDA_DISPLAY GraphicsStateGuardian : public GraphicsStateGuardianBa MAKE_PROPERTY(supports_timer_query, get_supports_timer_query); MAKE_PROPERTY(timer_queries_active, get_timer_queries_active); MAKE_PROPERTY(max_color_targets, get_max_color_targets); + MAKE_PROPERTY(supports_dual_source_blending, get_supports_dual_source_blending); INLINE ShaderModel get_shader_model() const; INLINE void set_shader_model(ShaderModel shader_model); @@ -609,6 +611,7 @@ class EXPCL_PANDA_DISPLAY GraphicsStateGuardian : public GraphicsStateGuardianBa bool _supports_indirect_draw; int _max_color_targets; + bool _supports_dual_source_blending; int _supported_geom_rendering; bool _color_scale_via_lighting; diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index f71e01d2988..505fe7b10da 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3766,43 +3766,24 @@ do_issue_blending() { } } - const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot())); - CPT(ColorBlendAttrib) color_blend = target_color_blend; - ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); + const ColorBlendAttrib *color_blend; + _target_rs->get_attrib_def(color_blend); + ColorBlendAttrib::Mode color_blend_mode = color_blend->get_mode(); - const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot())); + const TransparencyAttrib *target_transparency; + _target_rs->get_attrib_def(target_transparency); TransparencyAttrib::Mode transparency_mode = target_transparency->get_mode(); // Is there a color blend set? if (color_blend_mode != ColorBlendAttrib::M_none) { set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); - - switch (color_blend_mode) { - case ColorBlendAttrib::M_add: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); - break; - - case ColorBlendAttrib::M_subtract: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); - break; - - case ColorBlendAttrib::M_inv_subtract: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); - break; - - case ColorBlendAttrib::M_min: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MIN); - break; - - case ColorBlendAttrib::M_max: - set_render_state(D3DRS_BLENDOP, D3DBLENDOP_MAX); - break; - } - - set_render_state(D3DRS_SRCBLEND, - get_blend_func(color_blend->get_operand_a())); - set_render_state(D3DRS_DESTBLEND, - get_blend_func(color_blend->get_operand_b())); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_BLENDOP, get_blend_mode(color_blend_mode)); + set_render_state(D3DRS_BLENDOPALPHA, get_blend_mode(color_blend->get_alpha_mode())); + set_render_state(D3DRS_SRCBLEND, get_blend_func(color_blend->get_operand_a())); + set_render_state(D3DRS_DESTBLEND, get_blend_func(color_blend->get_operand_b())); + set_render_state(D3DRS_SRCBLENDALPHA, get_blend_func(color_blend->get_alpha_operand_a())); + set_render_state(D3DRS_DESTBLENDALPHA, get_blend_func(color_blend->get_alpha_operand_b())); return; } @@ -3817,6 +3798,7 @@ do_issue_blending() { case TransparencyAttrib::M_multisample_mask: case TransparencyAttrib::M_dual: set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); set_render_state(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); set_render_state(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); @@ -3824,6 +3806,7 @@ do_issue_blending() { case TransparencyAttrib::M_premultiplied_alpha: set_render_state(D3DRS_ALPHABLENDENABLE, TRUE); + set_render_state(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); set_render_state(D3DRS_BLENDOP, D3DBLENDOP_ADD); set_render_state(D3DRS_SRCBLEND, D3DBLEND_ONE); set_render_state(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); @@ -4052,6 +4035,33 @@ get_light_color(Light *light) const { return *(D3DCOLORVALUE *)cf.get_data(); } +/** + * Maps from ColorBlendAttrib::Mode to D3DBLENDOP vaule. + */ +D3DBLENDOP DXGraphicsStateGuardian9:: +get_blend_mode(ColorBlendAttrib::Mode mode) { + switch (mode) { + case ColorBlendAttrib::M_add: + return D3DBLENDOP_ADD; + + case ColorBlendAttrib::M_subtract: + return D3DBLENDOP_SUBTRACT; + + case ColorBlendAttrib::M_inv_subtract: + return D3DBLENDOP_REVSUBTRACT; + + case ColorBlendAttrib::M_min: + return D3DBLENDOP_MIN; + + case ColorBlendAttrib::M_max: + return D3DBLENDOP_MAX; + } + + dxgsg9_cat.error() + << "Unknown color blend mode " << (int)mode << endl; + return D3DBLENDOP_ADD; +} + /** * Maps from ColorBlendAttrib::Operand to D3DBLEND value. */ @@ -4106,6 +4116,21 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_incoming_color_saturate: return D3DBLEND_SRCALPHASAT; + + case ColorBlendAttrib::O_incoming1_color: + return D3DBLEND_SRCCOLOR2; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return D3DBLEND_INVSRCCOLOR2; + + case ColorBlendAttrib::O_incoming1_alpha: + // Not supported by DX. + return D3DBLEND_SRCCOLOR2; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + // Not supported by DX. + return D3DBLEND_INVSRCCOLOR2; + } dxgsg9_cat.error() diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index 4a51d214cbe..512cedbda2c 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -217,6 +217,7 @@ class EXPCL_PANDADX DXGraphicsStateGuardian9 : public GraphicsStateGuardian { const D3DCOLORVALUE &get_light_color(Light *light) const; INLINE static D3DTRANSFORMSTATETYPE get_tex_mat_sym(int stage_index); + static D3DBLENDOP get_blend_mode(ColorBlendAttrib::Mode mode); static D3DBLEND get_blend_func(ColorBlendAttrib::Operand operand); void report_texmgr_stats(); diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index 33046d00f9f..5e7059856c3 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -123,6 +123,10 @@ typedef char GLchar; #define GL_MAX_DRAW_BUFFERS GL_MAX_DRAW_BUFFERS_NV #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE +#define GL_SRC1_COLOR GL_SRC1_COLOR_EXT +#define GL_ONE_MINUS_SRC1_COLOR GL_ONE_MINUS_SRC1_COLOR_EXT +#define GL_SRC1_ALPHA GL_SRC1_ALPHA_EXT +#define GL_ONE_MINUS_SRC1_ALPHA GL_ONE_MINUS_SRC1_ALPHA_EXT // For GLES 3 compat - need a better solution for this #define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x1 diff --git a/panda/src/gles2gsg/panda_esgl2ext.h b/panda/src/gles2gsg/panda_esgl2ext.h index 7e6ff9c32a4..a221f003874 100644 --- a/panda/src/gles2gsg/panda_esgl2ext.h +++ b/panda/src/gles2gsg/panda_esgl2ext.h @@ -430,6 +430,17 @@ typedef struct __GLsync *GLsync; * EXT extension tokens *------------------------------------------------------------------------*/ +#ifndef GL_EXT_blend_func_extended +#define GL_EXT_blend_func_extended 1 +#define GL_SRC1_COLOR_EXT 0x88F9 +#define GL_SRC1_ALPHA_EXT 0x8589 +#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB +#define GL_SRC_ALPHA_SATURATE_EXT 0x0308 +#define GL_LOCATION_INDEX_EXT 0x930F +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC +#endif + /* GL_EXT_blend_minmax */ #ifndef GL_EXT_blend_minmax #define GL_MIN_EXT 0x8007 diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index a9df4de4698..de53ee150fb 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -129,16 +129,23 @@ null_glActiveTexture(GLenum gl_texture_stage) { #ifdef OPENGLES_2 #define _glBlendEquation glBlendEquation +#define _glBlendEquationSeparate glBlendEquationSeparate +#define _glBlendFuncSeparate glBlendFuncSeparate #define _glBlendColor glBlendColor #else static void APIENTRY null_glBlendEquation(GLenum) { } -#endif + +static void APIENTRY +null_glBlendFuncSeparate(GLenum src, GLenum dest, GLenum, GLenum) { + glBlendFunc(src, dest); +} static void APIENTRY null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) { } +#endif #ifndef OPENGLES_1 // We have a default shader that will be applied when there isn't any shader @@ -2284,29 +2291,115 @@ reset() { } #endif - // In OpenGL ES 2.x, this is supported in the core. -#ifndef OPENGLES_2 - _glBlendEquation = NULL; - bool supports_blend_equation = false; +#ifdef OPENGLES_1 + // In OpenGL ES 1, blending is supported via extensions. + if (has_extension("GL_OES_blend_subtract")) { + _glBlendEquation = (PFNGLBLENDEQUATIONPROC) + get_extension_func("glBlendEquationOES"); + + if (_glBlendEquation == NULL) { + _glBlendEquation = null_glBlendEquation; + GLCAT.warning() + << "BlendEquationOES advertised as supported by OpenGL ES runtime, but " + "could not get pointer to extension function.\n"; + } + } else { + _glBlendEquation = null_glBlendEquation; + } + + if (has_extension("GL_OES_blend_equation_separate")) { + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEOESPROC) + get_extension_func("glBlendEquationSeparateOES"); + + if (_glBlendEquation == NULL) { + _supports_blend_equation_separate = false; + GLCAT.warning() + << "BlendEquationSeparateOES advertised as supported by OpenGL ES " + "runtime, but could not get pointer to extension function.\n"; + } else { + _supports_blend_equation_separate = true; + } + } else { + _supports_blend_equation_separate = false; + _glBlendEquationSeparate = NULL; + } + + if (has_extension("GL_OES_blend_func_separate")) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEOESPROC) + get_extension_func("glBlendFuncSeparateOES"); + + if (_glBlendFuncSeparate == NULL) { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + GLCAT.warning() + << "BlendFuncSeparateOES advertised as supported by OpenGL ES runtime, but " + "could not get pointer to extension function.\n"; + } + } else { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + } + +#elif defined(OPENGLES) + // In OpenGL ES 2.x and above, this is supported in the core. + _supports_blend_equation_separate = false; + +#else if (is_at_least_gl_version(1, 2)) { - supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) get_extension_func("glBlendEquation"); - } else if (has_extension("GL_OES_blend_subtract")) { - supports_blend_equation = true; - _glBlendEquation = (PFNGLBLENDEQUATIONPROC) - get_extension_func("glBlendEquationOES"); + } else if (has_extension("GL_EXT_blend_minmax")) { - supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) get_extension_func("glBlendEquationEXT"); + + } else { + _glBlendEquation = null_glBlendEquation; } - if (supports_blend_equation && _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; + GLCAT.warning() + << "BlendEquation advertised as supported by OpenGL runtime, but could " + "not get pointer to extension function.\n"; + } + + if (is_at_least_gl_version(2, 0)) { + _supports_blend_equation_separate = true; + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) + get_extension_func("glBlendEquationSeparate"); + + } else if (has_extension("GL_EXT_blend_equation_separate")) { + _supports_blend_equation_separate = true; + _glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEEXTPROC) + get_extension_func("glBlendEquationSeparateEXT"); + + } else { + _supports_blend_equation_separate = false; + _glBlendEquationSeparate = NULL; + } + + if (_supports_blend_equation_separate && _glBlendEquationSeparate == NULL) { + _supports_blend_equation_separate = false; + GLCAT.warning() + << "BlendEquationSeparate advertised as supported by OpenGL runtime, " + "but could not get pointer to extension function.\n"; + } + + if (is_at_least_gl_version(1, 4)) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) + get_extension_func("glBlendFuncSeparate"); + + } else if (has_extension("GL_EXT_blend_func_separate")) { + _glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEEXTPROC) + get_extension_func("glBlendFuncSeparateEXT"); + + } else { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + } + + if (_glBlendFuncSeparate == NULL) { + _glBlendFuncSeparate = null_glBlendFuncSeparate; + GLCAT.warning() + << "BlendFuncSeparate advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; } #endif @@ -2332,6 +2425,15 @@ reset() { } #endif +#ifdef OPENGLES_1 + // OpenGL ES 1 doesn't support dual-source blending. +#elif defined(OPENGLES) + _supports_dual_source_blending = has_extension("GL_EXT_blend_func_extended"); +#else + _supports_dual_source_blending = + is_at_least_gl_version(3, 3) || has_extension("GL_ARB_blend_func_extended"); +#endif + #ifdef OPENGLES _edge_clamp = GL_CLAMP_TO_EDGE; #else @@ -6902,6 +7004,7 @@ do_issue_blending() { _target_rs->get_attrib_def(target_color_blend); CPT(ColorBlendAttrib) color_blend = target_color_blend; ColorBlendAttrib::Mode color_blend_mode = target_color_blend->get_mode(); + ColorBlendAttrib::Mode alpha_blend_mode = target_color_blend->get_alpha_mode(); const TransparencyAttrib *target_transparency; _target_rs->get_attrib_def(target_transparency); @@ -6914,9 +7017,17 @@ do_issue_blending() { enable_multisample_alpha_one(false); enable_multisample_alpha_mask(false); enable_blend(true); - _glBlendEquation(get_blend_equation_type(color_blend_mode)); - glBlendFunc(get_blend_func(color_blend->get_operand_a()), - get_blend_func(color_blend->get_operand_b())); + + if (_supports_blend_equation_separate) { + _glBlendEquationSeparate(get_blend_equation_type(color_blend_mode), + get_blend_equation_type(alpha_blend_mode)); + } else { + _glBlendEquation(get_blend_equation_type(color_blend_mode)); + } + _glBlendFuncSeparate(get_blend_func(color_blend->get_operand_a()), + get_blend_func(color_blend->get_operand_b()), + get_blend_func(color_blend->get_alpha_operand_a()), + get_blend_func(color_blend->get_alpha_operand_b())); #ifndef OPENGLES_1 LColor c; @@ -6931,9 +7042,17 @@ do_issue_blending() { #endif if (GLCAT.is_spam()) { - GLCAT.spam() << "glBlendEquation(" << color_blend_mode << ")\n"; - GLCAT.spam() << "glBlendFunc(" << color_blend->get_operand_a() - << color_blend->get_operand_b() << ")\n"; + if (_supports_blend_equation_separate) { + GLCAT.spam() << "glBlendEquationSeparate(" << color_blend_mode << ", " + << alpha_blend_mode << ")\n"; + } else { + GLCAT.spam() << "glBlendEquation(" << color_blend_mode << ")\n"; + } + GLCAT.spam() << "glBlendFuncSeparate(" + << color_blend->get_operand_a() << ", " + << color_blend->get_operand_b() << ", " + << color_blend->get_alpha_operand_a() << ", " + << color_blend->get_alpha_operand_b() << ")\n"; #ifndef OPENGLES_1 GLCAT.spam() << "glBlendColor(" << c << ")\n"; #endif @@ -9304,6 +9423,13 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_constant_alpha: case ColorBlendAttrib::O_one_minus_alpha_scale: break; + + // No dual-source blending, either. + case ColorBlendAttrib::O_incoming1_color: + case ColorBlendAttrib::O_one_minus_incoming1_color: + case ColorBlendAttrib::O_incoming1_alpha: + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + break; #else case ColorBlendAttrib::O_constant_color: case ColorBlendAttrib::O_color_scale: @@ -9320,6 +9446,18 @@ get_blend_func(ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_constant_alpha: case ColorBlendAttrib::O_one_minus_alpha_scale: return GL_ONE_MINUS_CONSTANT_ALPHA; + + case ColorBlendAttrib::O_incoming1_color: + return GL_SRC1_COLOR; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return GL_ONE_MINUS_SRC1_COLOR; + + case ColorBlendAttrib::O_incoming1_alpha: + return GL_SRC1_ALPHA; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + return GL_ONE_MINUS_SRC1_ALPHA; #endif case ColorBlendAttrib::O_incoming_color_saturate: diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 12739321dba..d06cf2de3f3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -141,6 +141,8 @@ typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, G typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); #ifndef OPENGLES_1 // GLSL shader functions @@ -817,8 +819,12 @@ class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian { PFNGLBUFFERSTORAGEPROC _glBufferStorage; #endif + bool _supports_blend_equation_separate; #ifndef OPENGLES_2 + // OpenGL ES 2+ has these in the core. PFNGLBLENDEQUATIONPROC _glBlendEquation; + PFNGLBLENDEQUATIONSEPARATEPROC _glBlendEquationSeparate; + PFNGLBLENDFUNCSEPARATEPROC _glBlendFuncSeparate; #endif #ifndef OPENGLES PFNGLBLENDCOLORPROC _glBlendColor; diff --git a/panda/src/pgraph/colorBlendAttrib.I b/panda/src/pgraph/colorBlendAttrib.I index fa2aca94ff2..1df1f9eb6c6 100644 --- a/panda/src/pgraph/colorBlendAttrib.I +++ b/panda/src/pgraph/colorBlendAttrib.I @@ -19,6 +19,9 @@ ColorBlendAttrib() : _mode(M_none), _a(O_one), _b(O_one), + _alpha_mode(M_none), + _alpha_a(O_one), + _alpha_b(O_one), _color(LColor::zero()), _involves_constant_color(false), _involves_color_scale(false) @@ -31,18 +34,29 @@ ColorBlendAttrib() : INLINE ColorBlendAttrib:: ColorBlendAttrib(ColorBlendAttrib::Mode mode, ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + ColorBlendAttrib::Mode alpha_mode, + ColorBlendAttrib::Operand alpha_a, ColorBlendAttrib::Operand alpha_b, const LColor &color) : _mode(mode), _a(a), _b(b), + _alpha_mode(alpha_mode), + _alpha_a(alpha_a), + _alpha_b(alpha_b), _color(color), - _involves_constant_color(involves_constant_color(a) || involves_constant_color(b)), - _involves_color_scale(involves_color_scale(a) || involves_color_scale(b)) + _involves_constant_color(involves_constant_color(a) || + involves_constant_color(b) || + involves_constant_color(alpha_a) || + involves_constant_color(alpha_b)), + _involves_color_scale(involves_color_scale(a) || + involves_color_scale(b) || + involves_color_scale(alpha_a) || + involves_color_scale(alpha_b)) { } /** - * Returns the colorBlend mode. + * Returns the blending mode for the RGB channels. */ INLINE ColorBlendAttrib::Mode ColorBlendAttrib:: get_mode() const { @@ -50,7 +64,7 @@ get_mode() const { } /** - * Returns the multiplier for the first component. + * Returns the RGB multiplier for the first component. */ INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: get_operand_a() const { @@ -58,13 +72,37 @@ get_operand_a() const { } /** - * Returns the multiplier for the second component. + * Returns the RGB multiplier for the second component. */ INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: get_operand_b() const { return _b; } +/** + * Returns the blending mode for the alpha channel. + */ +INLINE ColorBlendAttrib::Mode ColorBlendAttrib:: +get_alpha_mode() const { + return _alpha_mode; +} + +/** + * Returns the alpha multiplier for the first component. + */ +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_alpha_operand_a() const { + return _alpha_a; +} + +/** + * Returns the alpha multiplier for the second component. + */ +INLINE ColorBlendAttrib::Operand ColorBlendAttrib:: +get_alpha_operand_b() const { + return _alpha_b; +} + /** * Returns the constant color associated with the attrib. */ @@ -114,14 +152,5 @@ involves_constant_color(ColorBlendAttrib::Operand operand) { */ INLINE bool ColorBlendAttrib:: involves_color_scale(ColorBlendAttrib::Operand operand) { - switch (operand) { - case O_color_scale: - case O_one_minus_color_scale: - case O_alpha_scale: - case O_one_minus_alpha_scale: - return true; - - default: - return false; - } + return (operand >= O_color_scale); } diff --git a/panda/src/pgraph/colorBlendAttrib.cxx b/panda/src/pgraph/colorBlendAttrib.cxx index ef5d9349766..ce996ed81dd 100644 --- a/panda/src/pgraph/colorBlendAttrib.cxx +++ b/panda/src/pgraph/colorBlendAttrib.cxx @@ -39,19 +39,38 @@ make_off() { CPT(RenderAttrib) ColorBlendAttrib:: make(ColorBlendAttrib::Mode mode) { ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, O_one, O_one, + mode, O_one, O_one, LColor::zero()); return return_new(attrib); } /** * Constructs a new ColorBlendAttrib object that enables special-effect - * blending. This supercedes transparency. + * blending. This supercedes transparency. The given mode and operands are + * used for both the RGB and alpha channels. */ CPT(RenderAttrib) ColorBlendAttrib:: make(ColorBlendAttrib::Mode mode, ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, const LColor &color) { - ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, color); + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, mode, a, b, color); + return return_new(attrib); +} + +/** + * Constructs a new ColorBlendAttrib object that enables special-effect + * blending. This supercedes transparency. This form is used to specify + * separate blending parameters for the RGB and alpha channels. + */ +CPT(RenderAttrib) ColorBlendAttrib:: +make(ColorBlendAttrib::Mode mode, + ColorBlendAttrib::Operand a, ColorBlendAttrib::Operand b, + ColorBlendAttrib::Mode alpha_mode, + ColorBlendAttrib::Operand alpha_a, ColorBlendAttrib::Operand alpha_b, + const LColor &color) { + ColorBlendAttrib *attrib = new ColorBlendAttrib(mode, a, b, + alpha_mode, alpha_a, alpha_b, + color); return return_new(attrib); } @@ -187,10 +206,34 @@ fillin(DatagramIterator &scan, BamReader *manager) { _mode = (Mode)scan.get_uint8(); _a = (Operand)scan.get_uint8(); _b = (Operand)scan.get_uint8(); + + if (manager->get_file_minor_ver() >= 42) { + _alpha_mode = (Mode)scan.get_uint8(); + _alpha_a = (Operand)scan.get_uint8(); + _alpha_b = (Operand)scan.get_uint8(); + } else { + // Before bam 6.42, these were shifted by four. + if (_a >= O_incoming1_color) { + _a = (Operand)(_a + 4); + } + if (_b >= O_incoming1_color) { + _b = (Operand)(_b + 4); + } + + // And there was only one set of blend constants for both RGB and alpha. + _alpha_mode = _mode; + _alpha_a = _a; + _alpha_b = _b; + } + _color.read_datagram(scan); - _involves_constant_color = involves_constant_color(_a) || involves_constant_color(_b); - _involves_color_scale = involves_color_scale(_a) || involves_color_scale(_b); + _involves_constant_color = + involves_constant_color(_a) || involves_constant_color(_alpha_a) || + involves_constant_color(_b) || involves_constant_color(_alpha_b); + _involves_color_scale = + involves_color_scale(_a) || involves_color_scale(_alpha_a) || + involves_color_scale(_b) || involves_color_scale(_alpha_b); } /** @@ -234,7 +277,7 @@ operator << (ostream &out, ColorBlendAttrib::Operand operand) { return out << "one"; case ColorBlendAttrib::O_incoming_color: - return out << "incomfing_color"; + return out << "incoming_color"; case ColorBlendAttrib::O_one_minus_incoming_color: return out << "one_minus_incoming_color"; @@ -283,6 +326,18 @@ operator << (ostream &out, ColorBlendAttrib::Operand operand) { case ColorBlendAttrib::O_one_minus_alpha_scale: return out << "one_minus_alpha_scale"; + + case ColorBlendAttrib::O_incoming1_color: + return out << "incoming1_color"; + + case ColorBlendAttrib::O_one_minus_incoming1_color: + return out << "one_minus_incoming1_color"; + + case ColorBlendAttrib::O_incoming1_alpha: + return out << "incoming1_alpha"; + + case ColorBlendAttrib::O_one_minus_incoming1_alpha: + return out << "one_minus_incoming1_alpha"; } return out << "**invalid ColorBlendAttrib::Operand(" << (int)operand << ")**"; diff --git a/panda/src/pgraph/colorBlendAttrib.h b/panda/src/pgraph/colorBlendAttrib.h index 3e836fdb450..fdaefcc9426 100644 --- a/panda/src/pgraph/colorBlendAttrib.h +++ b/panda/src/pgraph/colorBlendAttrib.h @@ -52,11 +52,20 @@ class EXPCL_PANDA_PGRAPH ColorBlendAttrib : public RenderAttrib { O_one_minus_constant_alpha, O_incoming_color_saturate, // valid only for operand a - // If you set either of the operands to any of the below, the blend color - // is taken from the current ColorScaleAttrib. This also inhibits the - // normal behavior of the ColorScaleAttrib; it no longer directly scales - // the vertex colors, on the assumption that you will instead take care of - // the scale here, in the blend mode. + // The following are used for dual-source blending, where the fragment + // shader outputs a second color that will be used for blending. + O_incoming1_color, + O_one_minus_incoming1_color, + O_incoming1_alpha, + O_one_minus_incoming1_alpha, + + // If you set any of the operands to any of the below, the blend color is + // taken from the current ColorScaleAttrib. This also inhibits the normal + // behavior of the ColorScaleAttrib; it no longer directly scales the + // vertex colors, on the assumption that you will instead take care of the + // scale here, in the blend mode. + // + // These modes are being considered for deprecation. O_color_scale, O_one_minus_color_scale, O_alpha_scale, @@ -66,6 +75,7 @@ class EXPCL_PANDA_PGRAPH ColorBlendAttrib : public RenderAttrib { private: INLINE ColorBlendAttrib(); INLINE ColorBlendAttrib(Mode mode, Operand a, Operand b, + Mode alpha_mode, Operand alpha_a, Operand alpha_b, const LColor &color); PUBLISHED: @@ -73,11 +83,19 @@ class EXPCL_PANDA_PGRAPH ColorBlendAttrib : public RenderAttrib { static CPT(RenderAttrib) make(Mode mode); static CPT(RenderAttrib) make(Mode mode, Operand a, Operand b, const LColor &color = LColor::zero()); + static CPT(RenderAttrib) make(Mode rgb_mode, Operand rgb_a, Operand rgb_b, + Mode alpha_mode, Operand alpha_a, Operand alpha_b, + const LColor &color = LColor::zero()); static CPT(RenderAttrib) make_default(); INLINE Mode get_mode() const; INLINE Operand get_operand_a() const; INLINE Operand get_operand_b() const; + + INLINE Mode get_alpha_mode() const; + INLINE Operand get_alpha_operand_a() const; + INLINE Operand get_alpha_operand_b() const; + INLINE LColor get_color() const; INLINE bool involves_constant_color() const; @@ -97,6 +115,8 @@ class EXPCL_PANDA_PGRAPH ColorBlendAttrib : public RenderAttrib { private: Mode _mode; Operand _a, _b; + Mode _alpha_mode; + Operand _alpha_a, _alpha_b; LColor _color; bool _involves_constant_color; bool _involves_color_scale; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index 42517511357..2755f0f25d5 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -32,7 +32,7 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 6 on 2006-02-11 to factor out PandaNode::CData. static const unsigned short _bam_first_minor_ver = 14; -static const unsigned short _bam_minor_ver = 41; +static const unsigned short _bam_minor_ver = 42; // Bumped to minor version 14 on 2007-12-19 to change default ColorAttrib. // Bumped to minor version 15 on 2008-04-09 to add TextureAttrib::_implicit_sort. // Bumped to minor version 16 on 2008-05-13 to add Texture::_quality_level. @@ -61,5 +61,6 @@ static const unsigned short _bam_minor_ver = 41; // Bumped to minor version 39 on 2016-01-09 to change lights and materials. // Bumped to minor version 40 on 2016-01-11 to make NodePaths writable. // Bumped to minor version 41 on 2016-03-02 to change LensNode, Lens, and Camera. +// Bumped to minor version 42 on 2016-04-08 to expand ColorBlendAttrib. #endif