mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
[spline/bezier]Fix spline weights calculation and get rid of using next patch position in hwtess.
# Conflicts: # GPU/Directx9/VertexShaderGeneratorDX9.cpp # GPU/GLES/VertexShaderGeneratorGLES.cpp # GPU/Vulkan/VertexShaderGeneratorVulkan.cpp
This commit is contained in:
parent
a48a5b32f0
commit
3d07bca010
5 changed files with 50 additions and 22 deletions
|
@ -214,8 +214,8 @@ public:
|
|||
|
||||
const float inv_tess = 1.0f / (float)tess;
|
||||
for (int i = 0; i < num_patches; ++i) {
|
||||
const int _tess = (i == num_patches - 1) ? (tess + 1) : tess;
|
||||
for (int j = 0; j < _tess; ++j) {
|
||||
const int start = (i == 0) ? 0 : 1;
|
||||
for (int j = start; j <= tess; ++j) {
|
||||
const int index = i * tess + j;
|
||||
const float t = (float)index * inv_tess;
|
||||
CalcWeights(t, knots + i, divs[i], weights[index]);
|
||||
|
@ -346,9 +346,9 @@ public:
|
|||
const float inv_v = 1.0f / (float)patch.tess_v;
|
||||
|
||||
for (int patch_u = 0; patch_u < patch.num_patches_u; ++patch_u) {
|
||||
const int tess_u = patch.GetTessU(patch_u);
|
||||
const int start_u = patch.GetTessStart(patch_u);
|
||||
for (int patch_v = 0; patch_v < patch.num_patches_v; ++patch_v) {
|
||||
const int tess_v = patch.GetTessV(patch_v);
|
||||
const int start_v = patch.GetTessStart(patch_v);
|
||||
|
||||
// Prepare 4x4 control points to tessellate
|
||||
const int idx = patch.GetPointIndex(patch_u, patch_v);
|
||||
|
@ -358,7 +358,7 @@ public:
|
|||
Tessellator<Vec2f> tess_tex(tex, idx_v);
|
||||
Tessellator<Vec3f> tess_nrm(pos, idx_v);
|
||||
|
||||
for (int tile_u = 0; tile_u < tess_u; ++tile_u) {
|
||||
for (int tile_u = start_u; tile_u <= patch.tess_u; ++tile_u) {
|
||||
const int index_u = patch.GetIndexU(patch_u, tile_u);
|
||||
const Weight &wu = weights.u[index_u];
|
||||
|
||||
|
@ -371,7 +371,7 @@ public:
|
|||
if (sampleNrm)
|
||||
tess_nrm.SampleU(wu.deriv);
|
||||
|
||||
for (int tile_v = 0; tile_v < tess_v; ++tile_v) {
|
||||
for (int tile_v = start_v; tile_v <= patch.tess_v; ++tile_v) {
|
||||
const int index_v = patch.GetIndexV(patch_v, tile_v);
|
||||
const Weight &wv = weights.v[index_v];
|
||||
|
||||
|
|
|
@ -80,8 +80,7 @@ struct BezierPatch {
|
|||
}
|
||||
}
|
||||
|
||||
int GetTessU(int patch_u) const { return tess_u + 1; }
|
||||
int GetTessV(int patch_v) const { return tess_v + 1; }
|
||||
int GetTessStart(int patch) const { return 0; }
|
||||
|
||||
int GetPointIndex(int patch_u, int patch_v) const { return patch_v * 3 * count_u + patch_u * 3;}
|
||||
|
||||
|
@ -142,8 +141,7 @@ struct SplinePatchLocal {
|
|||
num_divisions_v = num_patches_v * tess_v;
|
||||
}
|
||||
|
||||
int GetTessU(int patch_u) const { return (patch_u == num_patches_u - 1) ? tess_u + 1 : tess_u; }
|
||||
int GetTessV(int patch_v) const { return (patch_v == num_patches_v - 1) ? tess_v + 1 : tess_v; }
|
||||
int GetTessStart(int patch) const { return (patch == 0) ? 0 : 1; }
|
||||
|
||||
int GetPointIndex(int patch_u, int patch_v) const { return patch_v * count_u + patch_u;}
|
||||
|
||||
|
|
|
@ -357,10 +357,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
|
|||
WRITE(p, " int2 patch_pos = int2(u, v);\n");
|
||||
WRITE(p, " int2 vertex_pos = int2(In.position.xy);\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if ((vertex_pos.x == spline_tess.x) && (u < spline_num_patches.x - 1))\n");
|
||||
WRITE(p, " u++;\n"); // Use next patch position
|
||||
WRITE(p, " if ((vertex_pos.y == spline_tess.y) && (v < spline_num_patches.y - 1))\n");
|
||||
WRITE(p, " v++;\n"); // Use next patch position
|
||||
WRITE(p, " bool2 isFirstEdge = !bool2(vertex_pos);\n"); // vertex_pos == 0
|
||||
WRITE(p, " bool2 isNotFirstPatch = bool2(patch_pos);\n"); // patch_pos > 0
|
||||
WRITE(p, " vertex_pos += patch_pos * spline_tess;\n");
|
||||
}
|
||||
// Load 4x4 control points
|
||||
|
@ -382,6 +380,12 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
|
|||
// Basis polynomials as weight coefficients
|
||||
WRITE(p, " float4 basis_u = tess_weights_u[vertex_pos.x].basis;\n");
|
||||
WRITE(p, " float4 basis_v = tess_weights_v[vertex_pos.y].basis;\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " basis_u = float4(basis_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " basis_v = float4(basis_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
// Tessellate
|
||||
WRITE(p, " float3 pos = tess_sample(_pos, basis_u, basis_v);\n");
|
||||
|
@ -401,6 +405,12 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
|
|||
// Derivatives as weight coefficients
|
||||
WRITE(p, " float4 deriv_u = tess_weights_u[vertex_pos.x].deriv;\n");
|
||||
WRITE(p, " float4 deriv_v = tess_weights_v[vertex_pos.y].deriv;\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " deriv_u = float4(deriv_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " deriv_v = float4(deriv_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " float3 du = tess_sample(_pos, deriv_u, basis_v);\n");
|
||||
WRITE(p, " float3 dv = tess_sample(_pos, basis_u, deriv_v);\n");
|
||||
|
|
|
@ -446,10 +446,8 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
|
|||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " ivec2 vertex_pos = ivec2(position.xy);\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if ((vertex_pos.x == u_spline_tess.x) && (u < u_spline_num_patches.x - 1))\n");
|
||||
WRITE(p, " u++;\n"); // Use next patch position
|
||||
WRITE(p, " if ((vertex_pos.y == u_spline_tess.y) && (v < u_spline_num_patches.y - 1))\n");
|
||||
WRITE(p, " v++;\n"); // Use next patch position
|
||||
WRITE(p, " bvec2 isFirstEdge = not(bvec2(vertex_pos));\n"); // vertex_pos == 0
|
||||
WRITE(p, " bvec2 isNotFirstPatch = bvec2(patch_pos);\n"); // patch_pos > 0
|
||||
WRITE(p, " vertex_pos += patch_pos * u_spline_tess;\n");
|
||||
}
|
||||
// Load 4x4 control points
|
||||
|
@ -470,6 +468,12 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
|
|||
// Basis polynomials as weight coefficients
|
||||
WRITE(p, " vec4 basis_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(vertex_pos.x * 2, 0)");
|
||||
WRITE(p, " vec4 basis_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(vertex_pos.y * 2, 0)");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " basis_u = vec4(basis_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " basis_v = vec4(basis_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
// Tessellate
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, basis_u, basis_v);\n");
|
||||
|
@ -489,6 +493,12 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
|
|||
// Derivatives as weight coefficients
|
||||
WRITE(p, " vec4 deriv_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(vertex_pos.x * 2 + 1, 0)");
|
||||
WRITE(p, " vec4 deriv_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(vertex_pos.y * 2 + 1, 0)");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " deriv_u = vec4(deriv_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " deriv_v = vec4(deriv_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, deriv_u, basis_v);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, basis_u, deriv_v);\n");
|
||||
|
|
|
@ -297,10 +297,8 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
|
|||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " ivec2 vertex_pos = ivec2(position.xy);\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if ((vertex_pos.x == spline_tess.x) && (u < spline_num_patches.x - 1))\n");
|
||||
WRITE(p, " u++;\n"); // Use next patch position
|
||||
WRITE(p, " if ((vertex_pos.y == spline_tess.y) && (v < spline_num_patches.y - 1))\n");
|
||||
WRITE(p, " v++;\n"); // Use next patch position
|
||||
WRITE(p, " bvec2 isFirstEdge = not(bvec2(vertex_pos));\n"); // vertex_pos == 0
|
||||
WRITE(p, " bvec2 isNotFirstPatch = bvec2(patch_pos);\n"); // patch_pos > 0
|
||||
WRITE(p, " vertex_pos += patch_pos * spline_tess;\n");
|
||||
}
|
||||
// Load 4x4 control points
|
||||
|
@ -321,6 +319,12 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
|
|||
// Basis polynomials as weight coefficients
|
||||
WRITE(p, " vec4 basis_u = tess_weights_u.data[vertex_pos.x].basis;\n");
|
||||
WRITE(p, " vec4 basis_v = tess_weights_v.data[vertex_pos.y].basis;\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " basis_u = vec4(basis_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " basis_v = vec4(basis_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
// Tessellate
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, basis_u, basis_v);\n");
|
||||
|
@ -340,6 +344,12 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
|
|||
// Derivatives as weight coefficients
|
||||
WRITE(p, " vec4 deriv_u = tess_weights_u.data[vertex_pos.x].deriv;\n");
|
||||
WRITE(p, " vec4 deriv_v = tess_weights_v.data[vertex_pos.y].deriv;\n");
|
||||
if (doSpline) {
|
||||
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
|
||||
WRITE(p, " deriv_u = vec4(deriv_u.yzw, 0);\n");
|
||||
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
|
||||
WRITE(p, " deriv_v = vec4(deriv_v.yzw, 0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, deriv_u, basis_v);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, basis_u, deriv_v);\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue