使用glDrawArraysInstanced进行OpenGL Tilemap渲染的问题

时间:2018-10-18 22:21:38

标签: c++ opengl shader fragment-shader vertex-shader

我正在用c ++开发2D瓷砖地图侧滚动游戏,我使用了像openGL,openAL等这样的库。

现在我正在重做游戏的渲染部分,以便从性能方面更好地进行游戏,在我开始进行游戏之前,我已经有工作版本,但是它在每帧调用180isch draw之类的东西,这很糟糕。 / p>

因此,我决定为游戏中的每个纹理进行实例渲染(如果我在地图上使用90个纹理,我将尝试渲染90个绘制调用,但是如果纹理不在屏幕上,我将跳过它),当我接触到它并尝试渲染某些东西时,我做了一些计算,一切都应该没问题,但这不是。

if (game->data->currentWorld != 0)
{
    tileSizeX = (2.0f / tileXsideCount);
    tileSizeY = (2.0f / tileYsideCount);
    float worldXoffset = getWorldOffsetX();
    float worldYoffset = getWorldOffsetY();
    float playerXoffset = getPlayerOffsetX();
    float playerYoffset = getPlayerOffsetY();
    int tileXoffset = getTileOffsetX();
    int tileYoffset = getTileOffsetY();

    int* textRenderCount = new int[game->data->currentWorld->textureCount];

    float vertices[] =
    {
        -1 + tileSizeX, -1 + tileSizeY , 1.0f, 0.0f, 0.0f,  1.0f, 1.0f, // top right
        -1 + tileSizeX, -1, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f, // bottom right
        -1, -1, 1.0f, 0.0f, 0.0f,  0.0f, 0.0f, // bottom left
        -1, -1 + tileSizeY, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f  // top left
    };

    unsigned int indices[] = {
                    0, 1, 3, // first triangle
                    1, 2, 3  // second triangle
    };

    for (int i = 1; i < game->data->currentWorld->textureCount; i++)
    {
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);
        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        int offsetIndex = 0;

        unsigned int texture;

        if (game->data->loadedTextures[i] != NULL)
        {
            texture = game->data->loadedTextures[i];
        }
        else
        {
            std::cout << "Renderer::RenderLoop - texture not found for id: " << i << endl;
        }

        // position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // color attribute
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
        glEnableVertexAttribArray(1);
        // texture coord attribute
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);

        tempShader->use();
        glBindTexture(GL_TEXTURE_2D, texture);

        for(int x = 0; x < game->data->currentWorld->sizeX; x++)
        {
            for (int y = 0; y < game->data->currentWorld->sizeY; y++)
            {
                if (
                    x > (tileXoffset - (tileXsideCount / 2) - 1) &&
                    x < (tileXoffset + (tileXsideCount)+1) &&
                    y >(tileYoffset - (tileYsideCount / 2) - 1) &&
                    y < (tileYoffset + (tileYsideCount)+1)
                    )
                {
                    if (game->data->currentWorld->world[x][y]->id == i)
                    {
                        if (game->data->debugTiles)
                        {
                            std::cout << "For tile: x: " << x << " y: " << y;
                        }
                        float offsetX = { ((x*1.0f) - worldXoffset)*tileSizeX};
                        float offsetY = { ((y*1.0f) - worldYoffset)*tileSizeY};
                        if (game->data->debugTiles)
                        {
                            std::cout << " offset is: " << offsetX << offsetY << endl;
                            std::cout << "worldXoffset is : " << worldXoffset << endl;
                            std::cout << "worldYoffset is : " << worldYoffset << endl;
                        }
                        stringstream ss;
                        std::string indexText;
                        ss << offsetIndex;
                        indexText = ss.str();
                        tempShader->setVec2(("offset[" + indexText + "]").c_str(), offsetX, offsetY);
                        offsetIndex++;
                    }
                }
            }
        }
        if (game->data->debugTiles)
        {
            std::cout << "RenderCount for last render request:" << offsetIndex+1 <<endl;
            game->data->debugTiles = false;
        }
    glBindVertexArray(VAO);
    glDrawArraysInstanced(GL_TRIANGLES,0, 6,offsetIndex+1);
    UnloadSceneBuffers();
    }

这里是返回偏移量的函数:

float Renderer::getWorldOffsetX()
{
    if (game->data->currentChar->xPos < tileXsideCount / 2)
    {
        return 0.0f;
    }
    else if(game->data->currentChar->xPos > game->data->currentWorld->sizeX - (tileXsideCount/2))
    {
        return (game->data->currentWorld->sizeX - (tileXsideCount / 2));
    }
    else
    {
        return (game->data->currentChar->xPos - tileXsideCount/2);
    }
};


float Renderer::getWorldOffsetY()
{
    if (game->data->currentChar->yPos < tileYsideCount / 2)
    {
        return 0.0f;
    }
    else if (game->data->currentChar->yPos > game->data->currentWorld->sizeY - (tileYsideCount / 2))
    {
        return (game->data->currentWorld->sizeY - (tileYsideCount / 2));
    }
    else
    {
        return (game->data->currentChar->yPos - tileYsideCount/2);
    }
};

float Renderer::getPlayerOffsetX()
{
    if (game->data->currentChar->xPos < tileXsideCount / 2)
    {
        return -1.0f + (game->data->currentChar->xPos*tileSizeX);
    }
    else if (game->data->currentChar->xPos > game->data->currentWorld->sizeX - (tileXsideCount / 2))
    {
        return +1.0f - (tileSizeX*((game->data->currentWorld->sizeX-tileXsideCount) - game->data->currentChar->xPos));
    }
    else
    {
        return 0.0f;
    }
};

float Renderer::getPlayerOffsetY()
{
    if (game->data->currentChar->yPos < tileYsideCount / 2)
    {
        return -1.0f + (game->data->currentChar->yPos*tileSizeY);
    }
    else if (game->data->currentChar->yPos > game->data->currentWorld->sizeY - (tileYsideCount / 2))
    {
        return +1.0f - (tileSizeY*((game->data->currentWorld->sizeY - tileYsideCount) - game->data->currentChar->yPos));
    }
    else
    {
        return 0.0f;
    }
};

int Renderer::getTileOffsetX()
{
    if (game->data->currentChar->xPos < tileXsideCount / 2)
    {
        return 0 + tileXsideCount/2;
    }
    else if (game->data->currentChar->xPos > game->data->currentWorld->sizeX - (tileXsideCount / 2))
    {
        return (game->data->currentWorld->sizeX-(tileXsideCount/2));
    }
    else
    {
        return game->data->currentChar->xPos;
    }
}

int Renderer::getTileOffsetY()
{
    if (game->data->currentChar->yPos < tileYsideCount / 2)
    {
        return 0 + tileYsideCount / 2;
}
    else if (game->data->currentChar->yPos > game->data->currentWorld->sizeY -(tileYsideCount / 2))
    {
        return (game->data->currentWorld->sizeY - (tileYsideCount / 2));
    }
    else
    {
        return game->data->currentChar->yPos;
    }
}

这是我的着色器:

顶点:

#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;

out vec2 TexCoord;

uniform vec2 offset[198];

void main()
{
    vec2 currentOffset = offset[gl_InstanceID];
    gl_Position = vec4(aPos + currentOffset,0.0f,1.0f);
    TexCoord = aTexCoord;
}

片段:

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;

void main()
{
    FragColor = texture(ourTexture, TexCoord);
}

这是我的着色器设置vec2函数(其功能与learnopengl.com上的相同):

void setVec2(const std::string &name, float input1,float input2)
{
    glUniform2f(glGetUniformLocation(ID, name.c_str()), input1,input2);
}

编辑: 这是我看到的:

enter image description here

0 个答案:

没有答案