首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使许多亮起的三角形看起来很平滑

使许多亮起的三角形看起来很平滑
EN

Stack Overflow用户
提问于 2015-03-08 01:46:08
回答 1查看 240关注 0票数 0

我正在尝试创建一个程序,通过创建许多三角形来显示使用Perlin噪声的波浪状动画。

这是我的程序中重要的部分:

代码语言:javascript
复制
class OGLT9_NOISE
{
    //class for Perlin Noise (noise3d()) and Fractional Brownian Motion (fmb()) generaion
};

glm::vec3 OGLT9_GRAPHICS::getNormal(glm::vec3 a, glm::vec3 b, glm::vec3 c)
{
    return glm::normalize(glm::cross(c-a, b-a));
}

void generateTerrain(OGLT9_SHADER *oglt9Shader)
{
    static OGLT9_NOISE noise;
    static float yValue = 0;
    int terrainRes = 7;             //terrain's resolution
    float terrainSpacing = 10.0f;
    vector<glm::vec3> vertexData;
    vector<glm::vec3> normalData;
    multi_array<float, 2> terrain;

    terrain.resize(extents[1<<terrainRes][1<<terrainRes]);

    for(long z=-(1<<(terrainRes-1)); z<(1<<(terrainRes-1)); z++)
        for(long x=-(1<<(terrainRes-1)); x<(1<<(terrainRes-1)); x++)
            terrain[z+(1<<(terrainRes-1))][x+(1<<(terrainRes-1))] = (noise.fbm((double)x/16.0, yValue, (double)z/16.0, 2, 0.4, 1.2, 2.9, 1.1)/2.0+0.5)*100.0;

    for(long z=0; z<(1<<terrainRes)-1; z++)
    {
        for(long x=0; x<(1<<terrainRes)-1; x++)
        {
            vertexData.push_back(glm::vec3((float)x*terrainSpacing, terrain[z][x], (float)z*terrainSpacing));
            vertexData.push_back(glm::vec3(((float)x+1.0f)*terrainSpacing, terrain[z+1][x+1], ((float)z+1.0f)*terrainSpacing));
            vertexData.push_back(glm::vec3(((float)x+1.0f)*terrainSpacing, terrain[z][x+1], (float)z*terrainSpacing));
            vertexData.push_back(glm::vec3((float)x*terrainSpacing, terrain[z][x], (float)z*terrainSpacing));
            vertexData.push_back(glm::vec3((float)x*terrainSpacing, terrain[z+1][x], ((float)z+1.0f)*terrainSpacing));
            vertexData.push_back(glm::vec3(((float)x+1.0f)*terrainSpacing, terrain[z+1][x+1], ((float)z+1.0f)*terrainSpacing));

            normalData.push_back(getNormal(vertexData[vertexData.size()-6], vertexData[vertexData.size()-5], vertexData[vertexData.size()-4]));
            normalData.push_back(normalData[normalData.size()-1]);
            normalData.push_back(normalData[normalData.size()-2]);
            normalData.push_back(getNormal(vertexData[vertexData.size()-3], vertexData[vertexData.size()-2], vertexData[vertexData.size()-1]));
            normalData.push_back(normalData[normalData.size()-1]);
            normalData.push_back(normalData[normalData.size()-2]);
        }
    }

    glUseProgram(oglt9Shader->program);
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, vertexData.size()*3*sizeof(float), vertexData.data(), GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(0);

    glGenBuffers(1, &nbo);
    glBindBuffer(GL_ARRAY_BUFFER, nbo);
    glBufferData(GL_ARRAY_BUFFER, normalData.size()*3*sizeof(float), normalData.data(), GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    numVertices = vertexData.size()*3;
    yValue += 0.01f;
}

void render()
{
    //Clear screen and enable depth buffer
    //Create and transmit matrices and light direction to shaders

    generateTerrain(oglt9Shader);

    glDrawArrays(GL_TRIANGLES, 0, numVertices);

    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &nbo);

    //Swap buffers to window
}

我的顶点着色器..。

代码语言:javascript
复制
#version 430 core

layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec3 vNormal;

uniform mat4 mMatrix;
uniform mat4 vMatrix;
uniform mat4 pMatrix;

out vec3 fPosition;
out vec3 fNormal;

void main(void)
{
    gl_Position = pMatrix * vMatrix * mMatrix * vec4(vPosition, 1.0);
    fPosition = vPosition;
    fNormal = normalize(transpose(inverse(mat3(mMatrix))) * vNormal);
}

#version 430 core

in  vec3 fPosition;
in  vec3 fNormal;
out vec4 outColor;
uniform vec3 lightDirection;

...and片段着色器。

代码语言:javascript
复制
void main(void)
{
    vec3 rawColor = vec3(1.0);
    vec3 ambientColor = vec3(1.0, 1.0, 1.0);
    float diffuseIntensity = max(0.0, dot(fNormal, lightDirection));
    vec3 diffuseColor = diffuseIntensity * vec3(0.9, 0.9, 0.9);

    outColor = vec4(rawColor*ambientColor*diffuseColor, 1.0);
}

这是最终的图像:

那么,我该怎么做才能使三角形变得平滑,这样你就看不到这些硬边了?

EN

回答 1

Stack Overflow用户

发布于 2015-03-08 02:09:06

对每个三角形的所有3个顶点使用相同的法线。这基本上将导致平面着色,这意味着每个三角形的颜色是恒定的。

您需要的是更好地近似曲面实际法线的法线,而不是单独计算每个三角形的法线。若要获得外观平滑的曲面,需要为每个顶点设置一条法线,然后在为共享该顶点的三角形指定顶点时使用该法线。

最有效的方法是在VBO中真正存储栅格的每个顶点/法线一次。然后,可以在定义三角形时使用索引缓冲区引用顶点。这意味着您有一个包含索引的GL_ELEMENT_ARRAY_BUFFER类型的额外缓冲区,然后使用glDrawElements()进行绘制。您应该能够找到有关如何做到这一点的参考信息和教程。

要实际获得法线,一种常见的方法是对所有相邻三角形的三角形法线求平均,以计算顶点的法线。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28918003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档