protected void render() {
    if (vertexCount < 3) return;

    // these may have changed due to a resize()
    // so they should be refreshed here
    pixels = parent.pixels;
    //zbuffer = parent.zbuffer;

//    noDepthTest = parent.hints[DISABLE_DEPTH_TEST];
    smooth = parent.smooth;

    // by default, text turns on smooth for the textures
    // themselves. but this should be shut off if the hint
    // for DISABLE_TEXT_SMOOTH is set.
//    texture_smooth = true;

    width = smooth ? parent.width*SUBXRES : parent.width;
    height = smooth ? parent.height*SUBYRES : parent.height;

    width1 = width - 1;
    height1 = height - 1;

    if (!interpARGB) {
      r2 = (int) (vertices[0][R] * 255);
      g2 = (int) (vertices[0][G] * 255);
      b2 = (int) (vertices[0][B] * 255);
      a2 = (int) (vertices[0][A] * 255);
      a2orig = a2; // save an extra copy
      rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
    }

    for (int i = 0; i < vertexCount; i++) {
      r[i] = 0; dr[i] = 0; l[i] = 0; dl[i] = 0;
    }

    /*
    // hack to not make polygons fly into the screen
    if (parent.hints[DISABLE_FLYING_POO]) {
      float nwidth2 = -width * 2;
      float nheight2 = -height * 2;
      float width2 = width * 2;
      float height2 = height * 2;
      for (int i = 0; i < vertexCount; i++) {
        if ((vertices[i][TX] < nwidth2) ||
            (vertices[i][TX] > width2) ||
            (vertices[i][TY] < nheight2) ||
            (vertices[i][TY] > height2)) {
          return;  // this is a bad poly
        }
      }
    }
    */

//    for (int i = 0; i < 4; i++) {
//      System.out.println(vertices[i][R] + " " + vertices[i][G] + " " + vertices[i][B]);
//    }
//    System.out.println();
    
    if (smooth) {
      for (int i = 0; i < vertexCount; i++) {
        vertices[i][TX] *= SUBXRES;
        vertices[i][TY] *= SUBYRES;
      }
      firstModY = -1;
    }

    // find top vertex (y is zero at top, higher downwards)
    int topi = 0;
    float ymin = vertices[0][TY];
    float ymax = vertices[0][TY]; // fry 031001
    for (int i = 1; i < vertexCount; i++) {
      if (vertices[i][TY] < ymin) {
        ymin = vertices[i][TY];
        topi = i;
      }
      if (vertices[i][TY] > ymax) {
        ymax = vertices[i][TY];
      }
    }

    // the last row is an exceptional case, because there won't
    // necessarily be 8 rows of subpixel lines that will force
    // the final line to render. so instead, the algo keeps track
    // of the lastY (in subpixel resolution) that will be rendered
    // and that will force a scanline to happen the same as
    // every eighth in the other situations
    //lastY = -1;  // fry 031001
    lastY = (int) (ymax - 0.5f);  // global to class bc used by other fxns

    int lefti = topi;             // li, index of left vertex
    int righti = topi;            // ri, index of right vertex
    int y = (int) (ymin + 0.5f);  // current scan line
    int lefty = y - 1;            // lower end of left edge
    int righty = y - 1;           // lower end of right edge

    interpX = true;

    int remaining = vertexCount;

    // scan in y, activating new edges on left & right
    // as scan line passes over new vertices
    while (remaining > 0) {
      // advance left edge?
      while ((lefty <= y) && (remaining > 0)) {
        remaining--;
        // step ccw down left side
        int i = (lefti != 0) ? (lefti-1) : (vertexCount-1);
        incrementalizeY(vertices[lefti], vertices[i], l, dl, y);
        lefty = (int) (vertices[i][TY] + 0.5f);
        lefti = i;
      }

      // advance right edge?
      while ((righty <= y) && (remaining > 0)) {
        remaining--;
        // step cw down right edge
        int i = (righti != vertexCount-1) ? (righti + 1) : 0;
        incrementalizeY(vertices[righti], vertices[i], r, dr, y);
        righty = (int) (vertices[i][TY] + 0.5f);
        righti = i;
      }

      // do scanlines till end of l or r edge
      while (y < lefty && y < righty) {
        // this doesn't work because it's not always set here
        //if (remaining == 0) {
        //lastY = (lefty < righty) ? lefty-1 : righty-1;
        //System.out.println("lastY is " + lastY);
        //}

        if ((y >= 0) && (y < height)) {
          //try {  // hopefully this bug is fixed
          if (l[TX] <= r[TX]) scanline(y, l, r);
          else scanline(y, r, l);
          //} catch (ArrayIndexOutOfBoundsException e) {
          //e.printStackTrace();
          //}
        }
        y++;
        // this increment probably needs to be different
        // UV and RGB shouldn't be incremented until line is emitted
        increment(l, dl);
        increment(r, dr);
      }
    }
    //if (smooth) {
    //System.out.println("y/lasty/lastmody = " + y + " " + lastY + " " + lastModY);
    //}
  }