尝试集成 2 个 OpenGL 程序。我的圈子没有按照我想要的方式出现在我的其他程序中
Trying to integrate 2 OpenGL programs. My circle does not appear in my other program the way I want
我正在尝试将 2 个程序集成在一起。
- 一个显示一个二维空心红色圆圈
- 另一个是3D "planet system"。 ("sun"周围有立方体moving/orbiting)
我想让红圈显示在"planet system"中。它不应该移动。我已经尝试整合代码,但圆圈并没有像我想要的那样出现。
我注意到当我取消注释这些代码部分(如下)时,圆圈出现了,但是 it moves around just like a planet。
static void init(GLFWwindow* window){
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//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[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
}
static void render_scene(){
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
}
还有,我的行星系统消失了。我很确定这与我的顶点乘以顶点着色器中的矩阵有关。如何放置圆圈而不移动它并使我的 "planets" 消失?
这是我的顶点着色器
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
这是我的主程序:
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
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)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 1.0
#define WINDOW_WIDTH 1500
#define WINDOW_HEIGHT 800
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f, // try adjusting this value to get rid of red line
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
glm::mat4 g_modelMatrix[5]; // object model matrices
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
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>(WINDOW_HEIGHT) / WINDOW_WIDTH; // 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;
//Color for edges. See Whosebug
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// enable point size
glEnable(GL_PROGRAM_POINT_SIZE);
// set line width
glLineWidth(5.0);
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
// initialise view matrix
g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//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[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
}
// function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer
glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
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(1500, 1000, "Assignment 2", 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(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
update_scene(); // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
你必须在画圆之前设置统一变量uModelViewProjectionMatrix
。
对于所有其他对象,您设置了适当的模型视图投影矩阵,但您不会为圆圈这样做。
由于圆不会移动并且没有其他位置数据,因此您只需要投影矩阵和视图矩阵。
在这种情况下,模型矩阵是单位矩阵,因此您可以跳过它。
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2);
如果你想把圆放在场景中的另一个位置,你必须为圆设置一个模型矩阵,你必须将圆的模型矩阵与视图矩阵和投影矩阵连接起来。
glm::vec3 circlePos = ....;
glm::mat4 circleModelMat = glm::translate(glm::mat4(1.0f), circlePos);
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * circleModelMat;
答案的扩展:
However, my cubes are still missing. All I can see is a static circle.
Do you know how I can get the cubes to appear as well?
您必须为两个顶点数组对象启用顶点属性:
glBindVertexArray(g_VAO[0]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// ...
glBindVertexArray(g_VAO[1]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
我正在尝试将 2 个程序集成在一起。
- 一个显示一个二维空心红色圆圈
- 另一个是3D "planet system"。 ("sun"周围有立方体moving/orbiting)
我想让红圈显示在"planet system"中。它不应该移动。我已经尝试整合代码,但圆圈并没有像我想要的那样出现。
我注意到当我取消注释这些代码部分(如下)时,圆圈出现了,但是 it moves around just like a planet。
static void init(GLFWwindow* window){
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//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[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
}
static void render_scene(){
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
}
还有,我的行星系统消失了。我很确定这与我的顶点乘以顶点着色器中的矩阵有关。如何放置圆圈而不移动它并使我的 "planets" 消失?
这是我的顶点着色器
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
这是我的主程序:
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
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)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 1.0
#define WINDOW_WIDTH 1500
#define WINDOW_HEIGHT 800
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f, // try adjusting this value to get rid of red line
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
glm::mat4 g_modelMatrix[5]; // object model matrices
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
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>(WINDOW_HEIGHT) / WINDOW_WIDTH; // 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;
//Color for edges. See Whosebug
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// enable point size
glEnable(GL_PROGRAM_POINT_SIZE);
// set line width
glLineWidth(5.0);
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
// initialise view matrix
g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//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[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
}
// function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer
glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
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(1500, 1000, "Assignment 2", 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(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
update_scene(); // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
你必须在画圆之前设置统一变量uModelViewProjectionMatrix
。
对于所有其他对象,您设置了适当的模型视图投影矩阵,但您不会为圆圈这样做。
由于圆不会移动并且没有其他位置数据,因此您只需要投影矩阵和视图矩阵。
在这种情况下,模型矩阵是单位矩阵,因此您可以跳过它。
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2);
如果你想把圆放在场景中的另一个位置,你必须为圆设置一个模型矩阵,你必须将圆的模型矩阵与视图矩阵和投影矩阵连接起来。
glm::vec3 circlePos = ....;
glm::mat4 circleModelMat = glm::translate(glm::mat4(1.0f), circlePos);
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * circleModelMat;
答案的扩展:
However, my cubes are still missing. All I can see is a static circle. Do you know how I can get the cubes to appear as well?
您必须为两个顶点数组对象启用顶点属性:
glBindVertexArray(g_VAO[0]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// ...
glBindVertexArray(g_VAO[1]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);