如何在OpenGL中使用着色器制作圆柱体的底部

rpppsulh  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(192)

我正在尝试使用OpenGL中的顶点和索引来制作一个圆柱体。我仍在尝试使用三角形、余弦和正弦函数构建圆柱体的底部,并对其进行渲染。但出于某种原因,它变成了一个由两个三角形组成的大三角形。有人能帮我算出圆柱体底座的正确坐标吗?或者更好的是,它协调了一个完整的圆柱体。以下是我的代码:


# include <GLglew.h>

# include <GLFWglfw3.h>

# include <iostream>

// GLM library 

# include <glm/glm.hpp>

# include <glm/gtc/matrix_transform.hpp>

# include <glm/gtc/type_ptr.hpp>

using namespace std;

int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;

// Draw Primitive(s)
void draw() {
    GLenum mode = GL_TRIANGLES;

    GLsizei indices = 6;

    glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}

// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {

    // Create Shader Object
    GLuint shaderID = glCreateShader(shaderType);
    const char* src = source.c_str();

    // Attach source code to Shader object
    glShaderSource(shaderID, 1, &src, nullptr);

    // Compile Shader
    glCompileShader(shaderID);

    // Return ID of Compiled shader
    return shaderID;
}

// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {

    // Compile vertex shader
    GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);

    // Compile fragment shader
    GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);

    // Create program object
    GLuint shaderProgram = glCreateProgram();

    // Attch vertex and fragment shaders to program object
    glAttachShader(shaderProgram, vertexShaderComp);
    glAttachShader(shaderProgram, fragmentShaderComp);

    // Link shaders to create executable
    glLinkProgram(shaderProgram);

    // Delete compiled vertex and fragment shaders
    glDeleteShader(vertexShaderComp);
    glDeleteShader(fragmentShaderComp);

    // Return Shader Program
    return shaderProgram;
}

int main(void) {

    width = 640; height = 480;

    GLFWwindow* window;

    // Initialize the library
    if (!glfwInit())
        return -1;

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    // Make the window's context current
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    if (glewInit() != GLEW_OK)
        cout << "Error!" << endl;

    GLfloat vertices[] = {

        // Triangle One
        0.0, 0.0, 0.0, // vert 0
        1.0, 0.0, 0.0,  // red

        cos(60), sin(60), 0.0, // vert 1
        0.0, 1.0, 0.0,  // green

        cos(60), -sin(60), 0.0,  // vert 2
        0.0, 0.0, 1.0,  // blue

        // Part of Triangle Two
        -cos(60), -sin(60), 0.0,  // vert 3
        1.0, 0.0, 1.0,  // purple

        // Part of Triangle Three
        -cos(60), -sin(60), 0.0, // vert 4
        0.0, 1.0, 0.0, // green

        // Part of Triangle Four
        -cos(60), sin(60), 0.0, // vert 5
        0.0, 0.0, 1.0, // blue

        // Part of Triangle Five
        -cos(60), sin(60), 0.0, // vert 6
        1.0, 0.0, 1.0, // purple

        // Part of Triangle Six
        -cos(60), sin(60), 0.0, // vert 7
        0.0, 1.0, 0.0  // green

    };

    // Define element indices 
    GLubyte indices[] = {
        0,1,2,
        0,2,3,
        0,3,4,
        0,4,5,
        0,5,6,
        0,6,7

    };

    // Enable Depth Buffer
    glEnable(GL_DEPTH_TEST);

    // Wireframe mode
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    GLuint VBO, EBO, VAO;

    glGenBuffers(1, &VBO); // Create VBO and returns ID
    glGenBuffers(1, &EBO); // Create EBO

    glGenVertexArrays(1, &VAO); // Create VAO
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO); // Select VBO and activate buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Load vertex attributes
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Load indices attributes

    // Specify attributes location and layout to GPU
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    // Color attribute location and layout
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindVertexArray(0);

    // Vertex shader source code
    string vertexShaderSource =
        "#version 330 coren"
        "layout(location = 0) in vec4 vPosition;"
        "layout(location = 1) in vec4 aColor;"
        "out vec4 oColor;"
        "uniform mat4 model;"
        "uniform mat4 view;"
        "uniform mat4 projection;"
        "void main()n"
        "{n"
        "gl_Position = projection * view * model * vPosition;"
        "oColor = aColor;"
        "}n";

    // Fragment shader source code
    string fragmentShaderSource =
        "#version 330 coren"
        "in vec4 oColor;"
        "out vec4 fragColor;"
        "void main()n"
        "{n"
        "fragColor = oColor;"
        "}n";

    // Creating Shader Program
    GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);

    while (!glfwWindowShouldClose(window)) {

        // Resize window and graphics simultaneously
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);

        // Render here
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Use Shader Program exe and select VAO before drawing
        glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes

        // Declare identity matrix 

        glm::mat4 viewMatrix(1.0f);
        glm::mat4 projectionMatrix(1.0f);

        // Initialize transforms

        //modelMatrix = glm::scale(modelMatrix, glm::vec3(1.0f, 1.0f, 1.0f));

        viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, -3.0f));
        viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(1.0f, 0.0f, 0.0f));

        projectionMatrix = glm::perspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);

        // Select uniform shader and variable
        GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
        GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
        GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");

        // Pass transform to Shader

        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
        glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));

        glBindVertexArray(VAO); // User-defined VAO must be called before draw

        for (GLuint i = 0; i < 4; i++) {

            glm::mat4 modelMatrix(1.0f);

            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));

            // Draw primitive(s)
            draw();

        }

        // Unbind Shader exe and VOA after drawing per frame
        glBindVertexArray(0); // In case different VAO will be used after
        glUseProgram(0); // In case different shader will be used after

        glBindVertexArray(VAO);

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for and process events
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
vxqlmq5t

vxqlmq5t1#

glm::perspectives视图参数的单位是弧度,而不是度。可以使用glm::radians将度数转换为弧度:

projectionMatrix = glm::perspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);

projectionMatrix = glm::perspective(glm::radians(45.0f), (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);

cossin的单位是弧度,而不是度。由于要计算圆周围的点,因此必须增加每个顶点的Angular :

GLfloat vertices[] = {
    0.0,                  0.0,                  0.0, 1.0, 0.0, 0.0,
    cos(  0 * toRadians), sin(  0 * toRadians), 0.0, 0.0, 1.0, 0.0, 
    cos( 60 * toRadians), sin( 60 * toRadians), 0.0, 0.0, 0.0, 1.0, 
    cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, 
    cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, 
    cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, 
    cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0,
    cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0
};

当然,你必须画出所有的花边。因此,指数的数量是18个,而不是6个:

void draw() {
    GLenum mode = GL_TRIANGLES;
    GLsizei indices = 18;
    glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}

相关问题