将 2d 曲线(带有参数法线)拉伸到 3d 时如何获得平滑的法线?

How to obtain smoothed normals when extruding a 2d curve (with parametric normals) into 3d?

我正在将正弦波曲线拉伸成 3d,但在渲染时,我可以看到法线没有平滑。

正弦波是用参数法线生成的,如下:

vector<CurvePoint> sineWave(int n, float x0, float y0, float step, float period)
{
    vector<CurvePoint> curve;

    for (int i = 0; i < n; i++) {
        float a = TWO_PI / period;
        float x = x0 + i * step;
        float y = y0 - sinf(x * a);
        float c = cosf(x * a);
        auto normal = glm::vec2(a * c, 1) / sqrtf(a * a * c * c + 1);

        curve.emplace_back(glm::vec2(x, y), normal);
    }

    return curve;
}

挤压方式:

void extrude(IndexedVertexBatch<XYZ.N> &batch, const Matrix &matrix, const vector<CurvePoint> &curve, GLenum frontFace, float distance)
{
    auto size = curve.size();
    if (size > 1 && distance != 0) {
        bool cw = ((frontFace == CW) && (distance > 0)) || ((frontFace == CCW) && (distance < 0));

        for (auto i = 0; i < size - 1; i++) {
            auto &p0 = curve[i].position;
            auto &p1 = curve[i + 1].position;
            auto normal = matrix.transformNormal(glm::vec3(curve[i].normal, 0));

            batch
                .addVertex(matrix.transformPoint(p0), normal)
                .addVertex(matrix.transformPoint(p1), normal)
                .addVertex(matrix.transformPoint(glm::vec3(p1, distance)), normal)
                .addVertex(matrix.transformPoint(glm::vec3(p0, distance)), normal);

            if (cw) {
                batch.addIndices(0, 3, 2, 2, 1, 0);
            } else {
                batch.addIndices(0, 1, 2, 2, 3, 0);
            }

            batch.incrementIndices(4);
        }
    }
}

渲染(类似 phong 的阴影):

如何获得平滑的法线?

愚蠢的我。这是挤压方法中的一个小错误,应该是这样的:

void extrude(IndexedVertexBatch<XYZ.N> &batch, const Matrix &matrix, const vector<CurvePoint> &curve, GLenum frontFace, float distance)
{
    auto size = curve.size();
    if (size > 1 && distance != 0) {
        bool cw = ((frontFace == CW) && (distance > 0)) || ((frontFace == CCW) && (distance < 0));

        for (auto i = 0; i < size - 1; i++) {
            auto &p0 = curve[i].position;
            auto &p1 = curve[i + 1].position;

            auto normal0 = matrix.transformNormal(glm::vec3(curve[i].normal, 0));
            auto normal1 = matrix.transformNormal(glm::vec3(curve[i + 1].normal, 0));

            batch
                .addVertex(matrix.transformPoint(p0), normal0)
                .addVertex(matrix.transformPoint(p1), normal1)
                .addVertex(matrix.transformPoint(glm::vec3(p1, distance)), normal1)
                .addVertex(matrix.transformPoint(glm::vec3(p0, distance)), normal0);

            if (cw) {
                batch.addIndices(0, 3, 2, 2, 1, 0);
            } else {
                batch.addIndices(0, 1, 2, 2, 3, 0);
            }

            batch.incrementIndices(4);
        }
    }
}