Преглед на файлове

Enabled shader generator to suppress alphatest and alpha-write

Josh Yelon преди 17 години
родител
ревизия
846c2a9fcc

+ 1 - 1
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)

+ 23 - 11
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);
       }

+ 3 - 3
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,

+ 23 - 9
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;

+ 12 - 0
panda/src/pgraph/shaderAttrib.I

@@ -42,6 +42,8 @@ ShaderAttrib(const ShaderAttrib &copy) :
   _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<<index)) ? true:false;
+}
+

+ 46 - 0
panda/src/pgraph/shaderAttrib.cxx

@@ -44,6 +44,8 @@ make_off() {
     attrib->_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<<flag;
+  if (value) {
+    result->_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<<flag;
+  result->_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);
 }
 

+ 13 - 0
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;
 

+ 57 - 16
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 >= "<<ref<<") discard;\n";
+    case RenderAttrib::M_equal:          text<<"\t if (result.a != "<<ref<<") discard;\n";
+    case RenderAttrib::M_less_equal:     text<<"\t if (result.a >  "<<ref<<") discard;\n";
+    case RenderAttrib::M_greater:        text<<"\t if (result.a <= "<<ref<<") discard;\n";
+    case RenderAttrib::M_not_equal:      text<<"\t if (result.a == "<<ref<<") discard;\n";
+    case RenderAttrib::M_greater_equal:  text<<"\t if (result.a <  "<<ref<<") discard;\n";
+    }
+  }
+  
   if (_out_primary_glow) {
     if (_map_index_glow >= 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;

+ 4 - 3
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;