opengl UI中 Flink 的对象

esbemjvw  于 7个月前  发布在  Flink
关注(0)|答案(1)|浏览(80)

我试图将两个圆锥体对象渲染到屏幕上,但屏幕有点 Flink 。它一次只显示一个圆锥体。下面是我到目前为止的代码。我按照互联网上的一些说明,人们说把glBindVertexArray(0)glfwSwapBuffers(gWindow)放在循环的末尾,而不是在每个渲染函数调用的下面。
我尝试在渲染功能和循环,但它没有工作。如果我把它们放在循环中,它只显示第二个圆锥体。如果我把它们放在Render()中,它会 Flink 。我做错了什么?

#include <iostream>         // cout, cerr
#include <cstdlib>          // EXIT_FAILURE
#include <GL/glew.h>        // GLEW library
#include <GLFW/glfw3.h>     // GLFW library

// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Cone.h" // Include the header file

using namespace std; // Standard namespace

/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif

// Unnamed namespace
namespace
{
    const char* const WINDOW_TITLE = "Thi Nguyen - Module Three Milestone"; // Macro for window title

    // Variables for window width and height
    const int WINDOW_WIDTH = 800;
    const int WINDOW_HEIGHT = 600;

    // Main GLFW window
    GLFWwindow* gWindow = nullptr;

    // Shader program
    GLuint gProgramId;
}

/* User-defined Function prototypes to:
 * initialize the program, set the window size,
 * redraw graphics on the window when resized,
 * and render graphics on the screen
 */
bool UInitialize(int, char* [], GLFWwindow** window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);

/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
    layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color;  // Color data from Vertex Attrib Pointer 1

out vec4 vertexColor; // variable to transfer color data to the fragment shader

//Global variables for the  transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates
    vertexColor = color; // references incoming color data
}
);

/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
    in vec4 vertexColor; // Variable to hold incoming color data from vertex shader

out vec4 fragmentColor;

void main()
{
    fragmentColor = vec4(vertexColor);
}
);

int main(int argc, char* argv[])
{
    if (!UInitialize(argc, argv, &gWindow))
        return EXIT_FAILURE;

    // Create the mesh

    //UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
    Cone Cone1;
    Cone1.CreateMesh();

    Cone Cone2;
    Cone2.CreateMesh();

    // Create the shader program
    if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
        return EXIT_FAILURE;

    // Sets the background color of the window to black (it will be implicitely used by glClear)
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(gWindow))
    {
        // input
        UProcessInput(gWindow);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glm::mat4 scale = glm::scale(glm::vec3(1.0f, 1.0f, 1.0f));
        glm::mat4 rotation = glm::rotate(-90.0f, glm::vec3(1.0, 1.0f, 1.0f));
        glm::mat4 translation = glm::translate(glm::vec3(1.0f, 0.0f, 0.0f));
        glm::mat4 model = translation * rotation * scale;
        glm::mat4 view = glm::translate(glm::vec3(0.0f, 0.0f, -5.0f));

        glm::mat4 scale2 = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
        glm::mat4 rotation2 = glm::rotate(0.0f, glm::vec3(1.0, 1.0f, 1.0f));
        glm::mat4 translation2 = glm::translate(glm::vec3(-1.0f, 0.0f, 0.0f));
        glm::mat4 model2 = translation2 * rotation2 * scale2;

        // Transforms the camera: move the camera back (z axis)
        glm::mat4 view2 = glm::translate(glm::vec3(0.0f, 0.0f, -5.0f));

        Cone1.Render(gWindow, gProgramId, model, view);
        Cone2.Render(gWindow, gProgramId, model2, view2);

        // unbind
        glBindVertexArray(0);
        glUseProgram(0);
        glfwSwapBuffers(gWindow);
        glfwPollEvents();
    }

    // Release shader program
    UDestroyShaderProgram(gProgramId);

    exit(EXIT_SUCCESS); // Terminates the program successfully
}

// Initialize GLFW, GLEW, and create a window
bool UInitialize(int argc, char* argv[], GLFWwindow** window)
{
    // GLFW: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // GLFW: window creation
    // ---------------------
    * window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
    if (*window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return false;
    }
    glfwMakeContextCurrent(*window);
    glfwSetFramebufferSizeCallback(*window, UResizeWindow);

    // GLEW: initialize
    // ----------------
    // Note: if using GLEW version 1.13 or earlier
    glewExperimental = GL_TRUE;
    GLenum GlewInitResult = glewInit();

    if (GLEW_OK != GlewInitResult)
    {
        std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
        return false;
    }

    // Displays GPU OpenGL version
    cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;

    return true;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
void UResizeWindow(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

// Implements the UCreateShaders function
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
    // Compilation and linkage error reporting
    int success = 0;
    char infoLog[512];

    // Create a Shader program object.
    programId = glCreateProgram();

    // Create the vertex and fragment shader objects
    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);

    // Retrive the shader source
    glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
    glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);

    // Compile the vertex shader, and print compilation errors (if any)
    glCompileShader(vertexShaderId); // compile the vertex shader
    // check for shader compile errors
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;

        return false;
    }

    glCompileShader(fragmentShaderId); // compile the fragment shader
    // check for shader compile errors
    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;

        return false;
    }

    // Attached compiled shaders to the shader program
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    glLinkProgram(programId);   // links the shader program
    // check for linking errors
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;

        return false;
    }

    glUseProgram(programId);    // Uses the shader program

    return true;
}

void UDestroyShaderProgram(GLuint programId)
{
    glDeleteProgram(programId);
}
// UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H

#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <iostream>         // cout, cerr
#include <cstdlib>          // EXIT_FAILURE
#include <GL/glew.h>        // GLEW library
#include <GLFW/glfw3.h>     // GLFW library

namespace
{
    // Stores the GL data relative to a given mesh
    struct GLMesh
    {
        GLuint vao;         // Handle for the vertex array object
        GLuint vbos[2];     // Handles for the vertex buffer objects
        GLuint nIndices;    // Number of indices of the mesh
    };
}

class Cone {
public:
    Cone();

    void CreateMesh();
    void Render(GLFWwindow* gWindow, GLuint& gProgramId, glm::mat4& modelMatrix, glm::mat4& viewMatrix);

private:
    // Member variables, if any
    GLMesh gMesh;
};

#endif // CONE_H
#include "Cone.h"
#include <GL/glew.h>
#include <glm/trigonometric.hpp>

// CTOR
Cone::Cone() {

}

void Cone::CreateMesh() {
    const int numSlices = 50; // Increase the number of slices for smoother base
    const int numVertices = numSlices + 1;
    GLfloat verts[numVertices * 7]{};

    // For the top vertex
    verts[0] = 0.0f;   // X position
    verts[1] = 1.0f;   // Y position
    verts[2] = 0.0f;   // Z position
    verts[3] = 1.0f;   // Red color
    verts[4] = 0.0f;   // Green color
    verts[5] = 0.0f;   // Blue color
    verts[6] = 1.0f;   // Alpha (transparency)

    // For the other vertices
    for (int i = 0; i < numSlices; ++i) {
        float theta = (2.0f * 3.14159265359f * float(i)) / float(numSlices);
        float x = cos(theta);
        float z = sin(theta);

        int vertexIndex = (i + 1) * 7;

        verts[vertexIndex] = x;
        verts[vertexIndex + 1] = 0.0f;
        verts[vertexIndex + 2] = z;
        verts[vertexIndex + 3] = 0.0f; // Set your desired color here (e.g., 0.0f for red, 1.0f for green, etc.)
        verts[vertexIndex + 4] = 1.0f;
        verts[vertexIndex + 5] = 0.0f;
        verts[vertexIndex + 6] = 1.0f; // Alpha
    }

    GLushort indices[numSlices * 3];
    for (int i = 0; i < numSlices; ++i) {
        indices[i * 3] = 0;
        indices[i * 3 + 1] = i + 1;
        indices[i * 3 + 2] = (i + 1) % numSlices + 1;
    }

    const GLuint floatsPerVertex = 3;
    const GLuint floatsPerColor = 4;

    glGenVertexArrays(1, &gMesh.vao); // we can also generate multiple VAOs or buffers at the same time
    glBindVertexArray(gMesh.vao);

    // Create 2 buffers: first one for the vertex data; second one for the indices
    glGenBuffers(2, gMesh.vbos);
    glBindBuffer(GL_ARRAY_BUFFER, gMesh.vbos[0]); // Activates the buffer
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU

    gMesh.nIndices = sizeof(indices) / sizeof(indices[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gMesh.vbos[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
    GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each

    // Create Vertex Attribute Pointers
    glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
    glEnableVertexAttribArray(1);
}

void Cone::Render(GLFWwindow* gWindow, GLuint& gProgramId, glm::mat4& modelMatrix, glm::mat4& viewMatrix) {
    // Enable z-depth
    glEnable(GL_DEPTH_TEST);

    // Clear the frame and z buffers
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Creates a perspective projection
    glm::mat4 projection = glm::perspective(45.0f, (GLfloat)800 / (GLfloat)600, 0.1f, 100.0f);

    // Set the shader to be used
    glUseProgram(gProgramId);

    // Retrieves and passes transform matrices to the Shader program
    GLint modelLoc = glGetUniformLocation(gProgramId, "model");
    GLint viewLoc = glGetUniformLocation(gProgramId, "view");
    GLint projLoc = glGetUniformLocation(gProgramId, "projection");

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    // Activate the VBOs contained within the mesh's VAO
    glBindVertexArray(gMesh.vao);

    // Draws the triangles
    glDrawElements(GL_TRIANGLES, gMesh.nIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);

    glfwSwapBuffers(gWindow);    // Flips the the back buffer with the front buffer every frame.
}
x6h2sr28

x6h2sr281#

互联网上的人是正确的:
glfwSwapBuffers应该只在所有内容都绘制好之后才调用。交换缓冲区会使当前状态对用户可见,如果您在中间执行此操作,则会显示半渲染图像,这会被视为 Flink 。
你只看到第二个立方体的原因是glClear应该只在帧的开始被调用,而不是在中间。由于glClear会清除后台缓冲区,因此所有已绘制的内容都将被删除。在你的代码中,在渲染第二个圆锥体时清除屏幕将删除第一个圆锥体的像素。

相关问题