[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:
xebra 2018-02-12 00:50:21 +09:00
parent a48a5b32f0
commit 3d07bca010
5 changed files with 50 additions and 22 deletions

View file

@ -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];

View file

@ -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;}

View file

@ -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");

View file

@ -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");

View file

@ -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");