Browse Source

Improvements to shader generation

Josh Yelon 18 years ago
parent
commit
a9dc480500

+ 20 - 19
direct/src/filter/CommonFilters.py

@@ -19,23 +19,23 @@ from FilterManager import FilterManager
 from pandac.PandaModules import Point3, Vec3, Vec4
 from pandac.PandaModules import NodePath, PandaNode
 from pandac.PandaModules import Filename
+from pandac.PandaModules import AuxBitplaneAttrib
 from pandac.PandaModules import RenderState, Texture, Shader
 import sys,os
 
 CARTOON_BODY="""
-float4 cartoondelta = k_cartoonseparation * texpix_txnormal.xwyw;
+float4 cartoondelta = k_cartoonseparation * texpix_txaux.xwyw;
 float4 cartoon_p0 = l_texcoordN + cartoondelta.xyzw;
-float4 cartoon_c0 = tex2D(k_txnormal, cartoon_p0.xy);
+float4 cartoon_c0 = tex2D(k_txaux, cartoon_p0.xy);
 float4 cartoon_p1 = l_texcoordN - cartoondelta.xyzw;
-float4 cartoon_c1 = tex2D(k_txnormal, cartoon_p1.xy);
+float4 cartoon_c1 = tex2D(k_txaux, cartoon_p1.xy);
 float4 cartoon_p2 = l_texcoordN + cartoondelta.wzyx;
-float4 cartoon_c2 = tex2D(k_txnormal, cartoon_p2.xy);
+float4 cartoon_c2 = tex2D(k_txaux, cartoon_p2.xy);
 float4 cartoon_p3 = l_texcoordN - cartoondelta.wzyx;
-float4 cartoon_c3 = tex2D(k_txnormal, cartoon_p3.xy);
+float4 cartoon_c3 = tex2D(k_txaux, cartoon_p3.xy);
 float4 cartoon_mx = max(cartoon_c0,max(cartoon_c1,max(cartoon_c2,cartoon_c3)));
 float4 cartoon_mn = min(cartoon_c0,min(cartoon_c1,min(cartoon_c2,cartoon_c3)));
-float4 cartoon_trigger = saturate(((cartoon_mx-cartoon_mn) * 3) - k_cartooncutoff.x);
-float  cartoon_thresh = dot(cartoon_trigger.xyz,float3(1,1,1));
+float cartoon_thresh = saturate(dot(cartoon_mx - cartoon_mn, float4(3,3,0,0)) - 0.5);
 o_color = lerp(o_color, float4(0,0,0,1), cartoon_thresh);
 """
 
@@ -76,20 +76,23 @@ class CommonFilters:
             if (len(configuration) == 0):
                 return
 
+            auxbits = 0
             needtex = {}
             needtex["color"] = True
             if (configuration.has_key("CartoonInk")):
-                needtex["normal"] = True
+                needtex["aux"] = True
+                auxbits |= AuxBitplaneAttrib.ABOAuxNormal
             if (configuration.has_key("Bloom")):
                 needtex["bloom0"] = True
                 needtex["bloom1"] = True
                 needtex["bloom2"] = True
                 needtex["bloom3"] = True
+                auxbits |= AuxBitplaneAttrib.ABOGlow
             for tex in needtex:
                 self.textures[tex] = Texture("scene-"+tex)
                 needtexpix = True
 
-            self.finalQuad = self.manager.renderSceneInto(textures = self.textures)
+            self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits)
     
             if (configuration.has_key("Bloom")):
                 bloomconf = configuration["Bloom"]
@@ -126,8 +129,8 @@ class CommonFilters:
             text += " uniform float4 texpix_txcolor,\n"
             text += " out float4 l_texcoordC : TEXCOORD0,\n"
             if (configuration.has_key("CartoonInk")):
-                text += " uniform float4 texpad_txnormal,\n"
-                text += " uniform float4 texpix_txnormal,\n"
+                text += " uniform float4 texpad_txaux,\n"
+                text += " uniform float4 texpix_txaux,\n"
                 text += " out float4 l_texcoordN : TEXCOORD1,\n"
             if (configuration.has_key("Bloom")):
                 text += " uniform float4 texpad_txbloom3,\n"
@@ -137,13 +140,13 @@ class CommonFilters:
             text += " l_position=mul(mat_modelproj, vtx_position);\n"
             text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n"
             if (configuration.has_key("CartoonInk")):
-                text += " l_texcoordN=(vtx_position.xzxz * texpad_txnormal) + texpad_txnormal;\n"
+                text += " l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n"
             if (configuration.has_key("Bloom")):
                 text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n"
             if (configuration.has_key("HalfPixelShift")):
                 text += " l_texcoordC+=texpix_txcolor*0.5;\n"
                 if (configuration.has_key("CartoonInk")):
-                    text += " l_texcoordN+=texpix_txnormal*0.5;\n"
+                    text += " l_texcoordN+=texpix_txaux*0.5;\n"
             text += "}\n"
 
             text += "void fshader(\n"
@@ -151,14 +154,13 @@ class CommonFilters:
             text += "uniform float4 texpix_txcolor,\n"
             if (configuration.has_key("CartoonInk")):
                 text += "float4 l_texcoordN : TEXCOORD1,\n"
-                text += "uniform float4 texpix_txnormal,\n"
+                text += "uniform float4 texpix_txaux,\n"
             if (configuration.has_key("Bloom")):
                 text += "float4 l_texcoordB : TEXCOORD2,\n"
             for key in self.textures:
                 text += "uniform sampler2D k_tx" + key + ",\n"
             if (configuration.has_key("CartoonInk")):
                 text += "uniform float4 k_cartoonseparation,\n"
-                text += "uniform float4 k_cartooncutoff,\n"
             text += "out float4 o_color : COLOR)\n"
             text += "{\n"
             text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n"
@@ -177,9 +179,8 @@ class CommonFilters:
 
         if (changed == "CartoonInk") or fullrebuild:
             if (configuration.has_key("CartoonInk")):
-                (separation, cutoff) = configuration["CartoonInk"]
+                separation = configuration["CartoonInk"]
                 self.finalQuad.setShaderInput("cartoonseparation", Vec4(separation,0,separation,0))
-                self.finalQuad.setShaderInput("cartooncutoff", Vec4(cutoff,cutoff,cutoff,cutoff))
 
         if (changed == "Bloom") or fullrebuild:
             if (configuration.has_key("Bloom")):
@@ -190,9 +191,9 @@ class CommonFilters:
                 self.bloom[0].setShaderInput("desat", bloomconf.desat)
                 self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity)
 
-    def setCartoonInk(self, separation=1, cutoff=0.3):
+    def setCartoonInk(self, separation=1):
         fullrebuild = (self.configuration.has_key("CartoonInk") == False)
-        self.configuration["CartoonInk"] = (separation, cutoff)
+        self.configuration["CartoonInk"] = separation
         self.reconfigure(fullrebuild, "CartoonInk")
 
     def delCartoonInk(self):

+ 7 - 10
direct/src/filter/FilterManager.py

@@ -119,7 +119,7 @@ class FilterManager:
 
         return winx,winy
 
-    def renderSceneInto(self, depthtex=False, colortex=False, normaltex=False, textures=None):
+    def renderSceneInto(self, depthtex=False, colortex=False, auxtex=False, auxbits=0, textures=None):
 
         """ Causes the scene to be rendered into the supplied textures
         instead of into the original window.  Puts a fullscreen quad
@@ -163,11 +163,11 @@ class FilterManager:
         if (textures):
             colortex = textures.get("color", None)
             depthtex = textures.get("depth", None)
-            normaltex = textures.get("normal", None)
+            auxtex = textures.get("aux", None)
 
         if (colortex == None): colortex = Texture("filter-base-color")
 
-        texgroup = (depthtex, colortex, normaltex, None)
+        texgroup = (depthtex, colortex, auxtex, None)
 
         # Choose the size of the offscreen buffer.
 
@@ -186,14 +186,11 @@ class FilterManager:
         quad.setTexture(colortex)
         quad.setColor(Vec4(1,0.5,0.5,1))
 
-        auxbits = AuxBitplaneAttrib.ABOColor;
-        if (normaltex != None):
-            auxbits += AuxBitplaneAttrib.ABOCsnormal;
-        
         cs = NodePath("dummy")
         cs.setState(self.caminit)
         cs.setShaderAuto();
-        cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
+        if (auxbits):
+            cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
         self.camera.node().setInitialState(cs.getState())
 
         quadcamnode = Camera("filter-quad-cam")
@@ -208,9 +205,9 @@ class FilterManager:
 
         dr = buffer.getDisplayRegion(0)
         self.setStackedClears(dr, self.rclears, self.wclears)
-        if (normaltex):
+        if (auxtex):
             dr.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
-            dr.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.0,0.0,0.0,0.0))
+            dr.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5,0.5,1.0,0.0))
         self.region.disableClears()
         if (self.isFullscreen()):
             self.win.disableClears()

+ 2 - 2
panda/src/pgraph/auxBitplaneAttrib.cxx

@@ -36,7 +36,7 @@ CPT(RenderAttrib) AuxBitplaneAttrib::_default;
 CPT(RenderAttrib) AuxBitplaneAttrib::
 make() {
   if (_default == 0) {
-    AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(ABO_color);
+    AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(0);
     _default = return_new(attrib);
   }
   return _default;
@@ -102,7 +102,7 @@ compare_to_impl(const RenderAttrib *other) const {
 ////////////////////////////////////////////////////////////////////
 RenderAttrib *AuxBitplaneAttrib::
 make_default_impl() const {
-  return new AuxBitplaneAttrib(ABO_color);
+  return new AuxBitplaneAttrib(0);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 29 - 5
panda/src/pgraph/auxBitplaneAttrib.h

@@ -29,8 +29,30 @@ class FactoryParams;
 // Description : Modern frame buffers can have 'aux' bitplanes, which
 //               are additional bitplanes above and beyond the
 //               standard depth and color.  This attrib controls what
-//               gets rendered into those additional bitplanes when
-//               using the standard shader generator.
+//               gets rendered into those additional bitplanes.  It
+//               can also affect what goes into the alpha channel
+//               of the primary color buffer.
+//
+//               ABO_glow: copy the glow map into the alpha channel
+//               of the primary frame buffer.  If there is no glow
+//               map, set it to zero.  Caveat: it is not
+//               possible to write glow or depth values to the
+//               framebuffer alpha channel at the same time as using
+//               alpha blending or alpha testing.  Any attempt to use
+//               transparency, blending, or alpha testing will cause
+//               this flag to be overridden.
+//
+//               ABO_aux_normal: put the camera-space normal into
+//               the into the R,G components of the first auxiliary
+//               bitplane.
+//
+//               ABO_aux_modelz: put the clip-space Z coordinate of
+//               the center of the model (after perspective divide)
+//               into the B channel of the first auxiliary bitplane.
+//
+//               ABO_aux_glow: put a copy of the glow map into the
+//               alpha channel of the first auxiliary bitplane.
+//               If there is no glow map, set it to zero.
 //
 //               AuxBitplaneAttrib is relevant only when shader
 //               generation is enabled. Otherwise, it has no effect.
@@ -42,9 +64,11 @@ private:
 
 PUBLISHED:
   enum AuxBitplaneOutput {
-    ABO_color = 1,     // Render an ordinary scene into the ordinary color buffer.
-    ABO_csnormal = 2,  // Render a camera-space normal into an aux bitplane.
-    ABO_glowalpha = 4, // Render all glow maps into the color buffer alpha channel.
+    ABO_glow = 1,
+    
+    ABO_aux_normal = 2,
+    ABO_aux_modelz = 4,
+    ABO_aux_glow = 8,
   };
   static CPT(RenderAttrib) make();
   static CPT(RenderAttrib) make(int outputs);

+ 87 - 38
panda/src/pgraph/shaderGenerator.cxx

@@ -146,15 +146,30 @@ analyze_renderstate(const RenderState *rs) {
 
   rs->store_into_slots(&_attribs);
 
-  // Figure out which bitplane should hold which output.
-  
-  int next = 0;
-  if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_color) {
-    _bitplane_color = next++;
+  // Check if there's an alpha test, color blend, or transparency.
+
+  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;
+  }
+  if (_attribs._transparency->get_mode() != TransparencyAttrib::M_none) {
+    _have_transparency = true;
   }
-  if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_csnormal) {
-    _bitplane_normal = next++;
+  
+  // Determine what output values are desired.
+  
+  int outputs = _attribs._aux_bitplane->get_outputs();
+  if (_have_alpha_test || _have_color_blend || _have_transparency) {
+    _out_primary_alpha = true;
+  } else {
+    _out_primary_glow = (outputs & AuxBitplaneAttrib::ABO_glow) ? true:false;
   }
+  _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.
 
@@ -165,12 +180,10 @@ analyze_renderstate(const RenderState *rs) {
   
   // Determine whether or not vertex colors or flat colors are present.
 
-  if ((_bitplane_color >= 0)&&(_attribs._color != 0)) {
-    if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) {
-      _vertex_colors = true;
-    } else if (_attribs._color->get_color_type() == ColorAttrib::T_flat) {
-      _flat_colors = true;
-    }
+  if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) {
+    _vertex_colors = true;
+  } else if (_attribs._color->get_color_type() == ColorAttrib::T_flat) {
+    _flat_colors = true;
   }
 
   // Break out the lights by type.
@@ -221,8 +234,7 @@ analyze_renderstate(const RenderState *rs) {
   
   // Determine whether lighting is needed.
 
-  if ((_bitplane_color >= 0) &&
-      (_attribs._light->get_num_on_lights() > 0)) {
+  if (_attribs._light->get_num_on_lights() > 0) {
     _lighting = true;
   }
   
@@ -331,11 +343,18 @@ clear_analysis() {
   _map_index_height = -1;
   _map_index_glow = -1;
   _map_index_gloss = -1;
-  _bitplane_color = -1;
-  _bitplane_normal = -1;
+  _have_alpha_test = false;
+  _have_color_blend = false;
+  _have_transparency = false;
+  _out_primary_alpha = false;
+  _out_primary_glow  = false;
+  _out_aux_normal = false;
+  _out_aux_glow   = false;
+  _out_aux_any    = false;
   _attribs.clear_to_defaults();
   _material = (Material*)NULL;
   _need_material_props = false;
+  _need_clipspace_pos = false;
   _alights.clear();
   _dlights.clear();
   _plights.clear();
@@ -387,21 +406,20 @@ create_shader_attrib(const string &txt) {
 //               - lighting
 //               - normal maps
 //               - gloss maps
+//               - glow maps
 //               - materials, but not updates to materials
-//               - modulated 2D textures
+//               - 2D textures
 //               - texture stage modes: modulate, decal, add
 //               - light ramps (for cartoon shading)
 //
 //               Not yet supported:
-//               - 3D textures
-//               - cube textures
+//               - 3D textures, cube textures
 //               - texture stage modes: replace, blend
 //               - color scale attrib
 //               - texgen
 //               - texmatrix
-//               - glow maps (not yet sure what these should do)
+//               - fog
 //               - other TextureStage::Modes
-//               - cartoon thresholding and other special effects
 //
 //               Potential optimizations
 //               - omit attenuation calculations if attenuation off
@@ -422,6 +440,7 @@ synthesize_shader(const RenderState *rs) {
   char *binormal_vreg = 0;
   char *binormal_freg = 0;
   char *csnormal_freg = 0;
+  char *clip_freg = 0;
   pvector<char *> texcoord_vreg;
   pvector<char *> texcoord_freg;
   pvector<char *> tslightvec_freg;
@@ -466,7 +485,11 @@ synthesize_shader(const RenderState *rs) {
       text << "\t out float4 l_binormal : " << binormal_freg << ",\n";
     }
   }
-  if (_bitplane_normal >= 0) {
+  if (_need_clipspace_pos) {
+    clip_freg = alloc_freg();
+    text << "\t out float4 l_clip : " << clip_freg << ",\n";
+  }
+  if (_out_aux_normal) {
     if (normal_vreg == 0) {
       normal_vreg = alloc_vreg();
       text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
@@ -482,7 +505,9 @@ synthesize_shader(const RenderState *rs) {
   text << ") {\n";
   
   text << "\t l_position = mul(mat_modelproj, vtx_position);\n";
-
+  if (_need_clipspace_pos) {
+    text << "\t l_clip = l_position;\n";
+  }
   for (int i=0; i<_num_textures; i++) {
     text << "\t l_texcoord" << i << " = vtx_texcoord" << i << ";\n";
   }
@@ -497,7 +522,7 @@ synthesize_shader(const RenderState *rs) {
       text << "\t l_binormal = -vtx_binormal" << _map_index_normal << ";\n";
     }
   }
-  if (_bitplane_normal >= 0) {
+  if (_out_aux_normal) {
     text << "\t l_csnormal.xyz = mul(itp_modelview, vtx_normal);\n";
     text << "\t l_csnormal.w = 0;\n";
   }
@@ -542,13 +567,16 @@ synthesize_shader(const RenderState *rs) {
       }
     }
   }
-  if (_bitplane_normal >= 0) {
+  if (_out_aux_normal) {
     text << "\t in float4 l_csnormal : " << csnormal_freg << ",\n";
-    text << "\t out float4 o_csnormal : COLOR" << _bitplane_normal << ",\n";
   }
-  if (_bitplane_color >= 0) {
-    text << "\t out float4 o_color : COLOR" << _bitplane_color << ",\n";
+  if (_need_clipspace_pos) {
+    text << "\t in float4 l_clip : " << clip_freg << ",\n";
+  }
+  if (_out_aux_any) {
+    text << "\t out float4 o_aux : COLOR1,\n";
   }
+  text << "\t out float4 o_color : COLOR0,\n";
   if (_vertex_colors) {
     text << "\t in float4 l_color : COLOR\n";
   } else {
@@ -556,6 +584,9 @@ synthesize_shader(const RenderState *rs) {
   }
   text << ") {\n";
   text << "\t float4 result;\n";
+  if (_out_aux_any) {
+    text << "\t o_aux = float4(0,0,0,0);\n";
+  }
   text << "\t // Fetch all textures.\n";
   for (int i=0; i<_num_textures; i++) {
     text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n";
@@ -573,9 +604,9 @@ synthesize_shader(const RenderState *rs) {
       text << "\t l_normal = normalize(l_normal);\n";
     }
   }
-  if (_bitplane_normal >= 0) {
+  if (_out_aux_normal) {
     text << "\t // Output the camera-space surface normal\n";
-    text << "\t o_csnormal = (normalize(l_csnormal)*0.5) + float4(0.5,0.5,0.5,0);\n";
+    text << "\t o_aux.rg = ((normalize(l_csnormal)*0.5) + float4(0.5,0.5,0.5,0)).rg;\n";
   }
   if (_lighting) {
     text << "\t // Begin model-space light calculations\n";
@@ -747,7 +778,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 (_map_index_glow < 0) {
+    if (_out_primary_alpha) {
       if (_vertex_colors) {
         text << "\t result.a = l_color.a;\n";
       } else if (_flat_colors) {
@@ -785,7 +816,9 @@ synthesize_shader(const RenderState *rs) {
       break;
     case TextureStage::M_add:
       text << "\t result.rbg = result.rgb + tex" << i << ".rgb;\n";
-      text << "\t result.a   = result.a * tex" << i << ".a;\n";
+      if (_out_primary_alpha) {
+        text << "\t result.a   = result.a * tex" << i << ".a;\n";
+      }
       break;
     case TextureStage::M_combine:
       pgraph_cat.error() << "TextureStage::Mode COMBINE not yet supported in per-pixel mode.\n";
@@ -797,6 +830,22 @@ synthesize_shader(const RenderState *rs) {
       break;
     }
   }
+
+  if (_out_primary_glow) {
+    if (_map_index_glow >= 0) {
+      text << "\t result.a = tex" << _map_index_glow << ".a;\n";
+    } else {
+      text << "\t result.a = 0;\n";
+    }
+  }
+  if (_out_aux_glow) {
+    if (_map_index_glow >= 0) {
+      text << "\t o_aux.a = tex" << _map_index_glow << ".a;\n";
+    } else {
+      text << "\t o_aux.a = 0;\n";
+    }
+  }
+  
   if (_lighting) {
     if (_have_specular) {
       if (_material->has_specular()) {
@@ -808,6 +857,7 @@ synthesize_shader(const RenderState *rs) {
       text << "\t result.rgb = result.rgb + tot_specular.rgb;\n";
     }
   }
+  
   switch (_attribs._light_ramp->get_mode()) {
   case LightRampAttrib::LRT_hdr0:
     text << "\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
@@ -820,11 +870,10 @@ synthesize_shader(const RenderState *rs) {
     break;
   default: break;
   }
-  if (_bitplane_color >= 0) {
-    // 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"; 
-  }
+  
+  // 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"; 
   text << "}\n";
   
   // Insert the shader into the shader attrib.

+ 11 - 3
panda/src/pgraph/shaderGenerator.h

@@ -117,10 +117,18 @@ protected:
   int _map_index_height;
   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;
   
-  int _bitplane_color;
-  int _bitplane_normal;
-  
+  bool _need_clipspace_pos;
   bool _need_material_props;
   
   void analyze_renderstate(const RenderState *rs);