毛线图

时间:2019-03-04 18:14:27

标签: c++ opengl

我使用OpenGL在synthwave样式上创建了一些山脉和网格地板。在后期处理上产生的唯一影响是轻微的花开,但线条出了点问题:

当我进一步看时,线条很快开始画得很差。有时它们不是绘制的,或者只是一块。如果我旋转相机,这些线条的绘制甚至会有所不同。

如果我将相机粘贴在地板上的次数越多,情况就越糟:

An example

我尝试了几件事:禁用我的GC(NVidia)的抗锯齿,将每个滤镜纹理设置为GL_LINEAR而不是GL_NEAREST,深度缓冲区的精度为32位,而不是24位。

怎么了?

这是代码,我试图删除尽可能多的代码

init函数:

void initBase(int argc, char* argv[]) {

        YLogConsole::createInstance();

        glutInit(&argc, argv);
        glutSetOption(
            GLUT_ACTION_ON_WINDOW_CLOSE, 
            GLUT_ACTION_GLUTMAINLOOP_RETURNS
        );

        glutInitWindowSize(BaseWidth, BaseHeight);
        glutInitWindowPosition(0, 0);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

        YLog::log(YLog::ENGINE_INFO, (toString(argc) + " arguments en ligne de commande.").c_str());
        FullScreen = false;
        for (int i = 0; i<argc; i++)
        {
            if (argv[i][0] == 'f')
            {
                YLog::log(YLog::ENGINE_INFO, "Arg f mode fullscreen.\n");
                FullScreen = true;
            }
        }

        MainWindowId = glutCreateWindow("Yocto");
        glutReshapeWindow(BaseWidth, BaseHeight);
        setFullScreen(FullScreen);

        if (MainWindowId < 1)
        {
            YLog::log(YLog::ENGINE_ERROR, "Erreur creation de la fenetre.");
            exit(EXIT_FAILURE);
        }

        GLenum glewInitResult = glewInit();
        if (glewInitResult != GLEW_OK)
        {
            YLog::log(YLog::ENGINE_ERROR, ("Erreur init glew " + std::string((char*)glewGetErrorString(glewInitResult))).c_str());
            exit(EXIT_FAILURE);
        }

        //Affichage des capacités du système
        YLog::log(YLog::ENGINE_INFO, ("OpenGL Version : " + std::string((char*)glGetString(GL_VERSION))).c_str());

        glutDisplayFunc(updateBase);
        glutReshapeFunc(resizeBase);
        glutKeyboardFunc(keyboardDown);
        glutKeyboardUpFunc(keyboardUp);
        glutSpecialFunc(specialDown);
        glutSpecialUpFunc(specialUp);
        glutMouseFunc(mouseClick);
        glutMotionFunc(mouseMoveActive);
        glutPassiveMotionFunc(mouseMovePassive);
        glutIgnoreKeyRepeat(1);

        //Initialisation du YRenderer
        Renderer = YRenderer::getInstance();
        Renderer->setRenderObjectFun(renderObjectsBase);
        Renderer->setRender2DFun(render2dBase);
        Renderer->setBackgroundColor(YColor());
        Renderer->initialise(&TimerGPURender);

        //On applique la config du YRenderer
        glViewport(0, 0, Renderer->ScreenWidth, Renderer->ScreenHeight);
        Renderer->resize(Renderer->ScreenWidth, Renderer->ScreenHeight);

        //Ecrans de jeu
        ScreenManager = new GUIScreenManager();
        uint16 x = 10;
        uint16 y = 10;
        ScreenJeu = new GUIScreen();
        ScreenStats = new GUIScreen();

        //Bouton pour afficher les params
        GUIBouton * btn = new GUIBouton();
        btn->Titre = std::string("Params");
        btn->X = x;
        btn->Y = y;
        btn->setOnClick(clickBtnParams);
        ScreenJeu->addElement(btn);

        y += btn->Height + 5;

        btn = new GUIBouton();
        btn->Titre = std::string("Stats");
        btn->X = x;
        btn->Y = y;
        btn->setOnClick(clickBtnStats);
        ScreenJeu->addElement(btn);

        y += btn->Height + 1;

        //Ecran de stats
        y = btn->Height + 15;

        LblFps = new GUILabel();
        LblFps->Text = "FPS";
        LblFps->X = x;
        LblFps->Y = y;
        LblFps->Visible = true;
        ScreenStats->addElement(LblFps);

        //Ecran de parametrage
        x = 10;
        y = 10;
        ScreenParams = new GUIScreen();

        GUIBouton * btnClose = new GUIBouton();
        btnClose->Titre = std::string("Close");
        btnClose->X = x;
        btnClose->Y = y;
        btnClose->setOnClick(clickBtnClose);
        ScreenParams->addElement(btnClose);
        ScreenStats->addElement(btnClose);

        //Ecran a rendre
        ScreenManager->setActiveScreen(ScreenJeu);

        //Init YCamera
        Renderer->Camera->setPosition(YVec3f(320, 320, 320));
        Renderer->Camera->setLookAt(YVec3f(0, 0, 0));
        Renderer->Camera->setProjectionPerspective(Instance->Fov,
            (float)Instance->Renderer->ScreenWidth / (float)Instance->Renderer->ScreenHeight,
            Instance->NearPlane, Instance->FarPlane);

        //Init YTimer
        Timer = new YTimer();

        //Chargement des shaders
        Instance->loadShaders();

        //Init pour classe fille
        init();

        //On start le temps
        Timer->start();

        YLog::log(YLog::ENGINE_INFO, "[   Yocto initialized   ]\nPress : \n - f to toggle fullscreen\n - F1 for png screen shot\n - F5 to hot-reload shaders");

    }

主循环:

void SynthEngine::renderObjects()
{
    Renderer->updateMatricesFromOgl();
    glUseProgram(shaderWorld);
    Renderer->sendMatricesToShader(shaderWorld);
    dec->getGround()->render();
}

UpdateMatriceFromOgl:

void updateMatricesFromOgl() {
            float matMvTab[16];
            glGetFloatv(GL_MODELVIEW_MATRIX, matMvTab);
            memcpy(MatMV.Mat.t, matMvTab, 16 * sizeof(float));
            MatMV.transpose();

            float matProjTab[16];
            glGetFloatv(GL_PROJECTION_MATRIX, matProjTab);
            memcpy(MatP.Mat.t, matProjTab, 16 * sizeof(float));
            MatP.transpose();

            MatMVP = MatP;
            MatMVP *= MatMV;

            MatV.createViewMatrix(Camera->Position, Camera->LookAt, Camera->UpVec);

            MatIV = MatV;
            MatIV.invert();

            MatM = MatIV;
            MatM *= MatMV;

            MatIM = MatM;
            MatIM.invert();

            MatNorm = MatM;
            MatNorm.invert();
            MatNorm.transpose();

            MatIP = MatP;
            MatIP.invert();
        }

渲染功能(VBO),textureIndex和textureCubeIndex始终为0:

void YVbo::render(GBuffer * inBuffer) {

//La stat globales
YRenderer::NbVBOFacesRendered += NbVertices / 3;

if (textureIndex)
{
    glBindTexture(GL_TEXTURE_2D, textureIndex);
}

if (textureCubeIndex)
{
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureCubeIndex);
}

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);

for (int i = 0; i<NbElements; i++)
    glEnableVertexAttribArray(i);

if (StorageMethod == PACK_BY_ELEMENT_TYPE) {
    for (int i = 0; i<NbElements; i++)
        glVertexAttribPointer(i, Elements[i].NbFloats, GL_FLOAT, GL_FALSE, 0, (void*)(Elements[i].OffsetFloats * sizeof(float)));
} else {
    for (int i = 0; i<NbElements; i++)
        glVertexAttribPointer(i, Elements[i].NbFloats, GL_FLOAT, GL_FALSE, TotalNbFloatForOneVertice * sizeof(float), (void*)(Elements[i].OffsetFloats * sizeof(float)));
}

YEngine::Instance->TimerGPURender.startAccumPeriod();
glDrawArrays(GL_TRIANGLES, 0, NbVertices);
YEngine::Instance->TimerGPURender.endAccumPeriod();

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

}

ShaderWorld的顶点着色器:

#version 400

uniform mat4 mvp;
uniform float elapsed;

layout(location = 0) in vec3 position_in;
layout(location = 1) in vec4 color_border_in;
layout(location = 2) in vec4 color_fill_in;

out VertexAttrib
{
vec4 colorFill;
vec4 colorBorder;
} vertex;

void main()
{
gl_Position = mvp * vec4(position_in, 1);
vertex.colorBorder = color_border_in;
vertex.colorFill = color_fill_in;
}

几何着色器

    #version 400

out vec4 color_border;
out vec4 color_fill;
out vec3 bary;

in VertexAttrib
{
    vec4 colorFill;
    vec4 colorBorder;
} vertex[];

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

void main()
{
    for (int i = 0; i < 3; i++)
    {
        color_border = vertex[i].colorBorder;
        color_fill = vertex[i].colorFill;
        gl_Position = gl_in[i].gl_Position;

        if (i == 0)
            bary = vec3(0, 0, 1);
        if (i == 1)
            bary = vec3(0, 1, 0);
        if (i == 2)
            bary = vec3(1, 0, 0);

        EmitVertex();
    }
    EndPrimitive();
}

片段着色器:

#version 400

in vec4 color_border;
in vec4 color_fill;
in vec3 bary;

layout (location = 0) out vec4 color;
layout (location = 1) out vec4 passColor;

float toleranceLight = 0.7;

void main()
{
    vec4 interColor;
    if ((bary.x) < 0.01 || (bary.y) < 0.01 || ((bary.z) < 0.01 && color_border.r == 0))
    {
        interColor = color_border;
    }
    else
    {
        interColor = color_fill;
    }

    if (max(interColor.r,max(interColor.g, interColor.b)) > toleranceLight)
    {
        passColor = interColor;
    }
    else
    {
        passColor = vec4(0,0,0,1);
    }
    color = interColor;
}

1 个答案:

答案 0 :(得分:0)

这里的主要问题是vec3 bary的透视插值及其布尔性质,导致在color_border和color_fill边缘周围出现伪像。考虑基于重插值的边缘和填充颜色之间的某种插值。

或者,您可以考虑映射表示边缘与填充的蒙版纹理。您需要确保生成mipmap,并在运行时将其与各向异性过滤器一起使用。

另外,在这种情况下,您根本不需要几何着色器。只需直接从顶点着色器使用gl_VertexID%3并从那里输出bary。