From 846c2a9fccb850f7da93f7f76446842f9e00267b Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Tue, 6 May 2008 16:27:18 +0000 Subject: [PATCH] Enabled shader generator to suppress alphatest and alpha-write --- direct/src/filter/CommonFilters.py | 2 +- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 34 ++++++--- panda/src/glstuff/glGraphicsBuffer_src.cxx | 6 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 32 +++++--- panda/src/pgraph/shaderAttrib.I | 12 +++ panda/src/pgraph/shaderAttrib.cxx | 46 ++++++++++++ panda/src/pgraph/shaderAttrib.h | 13 ++++ panda/src/pgraph/shaderGenerator.cxx | 73 +++++++++++++++---- panda/src/pgraph/shaderGenerator.h | 7 +- 9 files changed, 182 insertions(+), 43 deletions(-) diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index 107d6809fe..72cfbb4ee6 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -187,7 +187,7 @@ class CommonFilters: if (configuration.has_key("Bloom")): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 - self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw) + self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 009e8d1106..a37f404cea 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3138,16 +3138,19 @@ do_issue_transform() { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian9:: do_issue_alpha_test() { - const AlphaTestAttrib *attrib = _target._alpha_test; - AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode(); - if (mode == AlphaTestAttrib::M_none) { + if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) { set_render_state(D3DRS_ALPHATESTENABLE, FALSE); - } else { - // AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC - set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode); - set_render_state(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f)); //d3d uses 0x0-0xFF, not a float - set_render_state(D3DRS_ALPHATESTENABLE, TRUE); + const AlphaTestAttrib *attrib = _target._alpha_test; + AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode(); + if (mode == AlphaTestAttrib::M_none) { + set_render_state(D3DRS_ALPHATESTENABLE, FALSE); + } else { + // AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC + set_render_state(D3DRS_ALPHAFUNC, (D3DCMPFUNC)mode); + set_render_state(D3DRS_ALPHAREF, (UINT) (attrib->get_reference_alpha()*255.0f)); //d3d uses 0x0-0xFF, not a float + set_render_state(D3DRS_ALPHATESTENABLE, TRUE); + } } } @@ -3453,7 +3456,9 @@ set_state_and_transform(const RenderState *target, _target._shader = _target_rs->get_generated_shader(); } - if (_target._alpha_test != _state._alpha_test) { + if ((_target._alpha_test != _state._alpha_test)|| + (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) != + _state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) { do_issue_alpha_test(); _state._alpha_test = _target._alpha_test; } @@ -3521,7 +3526,9 @@ set_state_and_transform(const RenderState *target, if ((_target._transparency != _state._transparency)|| (_target._color_write != _state._color_write)|| - (_target._color_blend != _state._color_blend)) { + (_target._color_blend != _state._color_blend)|| + (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != + _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) { do_issue_blending(); _state._transparency = _target._transparency; _state._color_write = _target._color_write; @@ -4085,6 +4092,9 @@ do_issue_blending() { // to effectively disable color write. unsigned int color_channels = _target._color_write->get_channels() & _color_write_mask; + if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) { + color_channels &= ~(ColorWriteAttrib::C_alpha); + } if (color_channels == ColorWriteAttrib::C_off) { if (_target._color_write != _state._color_write) { if (_screen->_can_direct_disable_color_writes) { @@ -4098,7 +4108,9 @@ do_issue_blending() { } return; } else { - if (_target._color_write != _state._color_write) { + if ((_target._color_write != _state._color_write)|| + (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != + _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) { if (_screen->_can_direct_disable_color_writes) { set_render_state(D3DRS_COLORWRITEENABLE, color_channels); } diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index ed2eb564ba..279ae62e55 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -272,7 +272,7 @@ rebuild_bitplanes() { int next = GL_COLOR_ATTACHMENT1_EXT; for (int i=0; i<_fb_properties.get_aux_rgba(); i++) { bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next); - next += 1; + next += 1; } for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) { bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), next); @@ -339,7 +339,7 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta } } } else { -// tex->set_format(Texture::F_rgba); + tex->set_format(Texture::F_rgba); TextureContext *tc = tex->prepare_now(glgsg->get_prepared_objects(), glgsg); nassertv(tc != (TextureContext *)NULL); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); @@ -412,7 +412,7 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta GL_RENDERBUFFER_EXT, rb); } } else { - glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA, + glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA8_EXT, _rb_size_x, _rb_size_y); glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint, diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index d57f9fe117..1d80f94123 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -3937,14 +3937,18 @@ do_issue_depth_test() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_alpha_test() { - const AlphaTestAttrib *attrib = _target._alpha_test; - AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode(); - if (mode == AlphaTestAttrib::M_none) { + if (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test)) { enable_alpha_test(false); } else { - assert(GL_NEVER==(AlphaTestAttrib::M_never-1+0x200)); - GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), attrib->get_reference_alpha()); - enable_alpha_test(true); + const AlphaTestAttrib *attrib = _target._alpha_test; + AlphaTestAttrib::PandaCompareFunc mode = attrib->get_mode(); + if (mode == AlphaTestAttrib::M_none) { + enable_alpha_test(false); + } else { + assert(GL_NEVER==(AlphaTestAttrib::M_never-1+0x200)); + GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), attrib->get_reference_alpha()); + enable_alpha_test(true); + } } } @@ -4122,6 +4126,9 @@ do_issue_blending() { // to effectively disable color write. unsigned int color_channels = _target._color_write->get_channels() & _color_write_mask; + if (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write)) { + color_channels &= ~(ColorWriteAttrib::C_alpha); + } if (color_channels == ColorWriteAttrib::C_off) { if (_target._color_write != _state._color_write) { enable_multisample_alpha_one(false); @@ -4137,7 +4144,9 @@ do_issue_blending() { } return; } else { - if (_target._color_write != _state._color_write) { + if ((_target._color_write != _state._color_write)|| + (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != + _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) { if (CLP(color_mask)) { GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0, (color_channels & ColorWriteAttrib::C_green) != 0, @@ -4147,6 +4156,7 @@ do_issue_blending() { } } + CPT(ColorBlendAttrib) color_blend = _target._color_blend; ColorBlendAttrib::Mode color_blend_mode = _target._color_blend->get_mode(); TransparencyAttrib::Mode transparency_mode = _target._transparency->get_mode(); @@ -6064,7 +6074,9 @@ set_state_and_transform(const RenderState *target, _target._shader = _target_rs->get_generated_shader(); } - if (_target._alpha_test != _state._alpha_test) { + if ((_target._alpha_test != _state._alpha_test)|| + (_target._shader->get_flag(ShaderAttrib::F_subsume_alpha_test) != + _state._shader->get_flag(ShaderAttrib::F_subsume_alpha_test))) { PStatTimer timer(_draw_set_state_alpha_test_pcollector); do_issue_alpha_test(); _state._alpha_test = _target._alpha_test; @@ -6138,7 +6150,9 @@ set_state_and_transform(const RenderState *target, if ((_target._transparency != _state._transparency)|| (_target._color_write != _state._color_write)|| - (_target._color_blend != _state._color_blend)) { + (_target._color_blend != _state._color_blend)|| + (_target._shader->get_flag(ShaderAttrib::F_disable_alpha_write) != + _state._shader->get_flag(ShaderAttrib::F_disable_alpha_write))) { PStatTimer timer(_draw_set_state_blending_pcollector); do_issue_blending(); _state._transparency = _target._transparency; diff --git a/panda/src/pgraph/shaderAttrib.I b/panda/src/pgraph/shaderAttrib.I index 7d23783fb8..0bb88f99f0 100755 --- a/panda/src/pgraph/shaderAttrib.I +++ b/panda/src/pgraph/shaderAttrib.I @@ -42,6 +42,8 @@ ShaderAttrib(const ShaderAttrib ©) : _shader_priority(copy._shader_priority), _auto_shader(copy._auto_shader), _has_shader(copy._has_shader), + _flags(_flags), + _has_flags(_has_flags), _inputs(copy._inputs) { } @@ -79,3 +81,13 @@ get_shader_priority() const { return _shader_priority; } +//////////////////////////////////////////////////////////////////// +// Function: ShaderAttrib::get_flag +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool ShaderAttrib:: +get_flag(int index) const { + return (_flags & (1<_shader_priority = 0; attrib->_auto_shader = false; attrib->_has_shader = true; + attrib->_flags = 0; + attrib->_has_flags = 0; _off_attrib = return_new(attrib); } return _off_attrib; @@ -64,6 +66,8 @@ make() { attrib->_shader_priority = 0; attrib->_auto_shader = false; attrib->_has_shader = false; + attrib->_flags = 0; + attrib->_has_flags = 0; _null_attrib = return_new(attrib); } return _null_attrib; @@ -129,6 +133,38 @@ clear_shader() const { return return_new(result); } +//////////////////////////////////////////////////////////////////// +// Function: ShaderAttrib::set_flag +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ShaderAttrib:: +set_flag(int flag, bool value) const { + ShaderAttrib *result = new ShaderAttrib(*this); + int bit = 1<_flags |= bit; + } else { + result->_flags &= ~bit; + } + result->_has_flags |= bit; + return return_new(result); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderAttrib::clear_flag +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ShaderAttrib:: +clear_flag(int flag) const { + ShaderAttrib *result = new ShaderAttrib(*this); + int bit = 1<_flags &= ~bit; + result->_has_flags &= ~bit; + return return_new(result); +} + //////////////////////////////////////////////////////////////////// // Function: ShaderAttrib::set_shader_input // Access: Published @@ -432,6 +468,12 @@ compare_to_impl(const RenderAttrib *other) const { if (this->_has_shader != that->_has_shader) { return (this->_has_shader < that->_has_shader) ? -1 : 1; } + if (this->_flags != that->_flags) { + return (this->_flags < that->_flags) ? -1 : 1; + } + if (this->_has_flags != that->_has_flags) { + return (this->_has_flags < that->_has_flags) ? -1 : 1; + } Inputs::const_iterator i1 = this->_inputs.begin(); Inputs::const_iterator i2 = that->_inputs.begin(); @@ -487,6 +529,10 @@ compose_impl(const RenderAttrib *other) const { } } } + // Update the flags. + attr->_flags &= ~(over->_has_flags); + attr->_flags |= over->_flags; + attr->_has_flags |= (over->_has_flags); return return_new(attr); } diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index fab7fe8e72..b50822a899 100755 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -40,6 +40,11 @@ PUBLISHED: static CPT(RenderAttrib) make(); static CPT(RenderAttrib) make_off(); + enum { + F_disable_alpha_write = 0, // Suppress writes to color buffer alpha channel. + F_subsume_alpha_test = 1, // Shader promises to subsume the alpha test using TEXKILL + }; + INLINE bool has_shader() const; INLINE bool auto_shader() const; INLINE int get_shader_priority() const; @@ -59,9 +64,15 @@ PUBLISHED: CPT(RenderAttrib) set_shader_input(const string &id, const LVector4f &v, int priority=0) const; CPT(RenderAttrib) set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, double n4=1, int priority=0) const; + + CPT(RenderAttrib) set_flag(int flag, bool value) const; + CPT(RenderAttrib) clear_flag(int flag) const; + CPT(RenderAttrib) clear_shader_input(InternalName *id) const; CPT(RenderAttrib) clear_shader_input(const string &id) const; + INLINE bool get_flag(int flag) const; + const Shader *get_shader() const; const ShaderInput *get_shader_input(InternalName *id) const; const ShaderInput *get_shader_input(const string &id) const; @@ -86,6 +97,8 @@ private: int _shader_priority; bool _auto_shader; bool _has_shader; + int _flags; + int _has_flags; typedef pmap < CPT(InternalName), CPT(ShaderInput) > Inputs; Inputs _inputs; diff --git a/panda/src/pgraph/shaderGenerator.cxx b/panda/src/pgraph/shaderGenerator.cxx index f56fb83f9d..526b123c59 100644 --- a/panda/src/pgraph/shaderGenerator.cxx +++ b/panda/src/pgraph/shaderGenerator.cxx @@ -147,32 +147,46 @@ analyze_renderstate(const RenderState *rs) { // verify_enforce_attrib_lock(); rs->store_into_slots(&_attribs); + int outputs = _attribs._aux_bitplane->get_outputs(); - // Check if there's an alpha test, color blend, or transparency. - + // Decide whether or not we need alpha testing or alpha blending. + if ((_attribs._alpha_test->get_mode() != RenderAttrib::M_none)&& (_attribs._alpha_test->get_mode() != RenderAttrib::M_always)) { _have_alpha_test = true; } if (_attribs._color_blend->get_mode() != ColorBlendAttrib::M_none) { - _have_color_blend = true; + _have_alpha_blend = true; } - if (_attribs._transparency->get_mode() != TransparencyAttrib::M_none) { - _have_transparency = true; + if ((_attribs._transparency->get_mode() == TransparencyAttrib::M_alpha)|| + (_attribs._transparency->get_mode() == TransparencyAttrib::M_dual)) { + _have_alpha_blend = true; } - // Determine what output values are desired. + // Decide what to send to the framebuffer alpha, if anything. - int outputs = _attribs._aux_bitplane->get_outputs(); - if (_have_alpha_test || _have_color_blend || _have_transparency) { - _out_primary_alpha = true; + if (outputs & AuxBitplaneAttrib::ABO_glow) { + if (_have_alpha_blend) { + _calc_primary_alpha = true; + _out_primary_glow = false; + _disable_alpha_write = true; + } else if (_have_alpha_test) { + _calc_primary_alpha = true; + _out_primary_glow = true; + _subsume_alpha_test = true; + } } else { - _out_primary_glow = (outputs & AuxBitplaneAttrib::ABO_glow) ? true:false; + if (_have_alpha_blend || _have_alpha_test) { + _calc_primary_alpha = true; + } } + + // Determine what to put into the aux bitplane. + _out_aux_normal = (outputs & AuxBitplaneAttrib::ABO_aux_normal) ? true:false; _out_aux_glow = (outputs & AuxBitplaneAttrib::ABO_aux_glow) ? true:false; _out_aux_any = (_out_aux_normal || _out_aux_glow); - + // Count number of textures. _num_textures = 0; @@ -360,10 +374,11 @@ clear_analysis() { _map_index_height = -1; _map_index_glow = -1; _map_index_gloss = -1; + _calc_primary_alpha = false; _have_alpha_test = false; - _have_color_blend = false; - _have_transparency = false; - _out_primary_alpha = false; + _have_alpha_blend = false; + _subsume_alpha_test = false; + _disable_alpha_write = false; _out_primary_glow = false; _out_aux_normal = false; _out_aux_glow = false; @@ -795,7 +810,7 @@ synthesize_shader(const RenderState *rs) { // Combine in alpha, which bypasses lighting calculations. // Use of lerp here is a workaround for a radeon driver bug. - if (_out_primary_alpha) { + if (_calc_primary_alpha) { if (_vertex_colors) { text << "\t result.a = l_color.a;\n"; } else if (_flat_colors) { @@ -833,7 +848,7 @@ synthesize_shader(const RenderState *rs) { break; case TextureStage::M_add: text << "\t result.rbg = result.rgb + tex" << i << ".rgb;\n"; - if (_out_primary_alpha) { + if (_calc_primary_alpha) { text << "\t result.a = result.a * tex" << i << ".a;\n"; } break; @@ -848,6 +863,20 @@ synthesize_shader(const RenderState *rs) { } } + if (_subsume_alpha_test) { + text << "\t // Shader includes alpha test:\n"; + double ref = _attribs._alpha_test->get_reference_alpha(); + switch (_attribs._alpha_test->get_mode()) { + case RenderAttrib::M_never: text<<"\t discard;\n"; + case RenderAttrib::M_less: text<<"\t if (result.a >= "< "<= 0) { text << "\t result.a = tex" << _map_index_glow << ".a;\n"; @@ -891,10 +920,22 @@ synthesize_shader(const RenderState *rs) { // The multiply is a workaround for a radeon driver bug. // It's annoying as heck, since it produces an extra instruction. text << "\t o_color = result * 1.000001;\n"; + if (_subsume_alpha_test) { + text << "\t // Shader subsumes normal alpha test.\n"; + } + if (_disable_alpha_write) { + text << "\t // Shader disables alpha write.\n"; + } text << "}\n"; // Insert the shader into the shader attrib. CPT(RenderAttrib) shattr = create_shader_attrib(text.str()); + if (_subsume_alpha_test) { + shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test, true); + } + if (_disable_alpha_write) { + shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write, true); + } clear_analysis(); reset_register_allocator(); return shattr; diff --git a/panda/src/pgraph/shaderGenerator.h b/panda/src/pgraph/shaderGenerator.h index 4b7221e943..60b0716dbf 100644 --- a/panda/src/pgraph/shaderGenerator.h +++ b/panda/src/pgraph/shaderGenerator.h @@ -118,15 +118,16 @@ protected: int _map_index_glow; int _map_index_gloss; - bool _out_primary_alpha; bool _out_primary_glow; bool _out_aux_normal; bool _out_aux_glow; bool _out_aux_any; bool _have_alpha_test; - bool _have_color_blend; - bool _have_transparency; + bool _have_alpha_blend; + bool _calc_primary_alpha; + bool _subsume_alpha_test; + bool _disable_alpha_write; bool _need_clipspace_pos; bool _need_material_props;