mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
[spline/bezier]Writing vertices to the buffer directly.
This commit is contained in:
1 parent
51a5935d9a
commit
43e3028add
6 files changed
+83
-57
No files matched your search
+70
-36
@@ -41,6 +41,25 @@ static void CopyQuad(u8 *&dest, const SimpleVertex *v1, const SimpleVertex *v2,
|
||||
dest += vertexSize;
|
||||
}
|
||||
|
||||
static void CopyQuadIndex(u16 *&indices, GEPatchPrimType type, const int idx0, const int idx1, const int idx2, const int idx3) {
|
||||
if (type == GE_PATCHPRIM_LINES) {
|
||||
*(indices++) = idx0;
|
||||
*(indices++) = idx2;
|
||||
*(indices++) = idx1;
|
||||
*(indices++) = idx3;
|
||||
*(indices++) = idx1;
|
||||
*(indices++) = idx2;
|
||||
}
|
||||
else {
|
||||
*(indices++) = idx0;
|
||||
*(indices++) = idx2;
|
||||
*(indices++) = idx1;
|
||||
*(indices++) = idx1;
|
||||
*(indices++) = idx2;
|
||||
*(indices++) = idx3;
|
||||
}
|
||||
}
|
||||
|
||||
#undef b2
|
||||
|
||||
// Bernstein basis functions
|
||||
@@ -111,7 +130,7 @@ void spline_knot(int n, int type, float *knot) {
|
||||
}
|
||||
}
|
||||
|
||||
void _SplinePatchLowQuality(u8 *&dest, int &count, const SplinePatchLocal &spatch, u32 origVertType) {
|
||||
void _SplinePatchLowQuality(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType) {
|
||||
// Fast and easy way - just draw the control points, generate some very basic normal vector substitutes.
|
||||
// Very inaccurate but okay for Loco Roco. Maybe should keep it as an option because it's fast.
|
||||
|
||||
@@ -125,6 +144,9 @@ void _SplinePatchLowQuality(u8 *&dest, int &count, const SplinePatchLocal &spatc
|
||||
tu_width /= (float)(tile_max_u - tile_min_u);
|
||||
tv_height /= (float)(tile_max_v - tile_min_v);
|
||||
|
||||
GEPatchPrimType prim_type = gstate.getPatchPrimitiveType();
|
||||
|
||||
int i = 0;
|
||||
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
||||
for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
|
||||
int point_index = tile_u + tile_v * spatch.count_u;
|
||||
@@ -162,14 +184,21 @@ void _SplinePatchLowQuality(u8 *&dest, int &count, const SplinePatchLocal &spatc
|
||||
v3.nrm = norm;
|
||||
}
|
||||
|
||||
int idx0 = i * 4 + 0;
|
||||
int idx1 = i * 4 + 1;
|
||||
int idx2 = i * 4 + 2;
|
||||
int idx3 = i * 4 + 3;
|
||||
i++;
|
||||
|
||||
CopyQuad(dest, &v0, &v1, &v2, &v3);
|
||||
CopyQuadIndex(indices, prim_type, idx0, idx1, idx2, idx3);
|
||||
count += 6;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void _SplinePatchFullQuality(u8 *&dest, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality) {
|
||||
void _SplinePatchFullQuality(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType, int quality) {
|
||||
// Full (mostly) correct tessellation of spline patches.
|
||||
// Not very fast.
|
||||
|
||||
@@ -193,7 +222,7 @@ void _SplinePatchFullQuality(u8 *&dest, int &count, const SplinePatchLocal &spa
|
||||
if (patch_div_t < 2) patch_div_t = 2;
|
||||
|
||||
// First compute all the vertices and put them in an array
|
||||
SimpleVertex *vertices = new SimpleVertex[(patch_div_s + 1) * (patch_div_t + 1)];
|
||||
SimpleVertex *&vertices = (SimpleVertex*&)dest;
|
||||
|
||||
float tu_width = spatch.count_u - 3;
|
||||
float tv_height = spatch.count_v - 3;
|
||||
@@ -300,40 +329,36 @@ void _SplinePatchFullQuality(u8 *&dest, int &count, const SplinePatchLocal &spa
|
||||
}
|
||||
}
|
||||
|
||||
// Tesselate. TODO: Use indices so we only need to emit 4 vertices per pair of triangles instead of six.
|
||||
GEPatchPrimType prim_type = gstate.getPatchPrimitiveType();
|
||||
// Tesselate.
|
||||
for (int tile_v = 0; tile_v < patch_div_t; ++tile_v) {
|
||||
for (int tile_u = 0; tile_u < patch_div_s; ++tile_u) {
|
||||
float u = ((float)tile_u / (float)patch_div_s);
|
||||
float v = ((float)tile_v / (float)patch_div_t);
|
||||
int idx0 = tile_v * (patch_div_s + 1) + tile_u;
|
||||
int idx1 = tile_v * (patch_div_s + 1) + tile_u + 1;
|
||||
int idx2 = (tile_v + 1) * (patch_div_s + 1) + tile_u;
|
||||
int idx3 = (tile_v + 1) * (patch_div_s + 1) + tile_u + 1;
|
||||
|
||||
SimpleVertex *v0 = &vertices[tile_v * (patch_div_s + 1) + tile_u];
|
||||
SimpleVertex *v1 = &vertices[tile_v * (patch_div_s + 1) + tile_u + 1];
|
||||
SimpleVertex *v2 = &vertices[(tile_v + 1) * (patch_div_s + 1) + tile_u];
|
||||
SimpleVertex *v3 = &vertices[(tile_v + 1) * (patch_div_s + 1) + tile_u + 1];
|
||||
|
||||
CopyQuad(dest, v0, v1, v2, v3);
|
||||
CopyQuadIndex(indices, prim_type, idx0, idx1, idx2, idx3);
|
||||
count += 6;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] vertices;
|
||||
}
|
||||
|
||||
void TesselateSplinePatch(u8 *&dest, int &count, const SplinePatchLocal &spatch, u32 origVertType) {
|
||||
void TesselateSplinePatch(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType) {
|
||||
switch (g_Config.iSplineBezierQuality) {
|
||||
case LOW_QUALITY:
|
||||
_SplinePatchLowQuality(dest, count, spatch, origVertType);
|
||||
_SplinePatchLowQuality(dest, indices, count, spatch, origVertType);
|
||||
break;
|
||||
case MEDIUM_QUALITY:
|
||||
_SplinePatchFullQuality(dest, count, spatch, origVertType, 2);
|
||||
_SplinePatchFullQuality(dest, indices, count, spatch, origVertType, 2);
|
||||
break;
|
||||
case HIGH_QUALITY:
|
||||
_SplinePatchFullQuality(dest, count, spatch, origVertType, 1);
|
||||
_SplinePatchFullQuality(dest, indices, count, spatch, origVertType, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _BezierPatchLowQuality(u8 *&dest, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
void _BezierPatchLowQuality(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
const float third = 1.0f / 3.0f;
|
||||
// Fast and easy way - just draw the control points, generate some very basic normal vector subsitutes.
|
||||
// Very inaccurate though but okay for Loco Roco. Maybe should keep it as an option.
|
||||
@@ -341,6 +366,8 @@ void _BezierPatchLowQuality(u8 *&dest, int &count, int tess_u, int tess_v, const
|
||||
float u_base = patch.u_index / 3.0f;
|
||||
float v_base = patch.v_index / 3.0f;
|
||||
|
||||
GEPatchPrimType prim_type = gstate.getPatchPrimitiveType();
|
||||
|
||||
for (int tile_v = 0; tile_v < 3; tile_v++) {
|
||||
for (int tile_u = 0; tile_u < 3; tile_u++) {
|
||||
int point_index = tile_u + tile_v * 4;
|
||||
@@ -377,19 +404,28 @@ void _BezierPatchLowQuality(u8 *&dest, int &count, int tess_u, int tess_v, const
|
||||
v3.nrm = norm;
|
||||
}
|
||||
|
||||
|
||||
int total = patch.index * 3 * 3 * 4; // A patch has 3x3 tiles, and each tiles have 4 vertices.
|
||||
int tile_index = tile_u + tile_v * 3;
|
||||
int idx0 = total + tile_index * 4 + 0;
|
||||
int idx1 = total + tile_index * 4 + 1;
|
||||
int idx2 = total + tile_index * 4 + 2;
|
||||
int idx3 = total + tile_index * 4 + 3;
|
||||
|
||||
CopyQuad(dest, &v0, &v1, &v2, &v3);
|
||||
CopyQuadIndex(indices, prim_type, idx0, idx1, idx2, idx3);
|
||||
count += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _BezierPatchHighQuality(u8 *&dest, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
void _BezierPatchHighQuality(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
const float third = 1.0f / 3.0f;
|
||||
// Full correct tesselation of bezier patches.
|
||||
// Note: Does not handle splines correctly.
|
||||
|
||||
// First compute all the vertices and put them in an array
|
||||
SimpleVertex *vertices = new SimpleVertex[(tess_u + 1) * (tess_v + 1)];
|
||||
SimpleVertex *&vertices = (SimpleVertex*&)dest;
|
||||
|
||||
Vec3Packedf *horiz = new Vec3Packedf[(tess_u + 1) * 4];
|
||||
Vec3Packedf *horiz2 = horiz + (tess_u + 1) * 1;
|
||||
@@ -474,35 +510,33 @@ void _BezierPatchHighQuality(u8 *&dest, int &count, int tess_u, int tess_v, cons
|
||||
delete[] derivU1;
|
||||
delete[] horiz;
|
||||
|
||||
// Tesselate. TODO: Use indices so we only need to emit 4 vertices per pair of triangles instead of six.
|
||||
GEPatchPrimType prim_type = gstate.getPatchPrimitiveType();
|
||||
// Tesselate.
|
||||
for (int tile_v = 0; tile_v < tess_v; ++tile_v) {
|
||||
for (int tile_u = 0; tile_u < tess_u; ++tile_u) {
|
||||
float u = ((float)tile_u / (float)tess_u);
|
||||
float v = ((float)tile_v / (float)tess_v);
|
||||
int total = patch.index * (tess_u + 1) * (tess_v + 1);
|
||||
int idx0 = total + tile_v * (tess_u + 1) + tile_u;
|
||||
int idx1 = total + tile_v * (tess_u + 1) + tile_u + 1;
|
||||
int idx2 = total + (tile_v + 1) * (tess_u + 1) + tile_u;
|
||||
int idx3 = total + (tile_v + 1) * (tess_u + 1) + tile_u + 1;
|
||||
|
||||
const SimpleVertex *v0 = &vertices[tile_v * (tess_u + 1) + tile_u];
|
||||
const SimpleVertex *v1 = &vertices[tile_v * (tess_u + 1) + tile_u + 1];
|
||||
const SimpleVertex *v2 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u];
|
||||
const SimpleVertex *v3 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u + 1];
|
||||
|
||||
CopyQuad(dest, v0, v1, v2, v3);
|
||||
CopyQuadIndex(indices, prim_type, idx0, idx1, idx2, idx3);
|
||||
count += 6;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] vertices;
|
||||
dest += (tess_u + 1) * (tess_v + 1) * sizeof(SimpleVertex);
|
||||
}
|
||||
|
||||
void TesselateBezierPatch(u8 *&dest, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
void TesselateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType) {
|
||||
switch (g_Config.iSplineBezierQuality) {
|
||||
case LOW_QUALITY:
|
||||
_BezierPatchLowQuality(dest, count, tess_u, tess_v, patch, origVertType);
|
||||
_BezierPatchLowQuality(dest, indices, count, tess_u, tess_v, patch, origVertType);
|
||||
break;
|
||||
case MEDIUM_QUALITY:
|
||||
_BezierPatchHighQuality(dest, count, tess_u / 2, tess_v / 2, patch, origVertType);
|
||||
_BezierPatchHighQuality(dest, indices, count, tess_u / 2, tess_v / 2, patch, origVertType);
|
||||
break;
|
||||
case HIGH_QUALITY:
|
||||
_BezierPatchHighQuality(dest, count, tess_u, tess_v, patch, origVertType);
|
||||
_BezierPatchHighQuality(dest, indices, count, tess_u, tess_v, patch, origVertType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,8 @@ struct BezierPatch {
|
||||
// These are used to generate UVs.
|
||||
int u_index, v_index;
|
||||
|
||||
int index;
|
||||
|
||||
// Interpolate colors between control points (bilinear, should be good enough).
|
||||
void sampleColor(float u, float v, u8 color[4]) const {
|
||||
u *= 3.0f;
|
||||
@@ -161,5 +163,5 @@ enum quality {
|
||||
HIGH_QUALITY = 2,
|
||||
};
|
||||
|
||||
void TesselateSplinePatch(u8 *&dest, int &count, const SplinePatchLocal &spatch, u32 origVertType);
|
||||
void TesselateBezierPatch(u8 *&dest, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType);
|
||||
void TesselateSplinePatch(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch, u32 origVertType);
|
||||
void TesselateBezierPatch(u8 *&dest, u16 *&indices, int &count, int tess_u, int tess_v, const BezierPatch &patch, u32 origVertType);
|
||||
@@ -83,7 +83,7 @@ void TransformDrawEngineDX9::SubmitSpline(void* control_points, void* indices, i
|
||||
patch.count_v = count_v;
|
||||
patch.points = points;
|
||||
|
||||
TesselateSplinePatch(dest, count, patch, origVertType);
|
||||
TesselateSplinePatch(dest, quadIndices_, count, patch, origVertType);
|
||||
|
||||
delete[] points;
|
||||
|
||||
@@ -173,9 +173,10 @@ void TransformDrawEngineDX9::SubmitBezier(void* control_points, void* indices, i
|
||||
if (tess_u < 4) tess_u = 4;
|
||||
if (tess_v < 4) tess_v = 4;
|
||||
|
||||
u16 *inds = quadIndices_;
|
||||
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
|
||||
BezierPatch& patch = patches[patch_idx];
|
||||
TesselateBezierPatch(dest, count, tess_u, tess_v, patch, origVertType);
|
||||
TesselateBezierPatch(dest, inds, count, tess_u, tess_v, patch, origVertType);
|
||||
}
|
||||
delete[] patches;
|
||||
|
||||
|
||||
+6
-6
@@ -82,7 +82,7 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
patch.count_v = count_v;
|
||||
patch.points = points;
|
||||
|
||||
TesselateSplinePatch(dest, count, patch, origVertType);
|
||||
TesselateSplinePatch(dest, quadIndices_, count, patch, origVertType);
|
||||
|
||||
delete[] points;
|
||||
|
||||
@@ -98,9 +98,8 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
gstate_c.uv.vOff = 0;
|
||||
}
|
||||
|
||||
void *quadInds = prim_type == GE_PATCHPRIM_LINES ? quadIndicesLines_ : quadIndices_;
|
||||
int bytesRead;
|
||||
SubmitPrim(decoded2, quadInds, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
|
||||
SubmitPrim(decoded2, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
|
||||
|
||||
Flush();
|
||||
|
||||
@@ -154,6 +153,7 @@ void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int
|
||||
}
|
||||
patch.u_index = patch_u * 3;
|
||||
patch.v_index = patch_v * 3;
|
||||
patch.index = patch_v * num_patches_u + patch_u;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,9 +172,10 @@ void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int
|
||||
if (tess_u < 4) tess_u = 4;
|
||||
if (tess_v < 4) tess_v = 4;
|
||||
|
||||
u16 *inds = quadIndices_;
|
||||
for (int patch_idx = 0; patch_idx < num_patches_u*num_patches_v; ++patch_idx) {
|
||||
BezierPatch& patch = patches[patch_idx];
|
||||
TesselateBezierPatch(dest, count, tess_u, tess_v, patch, origVertType);
|
||||
TesselateBezierPatch(dest, inds, count, tess_u, tess_v, patch, origVertType);
|
||||
}
|
||||
delete[] patches;
|
||||
|
||||
@@ -190,9 +191,8 @@ void TransformDrawEngine::SubmitBezier(void* control_points, void* indices, int
|
||||
gstate_c.uv.vOff = 0;
|
||||
}
|
||||
|
||||
void *quadInds = prim_type == GE_PATCHPRIM_LINES ? quadIndicesLines_ : quadIndices_;
|
||||
int bytesRead;
|
||||
SubmitPrim(decoded2, quadInds, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
|
||||
SubmitPrim(decoded2, quadIndices_, primType[prim_type], count, vertTypeWithIndex16, &bytesRead);
|
||||
|
||||
Flush();
|
||||
|
||||
|
||||
@@ -152,15 +152,6 @@ TransformDrawEngine::TransformDrawEngine()
|
||||
quadIndices_[i * 6 + 4] = i * 4 + 2;
|
||||
quadIndices_[i * 6 + 5] = i * 4 + 3;
|
||||
}
|
||||
quadIndicesLines_ = new u16[6 * QUAD_INDICES_MAX];
|
||||
for (int i = 0; i < QUAD_INDICES_MAX; i++) {
|
||||
quadIndicesLines_[i * 6 + 0] = i * 4 + 0;
|
||||
quadIndicesLines_[i * 6 + 1] = i * 4 + 2;
|
||||
quadIndicesLines_[i * 6 + 2] = i * 4 + 1;
|
||||
quadIndicesLines_[i * 6 + 3] = i * 4 + 3;
|
||||
quadIndicesLines_[i * 6 + 4] = i * 4 + 1;
|
||||
quadIndicesLines_[i * 6 + 5] = i * 4 + 2;
|
||||
}
|
||||
|
||||
if (g_Config.bPrescaleUV) {
|
||||
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
|
||||
@@ -179,7 +170,6 @@ TransformDrawEngine::~TransformDrawEngine() {
|
||||
FreeMemoryPages(transformed, TRANSFORMED_VERTEX_BUFFER_SIZE);
|
||||
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
|
||||
delete [] quadIndices_;
|
||||
delete[] quadIndicesLines_;
|
||||
|
||||
unregister_gl_resource_holder(this);
|
||||
delete decJitCache_;
|
||||
|
||||
@@ -238,7 +238,6 @@ private:
|
||||
|
||||
// Fixed index buffer for easy quad generation from spline/bezier
|
||||
u16 *quadIndices_;
|
||||
u16 *quadIndicesLines_;
|
||||
|
||||
// Vertex buffer objects
|
||||
// Element buffer objects
|
||||
|
||||
Reference in new issue
Block a user