我无法正确地为我的OpenGL圈子着色

时间:2017-07-20 08:18:56

标签: opengl g++ glfw glew

我应该绘制6种不同的2D形状(点,线,三角形,正方形,星形,圆形),并为它们分别设置不同的颜色。我设法绘制了所有这些并为它们着色,除了我的圆圈。然而,我给(g_colors_circle)圆的颜色是从圆的中心绘制但是没有到达边缘。这是当前的输出:

output

有人可以告诉我如何解决它吗?

这是我的代码:

SimpleTriangle.cpp

#include <cstdio>       // for C++ i/o
#include <iostream>
using namespace std;    // to avoid having to use std::

#define GLEW_STATIC     // include GLEW as a static library
#include <GLEW/glew.h>  // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp>  // include GLM (ideally should only use the GLM headers that are actually used)
using namespace glm;    // to avoid having to use glm::

#include "shader.h"

/*-------------------- Circle Code --------------------*/

//Constants for Circle
#define PI 3.14159265
#define MAX_SLICES 32
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3   // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 0.5

GLuint g_VBO_circle[2];             // identifiers
GLuint g_VAO_circle = 0;

//Vertices for the circle
GLfloat g_vertices_circle[MAX_VERTICES] = {
    0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f,
};

GLfloat g_colors_circle[] = {
    1.0f, 1.0f, 0.0f,
    1.0f, 1.0f, 0.0f
};

GLuint g_slices = MIN_SLICES;   // number of circle slices

//raz: i think this generates the vertice values for array of the circle
void generate_circle()
{
    float angle = PI * 2 / static_cast<float>(g_slices);    // used to generate x and y coordinates
    float scale_factor = static_cast<float>(768) / 1024;    // scale to make it a circle instead of an elipse
    int index = 0;  // vertex index

    g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor;    // set x coordinate of vertex 1

                                                    // generate vertex coordinates for triangle fan
    for (int i = 2; i < g_slices + 2; i++)
    {
        // multiply by 3 because a vertex has x, y, z coordinates
        index = i * 3;

        g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
        g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
        g_vertices_circle[index + 2] = 0.0f;

        // update to next angle
        angle += PI * 2 / static_cast<float>(g_slices);
    }
}

static void init_circle()
{
    // generate vertices of triangle fan
    generate_circle();

    // create VBO (vertice positions) and buffer the data
    glGenBuffers(2, g_VBO_circle);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_DYNAMIC_DRAW);
    // create VBO (vertice color) and buffer the data
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);

    // create VAO and specify VBO data
    glGenVertexArrays(1, &g_VAO_circle);
    glBindVertexArray(g_VAO_circle);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);  // specify the form of the data 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[1]);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);  // specify the form of the data

    glEnableVertexAttribArray(0);   // enable vertex attributes
    glEnableVertexAttribArray(1);
}

/*---------------------------------------------------------*/

// global variables
GLuint g_VBO[2];            // vertex buffer object identifier
GLuint g_VAO = 0;           // vertex array object identifier
GLuint g_shaderProgramID = 0;       // shader program identifier

static void init()
{
    glClearColor(0.0, 0.0, 0.0, 1.0);   // set clear background colour

    // create and compile our GLSL program from the shader files
    g_shaderProgramID = loadShaders("SimpleVS.vert", "SimpleFS.frag");

    // enable point size
    glEnable(GL_PROGRAM_POINT_SIZE);
    // set line width
    glLineWidth(5.0);

    GLfloat verticesPosition[] = {

        //Dot
        -0.7f, 0.7f, 0.0f,
        //Line
        -0.5f, 0.7f, 0.0f,
        -0.2f, 0.7f, 0.0f,
        //Triangle  
        0.2f, 0.75f, 0.0f,
        0.0f, 0.4f, 0.0f,
        0.4f, 0.4f, 0.0f,
        //Star 
        0.0f, 0.2f, 0.0f,
        0.1f, 0.1f, 0.0f,
        0.2f, 0.05f, 0.0f,
        0.1f, 0.0f, 0.0f,
        0.2f, -0.1f, 0.0f,
        0.0f, 0.0f, 0.0f,
        -0.2f, -0.1f, 0.0f,
        -0.1f, 0.0f, 0.0f,
        -0.2f, 0.05f, 0.0f,
        -0.1f, 0.1f, 0.0f,
        //Rectangle
        -0.8f, 0.4f, 0.0f,
        -0.8f, 0.0f, 0.0f,
        -0.3f, 0.4f, 0.0f,
        -0.3f, 0.0f, 0.0f

    };

    GLfloat verticesColor[] = {
        //Dot
        1.0f, 1.0f, 1.0f,
        //Line
        0.5f, 0.0f, 0.0f,
        0.5f, 0.0f, 0.0f,
        //Triangle
        0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f,
        //Star
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        //Rectangle
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
    };

    // create VBO and buffer the data
    glGenBuffers(2, g_VBO);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);        // bind the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesPosition), verticesPosition, GL_STATIC_DRAW);      // copy data to buffer
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);        // bind the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticesColor), verticesColor, GL_STATIC_DRAW);        // copy data to buffer

    // create VAO and specify VBO data
    glGenVertexArrays(1, &g_VAO);
    glBindVertexArray(g_VAO);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);        // bind the VBO
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);      // specify the form of the data
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);        // bind the VBO
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);      // specify the form of the data

    glEnableVertexAttribArray(0);   // enable vertex attributes
    glEnableVertexAttribArray(1);
}

// function used to render the scene
static void render_scene()
{
    glClear(GL_COLOR_BUFFER_BIT);   // clear colour buffer

    glUseProgram(g_shaderProgramID);    // use the shaders associated with the shader program

    glBindVertexArray(g_VAO);           // make VAO active

    glDrawArrays(GL_POINTS, 0, 1);          //Draw dot 
    glDrawArrays(GL_LINES, 1, 2);           //Draw line
    glDrawArrays(GL_TRIANGLES, 3, 3);       //Draw triangle
    glDrawArrays(GL_LINE_LOOP, 6, 10);      //Draw star
    glDrawArrays(GL_TRIANGLE_STRIP, 16, 4); //Draw rectangle

    glFlush();  // flush the pipeline

    //To draw circle
    glBindVertexArray(g_VAO_circle);            // make VAO for circle active
    glDrawArrays(GL_TRIANGLE_FAN, 0, g_slices + 2); // display the vertices based on the primitive type

    glFlush();  // flush the pipeline
}

// key press or release callback function
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    // quit if the ESCAPE key was press
    if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 
    {
        // set flag to close the window
        glfwSetWindowShouldClose(window, GL_TRUE);
        return;
    }
    else if (key == GLFW_KEY_W && action == GLFW_PRESS)
    {
        // renderer using wireframe
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        return;
    }
    else if (key == GLFW_KEY_S && action == GLFW_PRESS)
    {
        // renderer using wireframe
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        return;
    }
    else if (key == GLFW_KEY_UP && action == GLFW_PRESS)
    {
        if (g_slices < MAX_SLICES)
        {
            g_slices++; // increment number of slices

                        // generate vertices of triangle fan
            generate_circle();

            // bind and copy data to GPU
            glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[0]);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_DYNAMIC_DRAW);
        }
        return;
    }
    else if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
    {
        if (g_slices > MIN_SLICES)
        {
            g_slices--; // decrement number of slices

                        // generate vertices of triangle fan
            generate_circle();

            // bind and copy data to GPU
            glBindBuffer(GL_ARRAY_BUFFER, g_VBO_circle[0]);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_DYNAMIC_DRAW);
            return;
        }
    }
}

// error callback function
static void error_callback(int error, const char* description)
{
    cerr << description << endl;    // output error description
}

int main(void)
{
    GLFWwindow* window = NULL;  // pointer to a GLFW window handle

    glfwSetErrorCallback(error_callback);   // set error callback function

    // initialise GLFW
    if(!glfwInit()) 
    {
        // if failed to initialise GLFW
        exit(EXIT_FAILURE);
    }

    // minimum OpenGL version 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    // create a window and its OpenGL context
    window = glfwCreateWindow(1024, 768, "Assignment 1", NULL, NULL);

    // if failed to create window
    if(window == NULL)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window); // set window context as the current context
    glfwSwapInterval(1);            // swap buffer interval

    // initialise GLEW
    if(glewInit() != GLEW_OK) 
    {
        // if failed to initialise GLEW
        cerr << "GLEW initialisation failed" << endl;
        exit(EXIT_FAILURE);
    }

    // set key callback function
    glfwSetKeyCallback(window, key_callback);

    // initialise rendering states
    init();
    init_circle();

    // the rendering loop
    while(!glfwWindowShouldClose(window))       
    {
        render_scene();             // render the scene

        glfwSwapBuffers(window);    // swap buffers
        glfwPollEvents();           // poll for events
    }

    // clean up
    glDeleteProgram(g_shaderProgramID);
    glDeleteBuffers(1, g_VBO);
    glDeleteVertexArrays(1, &g_VAO);
    glDeleteBuffers(1, g_VBO_circle);
    glDeleteVertexArrays(1, &g_VAO_circle);

    // close the window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();

    exit(EXIT_SUCCESS);
}

SimpleVS.vert

#version 330 core

// input data (different for all executions of this shader)
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aColor;

// output data (will be interpolated for each fragment)
out vec3 vColor;        //raz: this output is passed as input to the fragment shader

void main()
{
    // set point size
    gl_PointSize = 10.0;

    // set vertex position
    gl_Position = vec4(aPosition, 1.0);

    // the color of each vertex will be interpolated
    // to produce the color of each fragment
    vColor = aColor;
}

SimpleFS.frag

#version 330 core

// interpolated values from the vertex shaders
in vec3 vColor;

// output data
out vec3 fColor;

void main()
{
    // set output color
    fColor = vColor;
}

1 个答案:

答案 0 :(得分:0)

对于圆几何体中的每个顶点,必须设置颜色属性。您用于属性缓冲区的2个数组缓冲区g_vertices_circleg_colors_circle必须具有相同数量的元素。 如果圆必须是单色的,则必须始终对颜色属性缓冲区中的每个元素使用相同的颜色。

在基元之间,属性根据其重心坐标进行插值。您确实设置了圆心和第一个外点的颜色,但没有设置其他外部点的颜色,并将它们保留为未定义(可能是黑色),这会导致您在示例中看到的效果。

为颜色属性创建缓冲区,其长度与顶点缓冲区的长度相同,并在生成顶点时填充它。 您修改后的代码应如下所示:

GLfloat g_colors_circle[MAX_VERTICES] = {
    1.0f, 1.0f, 0.0f,
    1.0f, 1.0f, 0.0f
};

for (int i = 2; i < g_slices + 2; i++)
{
    // multiply by 3 because a vertex has x, y, z coordinates
    index = i * 3;

    g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
    g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
    g_vertices_circle[index + 2] = 0.0f;

    g_colors_circle[index] = 1.0f;
    g_colors_circle[index + 1] = 1.0f;
    g_colors_circle[index + 2] = 0.0f;

    // update to next angle
    angle += PI * 2 / static_cast<float>(g_slices);
}

注意,如果您只想要单色几何体,可以省略颜色属性并通过单个统一变量设置颜色。

相关问题