我应该绘制6种不同的2D形状(点,线,三角形,正方形,星形,圆形),并为它们分别设置不同的颜色。我设法绘制了所有这些并为它们着色,除了我的圆圈。然而,我给(g_colors_circle)圆的颜色是从圆的中心绘制但是没有到达边缘。这是当前的输出:
有人可以告诉我如何解决它吗?
这是我的代码:
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;
}
答案 0 :(得分:0)
对于圆几何体中的每个顶点,必须设置颜色属性。您用于属性缓冲区的2个数组缓冲区g_vertices_circle
和g_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);
}
注意,如果您只想要单色几何体,可以省略颜色属性并通过单个统一变量设置颜色。