__forceinline void Pipedata::addVertex(const Viewport& vp, const vec4& src, const mat4& m) { auto point_in_eyespace = mat4_mul(m, src); auto point_in_clipspace = vp.eye_to_clip(point_in_eyespace); auto clipflags = Guardband::clipPoint(point_in_clipspace); vlst_p.push_back(point_in_eyespace); vlst_cf.push_back(clipflags); new_vcnt++; }
void Pipedata::process_face(PFace& f, const Viewport& vp, const Viewdevice& vpd) { vec4 p1 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[0]])); vec4 p2 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[1]])); vec4 p3 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[2]])); const vec4 d31 = p3 - p1; const vec4 d21 = p2 - p1; const float area = d31.x*d21.y - d31.y*d21.x; bool backfacing = area < 0; if (backfacing) return; // cull // if (f.backfacing) { // std::swap(p1, p3); // } binner.insert(p1, p2, p3, backfacing, f); }
void Pipedata::addFace(const Viewport& vp, const Viewdevice& vpd, const Face& fsrc) { const int vidx1 = fsrc.ivp[0] + vbase; const int vidx2 = fsrc.ivp[1] + vbase; const int vidx3 = fsrc.ivp[2] + vbase; const auto& pv1_p = vlst_p[vidx1]; const auto& pv2_p = vlst_p[vidx2]; const auto& pv3_p = vlst_p[vidx3]; const auto& pv1_cf = vlst_cf[vidx1]; const auto& pv2_cf = vlst_cf[vidx2]; const auto& pv3_cf = vlst_cf[vidx3]; // early out if all points are outside of any plane if (pv1_cf & pv2_cf & pv3_cf) return; const unsigned required_clipping = pv1_cf | pv2_cf | pv3_cf; if (required_clipping == 0) { // all inside process_face(fsrc.make_rebased(vbase, tbase, nbase), vp, vpd); return; } // needs clipping unsigned a_vidx[32], b_vidx[32]; unsigned a_tidx[32], b_tidx[32]; unsigned a_nidx[32], b_nidx[32]; unsigned a_cnt = 3; for (unsigned i = 0; i < 3; i++) { a_vidx[i] = fsrc.ivp[i] + vbase; a_tidx[i] = fsrc.iuv[i] + tbase; a_nidx[i] = fsrc.ipn[i] + nbase; } for (int clip_plane = 0; clip_plane < 5; clip_plane++) { // XXX set to 6 to enable the far plane const int planebit = 1 << clip_plane; if (!(required_clipping & planebit)) continue; // skip plane that is ok bool we_are_inside; unsigned this_pi = 0; unsigned b_cnt = 0; do { const auto next_pi = (this_pi + 1) % a_cnt; // wrap const auto& this_v_p = vlst_p[a_vidx[this_pi]]; const auto this_v_c = vp.eye_to_clip(this_v_p); const auto& this_t = tlst[a_tidx[this_pi]]; const auto& this_n = nlst[a_nidx[this_pi]]; const auto& next_v_p = vlst_p[a_vidx[next_pi]]; const auto next_v_c = vp.eye_to_clip(next_v_p); const auto& next_t = tlst[a_tidx[next_pi]]; const auto& next_n = nlst[a_nidx[next_pi]]; if (this_pi == 0) { we_are_inside = Guardband::is_inside(planebit, this_v_c); } const bool next_is_inside = Guardband::is_inside(planebit, next_v_c); if (we_are_inside) { b_vidx[b_cnt] = a_vidx[this_pi]; b_tidx[b_cnt] = a_tidx[this_pi]; b_nidx[b_cnt] = a_nidx[this_pi]; b_cnt++; } if (we_are_inside != next_is_inside) { we_are_inside = !we_are_inside; const float t = Guardband::clipLine(planebit, this_v_c, next_v_c); auto new_p = lerp(this_v_p, next_v_p, t); auto new_c = vp.eye_to_clip(new_p); vlst_p.push_back(new_p); vlst_cf.push_back(0); b_vidx[b_cnt] = vlst_p.size() - 1; tlst.push_back(lerp(this_t, next_t, t)); b_tidx[b_cnt] = tlst.size() - 1; nlst.push_back(lerp(this_n, next_n, t)); b_nidx[b_cnt] = nlst.size() - 1; b_cnt++; } this_pi = next_pi; } while (this_pi != 0); for (unsigned i = 0; i < b_cnt; i++) { a_vidx[i] = b_vidx[i]; a_tidx[i] = b_tidx[i]; a_nidx[i] = b_nidx[i]; } a_cnt = b_cnt; if (a_cnt == 0) break; } if (a_cnt == 0) return; for (unsigned a = 1; a < a_cnt - 1; a++) { PFace f = make_tri( fsrc.mf, a_vidx[0], a_vidx[a], a_vidx[a + 1], a_tidx[0], a_tidx[a], a_tidx[a + 1], a_nidx[0], a_nidx[a], a_nidx[a + 1]); process_face(f, vp, vpd); } }
void Binner::insert_gltri( const Viewport& vp, const Viewdevice& vpd, const vec4 * const pv, const vec4 * const pn, const vec4 * const pc, const vec4 * const pt, int i0, int i1, int i2, const int material_id ) { auto p1 = vpd.clip_to_device(vp.eye_to_clip(pv[i0])); auto p2 = vpd.clip_to_device(vp.eye_to_clip(pv[i1])); auto p3 = vpd.clip_to_device(vp.eye_to_clip(pv[i2])); const auto d31 = p3 - p1; const auto d21 = p2 - p1; const float area = d31.x*d21.y - d31.y*d21.x; auto backfacing = area < 0; if (backfacing) return; // cull /* if (backfacing) { std::swap(p1, p3); std::swap(i0, i2); } */ auto pmin = vmax(vmin(p1, vmin(p2, p3)), vec4::zero()); auto pmax = vmin(vmax(p1, vmax(p2, p3)), device_max); auto x0 = int(pmin._x()); auto y0 = int(pmin._y()); auto x1 = int(pmax._x()); // trick: set this to pmin._x() auto y1 = int(pmax._y()); const int ylim = min(y1 / tileheight, device_height_in_tiles - 1); const int xlim = min(x1 / tilewidth, device_width_in_tiles - 1); const int tx0 = x0 / tilewidth; for (int ty = y0 / tileheight; ty <= ylim; ty++) { int bin_row_offset = ty * device_width_in_tiles; for (int tx = tx0; tx <= xlim; tx++) { auto& bin = bins[bin_row_offset + tx]; unsigned char facedata = material_id; if (backfacing) facedata |= 0x80; bin.glface.push_back(facedata); bin.gldata.push_back(p1); bin.gldata.push_back(pv[i0]); bin.gldata.push_back(pn[i0]); bin.gldata.push_back(pc[i0]); bin.gldata.push_back(pt[i0]); bin.gldata.push_back(p2); bin.gldata.push_back(pv[i1]); bin.gldata.push_back(pn[i1]); bin.gldata.push_back(pc[i1]); bin.gldata.push_back(pt[i1]); bin.gldata.push_back(p3); bin.gldata.push_back(pv[i2]); bin.gldata.push_back(pn[i2]); bin.gldata.push_back(pc[i2]); bin.gldata.push_back(pt[i2]); } } }