admin管理员组

文章数量:1344224

I'm trying to make a GUI:

#include <iostream>
#include "header/spgui.h"

// Declare global variables without immediate initialization.
GLuint VAO, VBO, EBO;
GLuint shaderProgram;  

struct Vertex {
    glm::vec2 position;  // (x, y)
    glm::vec2 texCoords; // (u, v)
    glm::vec4 color;     // (r, g, b, a)
};
// struct PageVertex {
//     Vertex Page;
// };
// Vector to hold all UI elements
std::vector<Widget> uiElements;


std::vector<float> vertices; // Stores position and color
std::vector<unsigned int> indices;
unsigned int indexOffset = 0; // Keeps track of the current index offset



void SWidget(const Widget& data) {
    uiElements.push_back(data);
}


void addvertices(float x, float y, float width, float height, float r, float g, float b) {
    int screenWidth, screenHeight;
    glfwGetFramebufferSize(getWindow(), &screenWidth, &screenHeight);  // Get current window size

    // Convert pixel values to normalized device coordinates (NDC)
    float xNDC = (x / screenWidth) * 2.0f - 1.0f;
    float yNDC = (y / screenHeight) * 2.0f - 1.0f;
    float widthNDC = (width / screenWidth) * 2.0f;
    float heightNDC = (height / screenHeight) * 2.0f;

    // Append vertex positions and colors
    vertices.insert(vertices.end(), {
        xNDC,          yNDC,          r, g, b,  // Bottom-left
        xNDC + widthNDC, yNDC,          r, g, b,  // Bottom-right
        xNDC + widthNDC, yNDC + heightNDC, r, g, b,  // Top-right
        xNDC,          yNDC + heightNDC, r, g, b   // Top-left
    });

    // Append indices, adjusting for the current index offset
    indices.insert(indices.end(), {
        indexOffset,     indexOffset + 1, indexOffset + 2, // First triangle
        indexOffset + 2, indexOffset + 3, indexOffset      // Second triangle
    });

    // Increase index offset by 4 since each box adds 4 new vertices
    indexOffset += 4;
}
std::array<float, 2> setAnchor(const Widget& data) {
    int screenWidth, screenHeight;
    glfwGetFramebufferSize(getWindow(), &screenWidth, &screenHeight);  

    float xAnchor = 0, yAnchor = 0;

    if (data.anchor == "center") {
        xAnchor = (screenWidth / 2.0f) - (data.width / 2.0f);
        yAnchor = (screenHeight / 2.0f) - (data.height / 2.0f);
    }

    return {xAnchor, yAnchor};
}

//Object Setup
void addBox(const Widget& data) {
    if(data.anchor != ""){
        auto [anchorX, anchorY] = setAnchor(data);  // Destructure directly
        addvertices(data.posX + anchorX, data.posY + anchorY, data.width, data.height, data.colorR, data.colorG, data.colorB);
    }else {
        addvertices(data.posX, data.posY, data.width, data.height, data.colorR, data.colorG, data.colorB);
    }
}

void setupSWidget(){
    vertices.clear();
    indices.clear();
    for (const auto& w : uiElements) {
        std::cout << "Widget: " << w.name << std::endl;

        std::string Sobject = w.object;
        if (Sobject == "box") {
            addBox(w );
        } else if (Sobject == "button") {
            // Handle case "2" if needed
        }       
    }
    //refreshBuffers();

    //std::cout << "Vertices count after setup: " << vertices.size() << ", Indices count: " << indices.size() << std::endl;

}

// void moveWidget(const std::string& widgetName, float deltaX, float deltaY) {
//     bool widgetFound = false;
//     for (auto& widget : uiElements) {
//         if (widget.name == widgetName) {
//             widget.posX += deltaX;
//             widget.posY += deltaY;
//             widgetFound = true;
//             break; // Stop searching once found
//         }
//     }

//     if (!widgetFound) {
//         std::cerr << "Warning: Widget with name '" << widgetName << "' not found!" << std::endl;
//         return;
//     }

//     // Recompute the vertices
//     setupSWidget();
    
//     // Update GPU buffers
//     refreshBuffers();
// }
// struct Object {
//     float x, y; // Position
// };

// // List of objects
// std::vector<Object> objects;

// Move a specific object
void moveWidget(int index, float dx, float dy) {
    if (index >= 0 && index < vertices.size() / 5 - 3) { // Ensure it's within bounds
        int baseIndex = index * 5; // Each vertex has 5 floats (x, y, r, g, b)

        // Move all four vertices
        vertices[baseIndex]     += dx; // Bottom-left x
        vertices[baseIndex + 5] += dx; // Bottom-right x
        vertices[baseIndex + 10] += dx; // Top-right x
        vertices[baseIndex + 15] += dx; // Top-left x

        vertices[baseIndex + 1] += dy; // Bottom-left y
        vertices[baseIndex + 6] += dy; // Bottom-right y
        vertices[baseIndex + 11] += dy; // Top-right y
        vertices[baseIndex + 16] += dy; // Top-left y
    }
}




//======================================================================================================



// Function: Check for OpenGL errors and output their location
void checkOpenGLError(const std::string& location) {
    GLenum error = glGetError();
    while (error != GL_NO_ERROR) {
        std::string errorMessage;
        switch (error) {
            case GL_INVALID_ENUM:                  errorMessage = "GL_INVALID_ENUM"; break;
            case GL_INVALID_VALUE:                 errorMessage = "GL_INVALID_VALUE"; break;
            case GL_INVALID_OPERATION:             errorMessage = "GL_INVALID_OPERATION"; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: errorMessage = "GL_INVALID_FRAMEBUFFER_OPERATION"; break;
            case GL_OUT_OF_MEMORY:                 errorMessage = "GL_OUT_OF_MEMORY"; break;
            default:                               errorMessage = "Unknown Error"; break;
        }
        std::cerr << "OpenGL Error at " << location << ": " << errorMessage << std::endl;
        error = glGetError();
    }
}

// Function: Set up shaders, buffers, and vertex attributes
void createshader() {
    // Create the shader program
    shaderProgram = glCreateProgram();

    // Vertex Shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    
    // Check for vertex shader compile errors
    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cerr << "ERROR: Vertex Shader Compilation Failed\n" << infoLog << std::endl;
    }

    // Fragment Shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    // Check for fragment shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cerr << "ERROR: Fragment Shader Compilation Failed\n" << infoLog << std::endl;
    }

    // Link Shaders to the Shader Program
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // Check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cerr << "ERROR: Shader Program Linking Failed\n" << infoLog << std::endl;
    }

    // Delete shaders as they are now linked into the program
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // Set uniform color if needed here (or in your render loop)

    // Generate VAO, VBO, and EBO
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO); // Persistent EBO

    glBindVertexArray(VAO);

    // Upload initial vertex data
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);

    // Upload initial index data
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_DYNAMIC_DRAW);


    // Define position attribute (x, y)
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // Define color attribute (r, g, b)
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // Unbind VAO (optional)
    glBindVertexArray(0);
}

// Function: Refresh buffers with the latest vertices and indices data
void refreshBuffers() {
    std::cout << "Refreshing Buffers: " << vertices.size() << " vertices, " << indices.size() << " indices." << std::endl;

    glBindVertexArray(VAO);  // Bind the VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO);  // Bind the VBO
    if (!vertices.empty()) {
        // Use offset 0 to update the entire buffer
        glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data());
        checkOpenGLError("glBufferSubData (GL_ARRAY_BUFFER)");
    } else {
        std::cerr << "Error: Vertices buffer is empty!" << std::endl;
    }

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);  // Bind the EBO
    if (!indices.empty()) {
        // Use offset 0 to update the entire buffer
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(unsigned int), indices.data());
        checkOpenGLError("glBufferSubData (GL_ELEMENT_ARRAY_BUFFER)");
    } else {
        std::cerr << "Error: Indices buffer is empty!" << std::endl;
    }

    glBindVertexArray(0);  // Unbind the VAO
}


// Function: Render UI elements
void renderUI() {
    // Bind default framebuffer (already complete, no need to check)
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    // Update vertex buffer data ONLY if needed
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data());
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Bind shader program
    glUseProgram(shaderProgram);

    // Bind VAO and EBO
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);  // Ensure the EBO is bound

    // Render UI
    glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, 0);

    // Unbind VAO (good practice)
    glBindVertexArray(0);
}


// Function: Clean up OpenGL objects
void deleteObjects() {
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);
}

...but I can't move any object without it disappearing.

When you call moveWidget(); it's supposed to move one of the objects, but its not.

本文标签: Object disappearing when trying to move it OpenGL CStack Overflow