将 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);
}
}
}
我正在将正弦波曲线拉伸成 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);
}
}
}