2
0
David Rose 17 жил өмнө
parent
commit
76f94669d0

+ 15 - 8
panda/src/tinydisplay/clip.cxx

@@ -33,9 +33,15 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v)
                 + ZB_POINT_ALPHA_MIN);
                 + ZB_POINT_ALPHA_MIN);
   
   
   /* texture */
   /* texture */
-  if (c->texture_2d_enabled) {
-    v->zp.s = (int)(v->tex_coord.v[0] * c->current_texture->s_max); 
-    v->zp.t = (int)(v->tex_coord.v[1] * c->current_texture->t_max);
+  if (c->num_textures_enabled >= 1) {
+    static const int si = 0;
+    v->zp.s = (int)(v->tex_coord[si].v[0] * c->current_textures[si]->s_max); 
+    v->zp.t = (int)(v->tex_coord[si].v[1] * c->current_textures[si]->t_max);
+  }
+  if (c->num_textures_enabled >= 2) {
+    static const int si = 1;
+    v->zp.sa = (int)(v->tex_coord[si].v[0] * c->current_textures[si]->s_max); 
+    v->zp.ta = (int)(v->tex_coord[si].v[1] * c->current_textures[si]->t_max);
   }
   }
 }
 }
 
 
@@ -201,14 +207,15 @@ static inline void updateTmp(GLContext *c,
     q->color.v[3]=p0->color.v[3];
     q->color.v[3]=p0->color.v[3];
   }
   }
 
 
-  if (c->texture_2d_enabled) {
-    q->tex_coord.v[0]=p0->tex_coord.v[0] + (p1->tex_coord.v[0]-p0->tex_coord.v[0])*t;
-    q->tex_coord.v[1]=p0->tex_coord.v[1] + (p1->tex_coord.v[1]-p0->tex_coord.v[1])*t;
+  for (int si = 0; si < c->num_textures_enabled; ++si) {
+    q->tex_coord[si].v[0]=p0->tex_coord[si].v[0] + (p1->tex_coord[si].v[0]-p0->tex_coord[si].v[0])*t;
+    q->tex_coord[si].v[1]=p0->tex_coord[si].v[1] + (p1->tex_coord[si].v[1]-p0->tex_coord[si].v[1])*t;
   }
   }
 
 
   q->clip_code=gl_clipcode(q->pc.v[0],q->pc.v[1],q->pc.v[2],q->pc.v[3]);
   q->clip_code=gl_clipcode(q->pc.v[0],q->pc.v[1],q->pc.v[2],q->pc.v[3]);
-  if (q->clip_code==0)
+  if (q->clip_code==0) {
     gl_transform_to_viewport(c,q);
     gl_transform_to_viewport(c,q);
+  }
 }
 }
 
 
 static void gl_draw_triangle_clip(GLContext *c,
 static void gl_draw_triangle_clip(GLContext *c,
@@ -368,7 +375,7 @@ void gl_draw_triangle_fill(GLContext *c,
 #endif
 #endif
     
     
 #ifdef PROFILE
 #ifdef PROFILE
-  if (c->texture_2d_enabled) {
+  if (c->num_textures_enabled != 0) {
     count_triangles_textured++;
     count_triangles_textured++;
   }
   }
 #endif
 #endif

+ 0 - 5
panda/src/tinydisplay/init.cxx

@@ -47,11 +47,6 @@ void glInit(GLContext *c, ZBuffer *zbuffer)
   c->current_normal.v[2]=0.0f;
   c->current_normal.v[2]=0.0f;
   c->current_normal.v[3]=0.0f;
   c->current_normal.v[3]=0.0f;
 
 
-  c->current_tex_coord.v[0]=0.0f;
-  c->current_tex_coord.v[1]=0.0f;
-  c->current_tex_coord.v[2]=0.0f;
-  c->current_tex_coord.v[3]=1.0f;
-
   c->cull_face_enabled=0;
   c->cull_face_enabled=0;
   
   
   /* specular buffer */
   /* specular buffer */

+ 79 - 52
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -51,6 +51,9 @@ PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_textured_pcollecto
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_perspective_pcollector("Pixels:White perspective");
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_perspective_pcollector("Pixels:White perspective");
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_perspective_pcollector("Pixels:Flat perspective");
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_perspective_pcollector("Pixels:Flat perspective");
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcollector("Pixels:Smooth perspective");
 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcollector("Pixels:Smooth perspective");
+PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_multitex_pcollector("Pixels:White multitex");
+PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_multitex_pcollector("Pixels:Flat multitex");
+PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex_pcollector("Pixels:Smooth multitex");
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::Constructor
 //     Function: TinyGraphicsStateGuardian::Constructor
@@ -120,6 +123,7 @@ reset() {
     Geom::GR_flat_last_vertex;
     Geom::GR_flat_last_vertex;
 
 
   _max_texture_dimension = (1 << ZB_POINT_ST_FRAC_BITS);
   _max_texture_dimension = (1 << ZB_POINT_ST_FRAC_BITS);
+  _max_texture_stages = MAX_TEXTURE_STAGES;
   _max_lights = MAX_LIGHTS;
   _max_lights = MAX_LIGHTS;
 
 
   _color_scale_via_lighting = false;
   _color_scale_via_lighting = false;
@@ -392,6 +396,9 @@ begin_frame(Thread *current_thread) {
   _pixel_count_white_perspective_pcollector.clear_level();
   _pixel_count_white_perspective_pcollector.clear_level();
   _pixel_count_flat_perspective_pcollector.clear_level();
   _pixel_count_flat_perspective_pcollector.clear_level();
   _pixel_count_smooth_perspective_pcollector.clear_level();
   _pixel_count_smooth_perspective_pcollector.clear_level();
+  _pixel_count_white_multitex_pcollector.clear_level();
+  _pixel_count_flat_multitex_pcollector.clear_level();
+  _pixel_count_smooth_multitex_pcollector.clear_level();
 #endif
 #endif
 
 
   return true;
   return true;
@@ -495,6 +502,9 @@ end_frame(Thread *current_thread) {
   _pixel_count_white_perspective_pcollector.flush_level();
   _pixel_count_white_perspective_pcollector.flush_level();
   _pixel_count_flat_perspective_pcollector.flush_level();
   _pixel_count_flat_perspective_pcollector.flush_level();
   _pixel_count_smooth_perspective_pcollector.flush_level();
   _pixel_count_smooth_perspective_pcollector.flush_level();
+  _pixel_count_white_multitex_pcollector.flush_level();
+  _pixel_count_flat_multitex_pcollector.flush_level();
+  _pixel_count_smooth_multitex_pcollector.flush_level();
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
 }
 }
 
 
@@ -604,27 +614,29 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     _vertices = (GLVertex *)PANDA_MALLOC_ARRAY(_vertices_size * sizeof(GLVertex));
     _vertices = (GLVertex *)PANDA_MALLOC_ARRAY(_vertices_size * sizeof(GLVertex));
   }
   }
 
 
-  GeomVertexReader rtexcoord, rcolor, rnormal;
+  GeomVertexReader  rcolor, rnormal;
 
 
-  // We only support single-texturing, so only bother with the first
-  // texture stage.
-  bool needs_texcoord = false;
-  bool needs_texmat = false;
-  LMatrix4f texmat;
-  const InternalName *texcoord_name = InternalName::get_texcoord();
+  // We now support up to 2-stage multitexturing.
+  GeomVertexReader rtexcoord[MAX_TEXTURE_STAGES];
+  bool needs_texcoord[MAX_TEXTURE_STAGES] = { false, false };
+  bool needs_texmat[MAX_TEXTURE_STAGES] = { false, false };
+  LMatrix4f texmat[MAX_TEXTURE_STAGES];
+  const InternalName *texcoord_name[MAX_TEXTURE_STAGES] = { 
+    InternalName::get_texcoord(), InternalName::get_texcoord()
+  };
   int max_stage_index = _target_texture->get_num_on_ff_stages();
   int max_stage_index = _target_texture->get_num_on_ff_stages();
-  if (max_stage_index > 0) {
-    TextureStage *stage = _target_texture->get_on_ff_stage(0);
-    rtexcoord = GeomVertexReader(data_reader, stage->get_texcoord_name(),
+  for (int si = 0; si < max_stage_index; ++si) {
+    TextureStage *stage = _target_texture->get_on_ff_stage(si);
+    rtexcoord[si] = GeomVertexReader(data_reader, stage->get_texcoord_name(),
                                  force);
                                  force);
-    rtexcoord.set_row(_min_vertex);
-    needs_texcoord = rtexcoord.has_column();
+    rtexcoord[si].set_row(_min_vertex);
+    needs_texcoord[si] = rtexcoord[si].has_column();
 
 
-    if (needs_texcoord) {
+    if (needs_texcoord[si]) {
       const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
       const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
       if (target_tex_matrix->has_stage(stage)) {
       if (target_tex_matrix->has_stage(stage)) {
-        needs_texmat = true;
-        texmat = target_tex_matrix->get_mat(stage);
+        needs_texmat[si] = true;
+        texmat[si] = target_tex_matrix->get_mat(stage);
       }
       }
     }
     }
   }
   }
@@ -689,17 +701,20 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     v->coord.v[2] = d[2];
     v->coord.v[2] = d[2];
     v->coord.v[3] = d[3];
     v->coord.v[3] = d[3];
 
 
-    if (needs_texmat) {
-      // Transform texcoords as a four-component vector for most generality.
-      LVecBase4f d = rtexcoord.get_data4f() * texmat;
-      v->tex_coord.v[0] = d[0];
-      v->tex_coord.v[1] = d[1];
-
-    } else if (needs_texcoord) {
-      // No need to transform, so just extract as two-component.
-      const LVecBase2f &d = rtexcoord.get_data2f();
-      v->tex_coord.v[0] = d[0];
-      v->tex_coord.v[1] = d[1];
+    // Texture coordinates.
+    for (int si = 0; si < max_stage_index; ++si) {
+      if (needs_texmat[si]) {
+        // Transform texcoords as a four-component vector for most generality.
+        LVecBase4f d = rtexcoord[si].get_data4f() * texmat[si];
+        v->tex_coord[si].v[0] = d[0];
+        v->tex_coord[si].v[1] = d[1];
+        
+      } else if (needs_texcoord[si]) {
+        // No need to transform, so just extract as two-component.
+        const LVecBase2f &d = rtexcoord[si].get_data2f();
+        v->tex_coord[si].v[0] = d[0];
+        v->tex_coord[si].v[1] = d[1];
+      }
     }
     }
 
 
     if (needs_color) {
     if (needs_color) {
@@ -846,8 +861,9 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
   int texfilter_state = 0;  // tnearest
   int texfilter_state = 0;  // tnearest
   if (texturing_state > 0) {
   if (texturing_state > 0) {
     texfilter_state = _texfilter_state;
     texfilter_state = _texfilter_state;
-    if (_c->matrix_model_projection_no_w_transform ||
-        _filled_flat) {
+
+    if (texturing_state < 3 &&
+        (_c->matrix_model_projection_no_w_transform || _filled_flat)) {
       // Don't bother with the perspective-correct algorithm if we're
       // Don't bother with the perspective-correct algorithm if we're
       // under an orthonormal lens, e.g. render2d; or if
       // under an orthonormal lens, e.g. render2d; or if
       // RenderMode::M_filled_flat is in effect.
       // RenderMode::M_filled_flat is in effect.
@@ -873,6 +889,9 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
   pixel_count_white_perspective = 0;
   pixel_count_white_perspective = 0;
   pixel_count_flat_perspective = 0;
   pixel_count_flat_perspective = 0;
   pixel_count_smooth_perspective = 0;
   pixel_count_smooth_perspective = 0;
+  pixel_count_white_multitex = 0;
+  pixel_count_flat_multitex = 0;
+  pixel_count_smooth_multitex = 0;
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
   
   
   return true;
   return true;
@@ -1268,6 +1287,9 @@ end_draw_primitives() {
   _pixel_count_white_perspective_pcollector.add_level(pixel_count_white_perspective);
   _pixel_count_white_perspective_pcollector.add_level(pixel_count_white_perspective);
   _pixel_count_flat_perspective_pcollector.add_level(pixel_count_flat_perspective);
   _pixel_count_flat_perspective_pcollector.add_level(pixel_count_flat_perspective);
   _pixel_count_smooth_perspective_pcollector.add_level(pixel_count_smooth_perspective);
   _pixel_count_smooth_perspective_pcollector.add_level(pixel_count_smooth_perspective);
+  _pixel_count_white_multitex_pcollector.add_level(pixel_count_white_multitex);
+  _pixel_count_flat_multitex_pcollector.add_level(pixel_count_flat_multitex);
+  _pixel_count_smooth_multitex_pcollector.add_level(pixel_count_smooth_multitex);
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
 
 
   GraphicsStateGuardian::end_draw_primitives();
   GraphicsStateGuardian::end_draw_primitives();
@@ -1537,7 +1559,7 @@ prepare_texture(Texture *tex) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::update_texture
 //     Function: TinyGraphicsStateGuardian::update_texture
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Ensures that the current Texture data is refreshed
 //  Description: Ensures that the current Texture data is refreshed
 //               onto the GSG.  This means updating the texture
 //               onto the GSG.  This means updating the texture
 //               properties and/or re-uploading the texture image, if
 //               properties and/or re-uploading the texture image, if
@@ -1552,7 +1574,7 @@ prepare_texture(Texture *tex) {
 //               true).
 //               true).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool TinyGraphicsStateGuardian::
 bool TinyGraphicsStateGuardian::
-update_texture(TextureContext *tc, bool force) {
+update_texture(TextureContext *tc, bool force, int stage_index) {
   apply_texture(tc);
   apply_texture(tc);
 
 
   TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
   TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
@@ -1570,8 +1592,8 @@ update_texture(TextureContext *tc, bool force) {
   }
   }
   gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
   gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
 
 
-  _c->current_texture = gltex;
-  _c->zb->current_texture = gltex->levels;
+  _c->current_textures[stage_index] = gltex;
+  _c->zb->current_textures[stage_index] = gltex->levels;
 
 
   return true;
   return true;
 }
 }
@@ -2026,35 +2048,44 @@ do_issue_material() {
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
 do_issue_texture() {
 do_issue_texture() {
   _texturing_state = 0;   // untextured
   _texturing_state = 0;   // untextured
-  _c->texture_2d_enabled = false;
+  _c->num_textures_enabled = 0;
 
 
   int num_stages = _target_texture->get_num_on_ff_stages();
   int num_stages = _target_texture->get_num_on_ff_stages();
   if (num_stages == 0) {
   if (num_stages == 0) {
     // No texturing.
     // No texturing.
     return;
     return;
   }
   }
-  nassertv(num_stages == 1);
+  nassertv(num_stages <= MAX_TEXTURE_STAGES);
 
 
-  TextureStage *stage = _target_texture->get_on_ff_stage(0);
-  Texture *texture = _target_texture->get_on_texture(stage);
-  nassertv(texture != (Texture *)NULL);
+  Texture *texture = NULL;
+  for (int si = 0; si < num_stages; ++si) {
+    TextureStage *stage = _target_texture->get_on_ff_stage(si);
+    texture = _target_texture->get_on_texture(stage);
+    nassertv(texture != (Texture *)NULL);
     
     
-  TextureContext *tc = texture->prepare_now(_prepared_objects, this);
-  if (tc == (TextureContext *)NULL) {
-    // Something wrong with this texture; skip it.
-    return;
-  }
+    TextureContext *tc = texture->prepare_now(_prepared_objects, this);
+    if (tc == (TextureContext *)NULL) {
+      // Something wrong with this texture; skip it.
+      return;
+    }
     
     
-  // Then, turn on the current texture mode.
-  if (!update_texture(tc, false)) {
-    return;
+    // Then, turn on the current texture mode.
+    if (!update_texture(tc, false, si)) {
+      return;
+    }
+
+    // M_replace means M_replace; anything else is treated the same as
+    // M_modulate.
+    _texture_replace = (stage->get_mode() == TextureStage::M_replace);
   }
   }
 
 
   // Set a few state cache values.
   // Set a few state cache values.
-  _c->texture_2d_enabled = true;
+  _c->num_textures_enabled = num_stages;
 
 
   _texturing_state = 2;   // perspective (perspective-correct texturing)
   _texturing_state = 2;   // perspective (perspective-correct texturing)
-  if (!td_perspective_textures) {
+  if (num_stages >= 2) {
+    _texturing_state = 3;  // multitexture
+  } else if (!td_perspective_textures) {
     _texturing_state = 1;    // textured (not perspective correct)
     _texturing_state = 1;    // textured (not perspective correct)
   }
   }
 
 
@@ -2086,7 +2117,7 @@ do_issue_texture() {
     // This is the cheapest texture filter.  We disallow mipmaps and
     // This is the cheapest texture filter.  We disallow mipmaps and
     // perspective correctness.
     // perspective correctness.
     _texfilter_state = 0;    // tnearest
     _texfilter_state = 0;    // tnearest
-    _texturing_state = 1;    // textured (not perspective correct)
+    _texturing_state = 1;    // textured (not perspective correct, no multitexture)
   
   
   } else {
   } else {
     // This is the default texture filter.  We use nearest sampling if
     // This is the default texture filter.  We use nearest sampling if
@@ -2097,10 +2128,6 @@ do_issue_texture() {
       _texfilter_state = 1;  // tmipmap
       _texfilter_state = 1;  // tmipmap
     }
     }
   }
   }
-
-  // M_replace means M_replace; anything else is treated the same as
-  // M_modulate.
-  _texture_replace = (stage->get_mode() == TextureStage::M_replace);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 1
panda/src/tinydisplay/tinyGraphicsStateGuardian.h

@@ -82,7 +82,7 @@ public:
                                        const TransformState *transform);
                                        const TransformState *transform);
 
 
   virtual TextureContext *prepare_texture(Texture *tex);
   virtual TextureContext *prepare_texture(Texture *tex);
-  virtual bool update_texture(TextureContext *tc, bool force);
+  bool update_texture(TextureContext *tc, bool force, int stage_index);
   virtual void release_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
 
   virtual void do_issue_light();
   virtual void do_issue_light();
@@ -173,6 +173,9 @@ private:
   static PStatCollector _pixel_count_white_perspective_pcollector;
   static PStatCollector _pixel_count_white_perspective_pcollector;
   static PStatCollector _pixel_count_flat_perspective_pcollector;
   static PStatCollector _pixel_count_flat_perspective_pcollector;
   static PStatCollector _pixel_count_smooth_perspective_pcollector;
   static PStatCollector _pixel_count_smooth_perspective_pcollector;
+  static PStatCollector _pixel_count_white_multitex_pcollector;
+  static PStatCollector _pixel_count_flat_multitex_pcollector;
+  static PStatCollector _pixel_count_smooth_multitex_pcollector;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 5 - 1
panda/src/tinydisplay/zbuffer.cxx

@@ -20,6 +20,9 @@ int pixel_count_smooth_textured;
 int pixel_count_white_perspective;
 int pixel_count_white_perspective;
 int pixel_count_flat_perspective;
 int pixel_count_flat_perspective;
 int pixel_count_smooth_perspective;
 int pixel_count_smooth_perspective;
+int pixel_count_white_multitex;
+int pixel_count_flat_multitex;
+int pixel_count_smooth_multitex;
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
 
 
 ZBuffer *ZB_open(int xsize, int ysize, int mode,
 ZBuffer *ZB_open(int xsize, int ysize, int mode,
@@ -80,7 +83,8 @@ ZBuffer *ZB_open(int xsize, int ysize, int mode,
 	zb->pbuf = (PIXEL *)frame_buffer;
 	zb->pbuf = (PIXEL *)frame_buffer;
     }
     }
 
 
-    zb->current_texture = NULL;
+    zb->current_textures[0] = NULL;
+    zb->current_textures[1] = NULL;
 
 
     return zb;
     return zb;
   error:
   error:

+ 13 - 5
panda/src/tinydisplay/zbuffer.h

@@ -43,11 +43,11 @@ typedef unsigned short ZPOINT;
    already doing the right thing.  Is msvc? */
    already doing the right thing.  Is msvc? */
 //#define FAST_ABS(v) (((v) ^ ((v) >> (sizeof(v) * 8 - 1))) - ((v) >> (sizeof(v) * 8 - 1)))
 //#define FAST_ABS(v) (((v) ^ ((v) >> (sizeof(v) * 8 - 1))) - ((v) >> (sizeof(v) * 8 - 1)))
 
 
-#define DO_CALC_MIPMAP_LEVEL \
+#define DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) \
   { \
   { \
-    mipmap_dx = ((unsigned int)abs(dsdx) + (unsigned int)abs(dtdx)); \
-    mipmap_level = get_next_higher_bit(mipmap_dx >> ZB_POINT_ST_FRAC_BITS); \
-    mipmap_dx &= ((1 << ((mipmap_level - 1) + ZB_POINT_ST_FRAC_BITS)) - 1); \
+    (mipmap_dx) = ((unsigned int)abs(dsdx) + (unsigned int)abs(dtdx)); \
+    (mipmap_level) = get_next_higher_bit((mipmap_dx) >> ZB_POINT_ST_FRAC_BITS); \
+    (mipmap_dx) &= ((1 << (((mipmap_level) - 1) + ZB_POINT_ST_FRAC_BITS)) - 1); \
   }
   }
 
 
 #define ZB_POINT_RED_MIN   0x0000
 #define ZB_POINT_RED_MIN   0x0000
@@ -81,6 +81,8 @@ typedef unsigned int PIXEL;
 // Returns an unsigned product of c1 * c2
 // Returns an unsigned product of c1 * c2
 #define PCOMPONENT_MULT(c1, c2) \
 #define PCOMPONENT_MULT(c1, c2) \
   ((((unsigned int)(c1) * (unsigned int)(c2))) >> 16)
   ((((unsigned int)(c1) * (unsigned int)(c2))) >> 16)
+#define PCOMPONENT_MULT3(c1, c2, c3) \
+  PCOMPONENT_MULT(c1, PCOMPONENT_MULT(c2, c3))
 
 
 // Returns a signed product of c1 * c2, where c1 is initially signed.
 // Returns a signed product of c1 * c2, where c1 is initially signed.
 // We leave 2 bits on the top to differentiate between c1 < 0 and c1 >
 // We leave 2 bits on the top to differentiate between c1 < 0 and c1 >
@@ -126,7 +128,7 @@ struct ZBuffer {
   int nb_colors;
   int nb_colors;
   unsigned char *dctable;
   unsigned char *dctable;
   int *ctable;
   int *ctable;
-  ZTextureLevel *current_texture;  // This is actually an array of texture levels.
+  ZTextureLevel *current_textures[MAX_TEXTURE_STAGES];  // This is actually an array of texture levels for each stage.
   int reference_alpha;
   int reference_alpha;
   int blend_r, blend_g, blend_b, blend_a;
   int blend_r, blend_g, blend_b, blend_a;
   ZB_storePixelFunc store_pix_func;
   ZB_storePixelFunc store_pix_func;
@@ -140,6 +142,9 @@ struct ZBufferPoint {
   int r,g,b,a;     /* color indexes */
   int r,g,b,a;     /* color indexes */
   
   
   float sz,tz;   /* temporary coordinates for mapping */
   float sz,tz;   /* temporary coordinates for mapping */
+
+  int sa, ta;   /* mapping coordinates for optional second texture stage */
+  float sza,tza; 
 };
 };
 
 
 /* zbuffer.c */
 /* zbuffer.c */
@@ -154,6 +159,9 @@ extern int pixel_count_smooth_textured;
 extern int pixel_count_white_perspective;
 extern int pixel_count_white_perspective;
 extern int pixel_count_flat_perspective;
 extern int pixel_count_flat_perspective;
 extern int pixel_count_smooth_perspective;
 extern int pixel_count_smooth_perspective;
+extern int pixel_count_white_multitex;
+extern int pixel_count_flat_multitex;
+extern int pixel_count_smooth_multitex;
 
 
 #define COUNT_PIXELS(pixel_count, p0, p1, p2) \
 #define COUNT_PIXELS(pixel_count, p0, p1, p2) \
   (pixel_count) += abs((p0)->x * ((p1)->y - (p2)->y) + (p1)->x * ((p2)->y - (p0)->y) + (p2)->x * ((p0)->y - (p1)->y)) / 2
   (pixel_count) += abs((p0)->x * ((p1)->y - (p2)->y) + (p1)->x * ((p2)->y - (p0)->y) + (p2)->x * ((p0)->y - (p1)->y)) / 2

+ 3 - 0
panda/src/tinydisplay/zfeatures.h

@@ -36,4 +36,7 @@
 #define TGL_FEATURE_24_BITS        1
 #define TGL_FEATURE_24_BITS        1
 #define TGL_FEATURE_32_BITS        1
 #define TGL_FEATURE_32_BITS        1
 
 
+/* Number of simultaneous texture stages supported (multitexture). */
+#define MAX_TEXTURE_STAGES 2
+
 #endif /* _tgl_features_h_ */
 #endif /* _tgl_features_h_ */

+ 3 - 4
panda/src/tinydisplay/zgl.h

@@ -105,7 +105,7 @@ typedef struct GLVertex {
   int edge_flag;
   int edge_flag;
   V3 normal;
   V3 normal;
   V4 coord;
   V4 coord;
-  V4 tex_coord;
+  V4 tex_coord[MAX_TEXTURE_STAGES];
   V4 color;
   V4 color;
   
   
   /* computed values */
   /* computed values */
@@ -151,8 +151,8 @@ typedef struct GLContext {
   GLMaterial materials[2];
   GLMaterial materials[2];
 
 
   /* textures */
   /* textures */
-  GLTexture *current_texture;
-  int texture_2d_enabled;
+  GLTexture *current_textures[MAX_TEXTURE_STAGES];
+  int num_textures_enabled;
  
  
   /* matrix */
   /* matrix */
   M4 matrix_projection;
   M4 matrix_projection;
@@ -180,7 +180,6 @@ typedef struct GLContext {
   /* current vertex state */
   /* current vertex state */
   V4 current_color;
   V4 current_color;
   V4 current_normal;
   V4 current_normal;
-  V4 current_tex_coord;
 
 
   /* depth test */
   /* depth test */
   int depth_test;
   int depth_test;

+ 58 - 1
panda/src/tinydisplay/ztriangle.h

@@ -33,9 +33,16 @@
   float sz1,dszdx,dszdy,dszdl_min,dszdl_max;
   float sz1,dszdx,dszdy,dszdl_min,dszdl_max;
   float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max;
   float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max;
 #endif
 #endif
+#ifdef INTERP_STZA
+  float sza1,dszadx,dszady,dszadl_min,dszadl_max;
+  float tza1,dtzadx,dtzady,dtzadl_min,dtzadl_max;
+#endif
 #if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ))
 #if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ))
   unsigned int mipmap_dx, mipmap_level;
   unsigned int mipmap_dx, mipmap_level;
 #endif
 #endif
+#ifdef INTERP_STZA
+  unsigned int mipmap_dxa, mipmap_levela;
+#endif
 
 
   EARLY_OUT();
   EARLY_OUT();
 
 
@@ -117,7 +124,7 @@
   dtdx = (int) (fdy2 * d1 - fdy1 * d2);
   dtdx = (int) (fdy2 * d1 - fdy1 * d2);
   dtdy = (int) (fdx1 * d2 - fdx2 * d1);
   dtdy = (int) (fdx1 * d2 - fdx2 * d1);
 
 
-  CALC_MIPMAP_LEVEL;
+  CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);
 #endif
 #endif
 
 
 #ifdef INTERP_STZ
 #ifdef INTERP_STZ
@@ -145,6 +152,31 @@
   }
   }
 #endif
 #endif
 
 
+#ifdef INTERP_STZA
+  {
+    float zz;
+    zz=(float) p0->z;
+    p0->sza= (float) p0->sa * zz;
+    p0->tza= (float) p0->ta * zz;
+    zz=(float) p1->z;
+    p1->sza= (float) p1->sa * zz;
+    p1->tza= (float) p1->ta * zz;
+    zz=(float) p2->z;
+    p2->sza= (float) p2->sa * zz;
+    p2->tza= (float) p2->ta * zz;
+
+    d1 = p1->sza - p0->sza;
+    d2 = p2->sza - p0->sza;
+    dszadx = (fdy2 * d1 - fdy1 * d2);
+    dszady = (fdx1 * d2 - fdx2 * d1);
+    
+    d1 = p1->tza - p0->tza;
+    d2 = p2->tza - p0->tza;
+    dtzadx = (fdy2 * d1 - fdy1 * d2);
+    dtzady = (fdx1 * d2 - fdx2 * d1);
+  }
+#endif
+
   /* screen coordinates */
   /* screen coordinates */
 
 
   pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y);
   pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y);
@@ -240,6 +272,15 @@
       tz1=l1->tz;
       tz1=l1->tz;
       dtzdl_min=(dtzdy + dtzdx * dxdy_min);
       dtzdl_min=(dtzdy + dtzdx * dxdy_min);
       dtzdl_max=dtzdl_min + dtzdx;
       dtzdl_max=dtzdl_min + dtzdx;
+#endif
+#ifdef INTERP_STZA
+      sza1=l1->sza;
+      dszadl_min=(dszady + dszadx * dxdy_min);
+      dszadl_max=dszadl_min + dszadx;
+      
+      tza1=l1->tza;
+      dtzadl_min=(dtzady + dtzadx * dxdy_min);
+      dtzadl_max=dtzadl_min + dtzadx;
 #endif
 #endif
     }
     }
 
 
@@ -277,6 +318,9 @@
 #ifdef INTERP_STZ
 #ifdef INTERP_STZ
           float sz,tz;
           float sz,tz;
 #endif
 #endif
+#ifdef INTERP_STZA
+          float sza,tza;
+#endif
 
 
           n=(x2 >> 16) - x1;
           n=(x2 >> 16) - x1;
           pp=(PIXEL *)((char *)pp1 + x1 * PSZB);
           pp=(PIXEL *)((char *)pp1 + x1 * PSZB);
@@ -297,6 +341,10 @@
 #ifdef INTERP_STZ
 #ifdef INTERP_STZ
           sz=sz1;
           sz=sz1;
           tz=tz1;
           tz=tz1;
+#endif
+#ifdef INTERP_STZA
+          sza=sza1;
+          tza=tza1;
 #endif
 #endif
           while (n>=3) {
           while (n>=3) {
               PUT_PIXEL(0);
               PUT_PIXEL(0);
@@ -343,6 +391,10 @@
 #ifdef INTERP_STZ
 #ifdef INTERP_STZ
 	sz1+=dszdl_max;
 	sz1+=dszdl_max;
 	tz1+=dtzdl_max;
 	tz1+=dtzdl_max;
+#endif
+#ifdef INTERP_STZA
+	sza1+=dszadl_max;
+	tza1+=dtzadl_max;
 #endif
 #endif
       } else {
       } else {
 	x1+=dxdy_min;
 	x1+=dxdy_min;
@@ -362,6 +414,10 @@
 #ifdef INTERP_STZ
 #ifdef INTERP_STZ
 	sz1+=dszdl_min;
 	sz1+=dszdl_min;
 	tz1+=dtzdl_min;
 	tz1+=dtzdl_min;
+#endif
+#ifdef INTERP_STZA
+	sza1+=dszadl_min;
+	tza1+=dtzadl_min;
 #endif
 #endif
       } 
       } 
       
       
@@ -379,6 +435,7 @@
 #undef INTERP_RGB
 #undef INTERP_RGB
 #undef INTERP_ST
 #undef INTERP_ST
 #undef INTERP_STZ
 #undef INTERP_STZ
+#undef INTERP_STZA
 
 
 #undef EARLY_OUT
 #undef EARLY_OUT
 #undef EARLY_OUT_FZ
 #undef EARLY_OUT_FZ

+ 8 - 4
panda/src/tinydisplay/ztriangle.py

@@ -34,7 +34,7 @@ ExtraOptions = [
     [ 'white', 'flat', 'smooth' ],
     [ 'white', 'flat', 'smooth' ],
 
 
     # texturing
     # texturing
-    [ 'untextured', 'textured', 'perspective' ],
+    [ 'untextured', 'textured', 'perspective', 'multitex' ],
     ]
     ]
 
 
 FullOptions = Options + ExtraOptions
 FullOptions = Options + ExtraOptions
@@ -60,9 +60,9 @@ CodeTable = {
     'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))',
     'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))',
 
 
     # texture filters
     # texture filters
-    'tnearest' : '#define CALC_MIPMAP_LEVEL\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t)',
-    'tmipmap' : '#define CALC_MIPMAP_LEVEL DO_CALC_MIPMAP_LEVEL\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level)',
-    'tgeneral' : '#define CALC_MIPMAP_LEVEL DO_CALC_MIPMAP_LEVEL\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ((level == 0) ? zb->tex_magfilter_func(texture_levels, s, t, level, level_dx) : zb->tex_minfilter_func(texture_levels, s, t, level, level_dx))',
+    'tnearest' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t)',
+    'tmipmap' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level)',
+    'tgeneral' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ((level == 0) ? zb->tex_magfilter_func(texture_levels, s, t, level, level_dx) : zb->tex_minfilter_func(texture_levels, s, t, level, level_dx))',
 }
 }
 
 
 ops = [0] * len(Options)
 ops = [0] * len(Options)
@@ -91,6 +91,10 @@ def getFname(ops):
         keyword = FullOptions[i][ops[i]]
         keyword = FullOptions[i][ops[i]]
         keywordList.append(keyword)
         keywordList.append(keyword)
 
 
+    if keywordList[-1] == 'multitex':
+        # We don't bother with white_multitex or flat_multitex.
+        keywordList[-2] = 'smooth'
+
     fname = 'FB_triangle_%s' % ('_'.join(keywordList))
     fname = 'FB_triangle_%s' % ('_'.join(keywordList))
     return fname
     return fname
 
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 112 - 112
panda/src/tinydisplay/ztriangle_code.h


+ 1 - 1
panda/src/tinydisplay/ztriangle_table.h

@@ -1,3 +1,3 @@
 /* This file is generated code--do not edit.  See ztriangle.py. */
 /* This file is generated code--do not edit.  See ztriangle.py. */
 
 
-extern const ZB_fillTriangleFunc fill_tri_funcs[2][4][3][2][3][3][3];
+extern const ZB_fillTriangleFunc fill_tri_funcs[2][4][3][2][3][3][4];

+ 166 - 12
panda/src/tinydisplay/ztriangle_two.h

@@ -128,7 +128,7 @@ static void FNAME(white_textured) (ZBuffer *zb,
 
 
 #define DRAW_INIT()				\
 #define DRAW_INIT()				\
   {						\
   {						\
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
   }
   }
 
 
 #define PUT_PIXEL(_a)                                                   \
 #define PUT_PIXEL(_a)                                                   \
@@ -170,7 +170,7 @@ static void FNAME(flat_textured) (ZBuffer *zb,
       /* This alpha is zero, and we'll never get other than 0. */       \
       /* This alpha is zero, and we'll never get other than 0. */       \
       return;                                   \
       return;                                   \
     }                                           \
     }                                           \
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
     or0 = p2->r;                                \
     or0 = p2->r;                                \
     og0 = p2->g;                                \
     og0 = p2->g;                                \
     ob0 = p2->b;                                \
     ob0 = p2->b;                                \
@@ -235,7 +235,7 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
 
 
 #define DRAW_INIT()                             \
 #define DRAW_INIT()                             \
   {                                             \
   {                                             \
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
   }
   }
 
 
 #define PUT_PIXEL(_a)                                                   \
 #define PUT_PIXEL(_a)                                                   \
@@ -293,7 +293,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
 
 
 #define DRAW_INIT()				\
 #define DRAW_INIT()				\
   {						\
   {						\
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -340,7 +340,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
         t=(int) tt;                            \
         t=(int) tt;                            \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
-        CALC_MIPMAP_LEVEL;                              \
+        CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);   \
         fz+=fndzdx;                                     \
         fz+=fndzdx;                                     \
         zinv=1.0f / fz;                                 \
         zinv=1.0f / fz;                                 \
       }                                                 \
       }                                                 \
@@ -366,7 +366,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
       t=(int) tt;                              \
       t=(int) tt;                              \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
-      CALC_MIPMAP_LEVEL;                                \
+      CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);    \
     }                                                   \
     }                                                   \
     while (n>=0) {                                      \
     while (n>=0) {                                      \
       PUT_PIXEL(0);                                     \
       PUT_PIXEL(0);                                     \
@@ -406,7 +406,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
       /* This alpha is zero, and we'll never get other than 0. */       \
       /* This alpha is zero, and we'll never get other than 0. */       \
       return;                                   \
       return;                                   \
     }                                           \
     }                                           \
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -470,7 +470,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
         t=(int) tt;                            \
         t=(int) tt;                            \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
-        CALC_MIPMAP_LEVEL;                              \
+        CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);  \
         fz+=fndzdx;                                     \
         fz+=fndzdx;                                     \
         zinv=1.0f / fz;                                 \
         zinv=1.0f / fz;                                 \
       }                                                 \
       }                                                 \
@@ -496,7 +496,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
       t=(int) tt;                              \
       t=(int) tt;                              \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
-      CALC_MIPMAP_LEVEL;                                \
+      CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);    \
     }                                                   \
     }                                                   \
     while (n>=0) {                                      \
     while (n>=0) {                                      \
       PUT_PIXEL(0);                                     \
       PUT_PIXEL(0);                                     \
@@ -545,7 +545,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
 
 
 #define DRAW_INIT() 				\
 #define DRAW_INIT() 				\
   {						\
   {						\
-    texture_levels = zb->current_texture;       \
+    texture_levels = zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -609,7 +609,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
         t=(int) tt;                            \
         t=(int) tt;                            \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
         dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
-        CALC_MIPMAP_LEVEL;                              \
+        CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);  \
         fz+=fndzdx;                                     \
         fz+=fndzdx;                                     \
         zinv=1.0f / fz;                                 \
         zinv=1.0f / fz;                                 \
       }                                                 \
       }                                                 \
@@ -635,7 +635,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
       t=(int) tt;                              \
       t=(int) tt;                              \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
       dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
-      CALC_MIPMAP_LEVEL;                                \
+      CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);  \
     }                                                   \
     }                                                   \
     while (n>=0) {                                      \
     while (n>=0) {                                      \
       PUT_PIXEL(0);                                     \
       PUT_PIXEL(0);                                     \
@@ -650,6 +650,160 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
 #include "ztriangle.h"
 #include "ztriangle.h"
 }
 }
 
 
+/*
+ * Smooth filled triangle, with perspective-correct mapping, on two
+ * stages of multitexture.
+ */
+
+static void FNAME(smooth_multitex) (ZBuffer *zb,
+                                    ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
+{
+  float fdzdx,fndzdx,ndszdx,ndtzdx,ndszadx,ndtzadx;
+
+#define INTERP_Z
+#define INTERP_STZ
+#define INTERP_STZA
+#define INTERP_RGB
+
+#define EARLY_OUT() 				\
+  {						\
+  }
+
+#define DRAW_INIT() 				\
+  {						\
+    fdzdx=(float)dzdx;                          \
+    fndzdx=NB_INTERP * fdzdx;                   \
+    ndszdx=NB_INTERP * dszdx;                   \
+    ndtzdx=NB_INTERP * dtzdx;                   \
+    ndszadx=NB_INTERP * dszadx;                   \
+    ndtzadx=NB_INTERP * dtzadx;                   \
+  }
+
+#define PUT_PIXEL(_a)                                                   \
+  {                                                                     \
+    zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
+    if (ZCMP(pz[_a], zz)) {                                             \
+      tmp = ZB_LOOKUP_TEXTURE(zb->current_textures[0], s, t, mipmap_level, mipmap_dx); \
+      int a = PALPHA_MULT(oa1, PIXEL_A(tmp));                           \
+      if (ACMP(zb, a)) {                                                \
+        int tmpa = ZB_LOOKUP_TEXTURE(zb->current_textures[1], sa, ta, mipmap_levela, mipmap_dxa); \
+        STORE_PIX(pp[_a],                                               \
+                  RGBA_TO_PIXEL(PCOMPONENT_MULT3(or1, PIXEL_R(tmp), PIXEL_R(tmpa)),     \
+                                PCOMPONENT_MULT3(og1, PIXEL_G(tmp), PIXEL_G(tmpa)),     \
+                                PCOMPONENT_MULT3(ob1, PIXEL_B(tmp), PIXEL_B(tmpa)),     \
+                                a),                                     \
+                  PCOMPONENT_MULT3(or1, PIXEL_R(tmp), PIXEL_R(tmpa)),                   \
+                  PCOMPONENT_MULT3(og1, PIXEL_G(tmp), PIXEL_G(tmpa)),                   \
+                  PCOMPONENT_MULT3(ob1, PIXEL_B(tmp), PIXEL_B(tmpa)),                   \
+                  a);                                                   \
+        STORE_Z(pz[_a], zz);                                            \
+      }                                                                 \
+    }                                                                   \
+    z+=dzdx;                                                            \
+    og1+=dgdx;                                                          \
+    or1+=drdx;                                                          \
+    ob1+=dbdx;                                                          \
+    oa1+=dadx;                                                          \
+    s+=dsdx;                                                            \
+    t+=dtdx;                                                            \
+    sa+=dsadx;                                                            \
+    ta+=dtadx;                                                            \
+  }
+
+#define DRAW_LINE()                                     \
+  {                                                     \
+    register ZPOINT *pz;                                \
+    register PIXEL *pp;                                 \
+    register int s,t,sa,ta,z,zz;                     \
+    register int n,dsdx,dtdx,dsadx,dtadx;                           \
+    register int or1,og1,ob1,oa1;              \
+    float sz,tz,sza,tza,fz,zinv;                                \
+    n=(x2>>16)-x1;                                      \
+    fz=(float)z1;                                       \
+    zinv=1.0f / fz;                                     \
+    pp=(PIXEL *)((char *)pp1 + x1 * PSZB);              \
+    pz=pz1+x1;                                          \
+    z=z1;						\
+    sz=sz1;                                             \
+    tz=tz1;                                             \
+    sza=sza1;                                             \
+    tza=tza1;                                             \
+    or1 = r1;                                           \
+    og1 = g1;                                           \
+    ob1 = b1;                                           \
+    oa1 = a1;                                           \
+    while (n>=(NB_INTERP-1)) {                          \
+      {                                                 \
+        float ss,tt;                                    \
+        ss=(sz * zinv);                                 \
+        tt=(tz * zinv);                                 \
+        s=(int) ss;                            \
+        t=(int) tt;                            \
+        dsdx= (int)( (dszdx - ss*fdzdx)*zinv );         \
+        dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );         \
+        CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);     \
+      }                                                 \
+      {                                                 \
+        float ssa,tta;                                    \
+        ssa=(sza * zinv);                                 \
+        tta=(tza * zinv);                                 \
+        sa=(int) ssa;                            \
+        ta=(int) tta;                            \
+        dsadx= (int)( (dszadx - ssa*fdzdx)*zinv );         \
+        dtadx= (int)( (dtzadx - tta*fdzdx)*zinv );         \
+        CALC_MIPMAP_LEVEL(mipmap_levela, mipmap_dxa, dsadx, dtadx);   \
+      }                                                 \
+      fz+=fndzdx;                                     \
+      zinv=1.0f / fz;                                 \
+      PUT_PIXEL(0);                                     \
+      PUT_PIXEL(1);                                     \
+      PUT_PIXEL(2);                                     \
+      PUT_PIXEL(3);                                     \
+      PUT_PIXEL(4);                                     \
+      PUT_PIXEL(5);                                     \
+      PUT_PIXEL(6);                                     \
+      PUT_PIXEL(7);                                     \
+      pz+=NB_INTERP;                                    \
+      pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB);      \
+      n-=NB_INTERP;                                     \
+      sz+=ndszdx;                                       \
+      tz+=ndtzdx;                                       \
+      sza+=ndszadx;                                       \
+      tza+=ndtzadx;                                       \
+    }                                                   \
+    {                                                   \
+      float ss,tt;                                      \
+      ss=(sz * zinv);                                   \
+      tt=(tz * zinv);                                   \
+      s=(int) ss;                              \
+      t=(int) tt;                              \
+      dsdx= (int)( (dszdx - ss*fdzdx)*zinv );           \
+      dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );           \
+      CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);     \
+    }                                                   \
+    {                                                   \
+      float ssa,tta;                                      \
+      ssa=(sza * zinv);                                   \
+      tta=(tza * zinv);                                   \
+      sa=(int) ssa;                              \
+      ta=(int) tta;                              \
+      dsadx= (int)( (dszadx - ssa*fdzdx)*zinv );           \
+      dtadx= (int)( (dtzadx - tta*fdzdx)*zinv );           \
+      CALC_MIPMAP_LEVEL(mipmap_levela, mipmap_dxa, dsadx, dtadx);   \
+    }                                                   \
+    while (n>=0) {                                      \
+      PUT_PIXEL(0);                                     \
+      pz+=1;                                            \
+      pp=(PIXEL *)((char *)pp + PSZB);                  \
+      n-=1;                                             \
+    }                                                   \
+  }
+
+#define PIXEL_COUNT pixel_count_smooth_multitex
+
+#include "ztriangle.h"
+}
+
 #undef ACMP
 #undef ACMP
 #undef ZCMP
 #undef ZCMP
 #undef STORE_PIX
 #undef STORE_PIX

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно