如何让我的 OpenGL 立方体 "fade" 进出
How to make my OpenGL cube "fade" in and out
我的程序是动人的"planet system"。
我想让最远的行星(立方体)到 "fade" 交替从透明到完全不透明。
我知道这与调整顶点的 alpha 值有关。但是,我对混合和透明度不熟悉。
我得到了一些可以改变对象的 alpha 值的代码。我已将它集成到我的程序中,但现在我的程序一直在崩溃。谁能告诉我它为什么会崩溃以及我如何更改我的代码来让星球淡入淡出?
这是我添加到程序中的代码
GLuint g_alphaIndex; // for transparency of 4th planet
float g_alpha = 0.5f; // transparency of 4th planet
static void init(GLFWwindow* window)
{
....
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
.....
.....
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
....
}
static void render_scene()
{
......
// Object 4
glUniform1fv(g_alphaIndex, 2, &g_alpha);
......
}
/*
In Fragment shader
*/
uniform float uAlpha;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
这是我的完整程序
#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"
#include "camera.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 3.0
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 1000
// 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,
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
GLuint g_alphaIndex; // for transparency of 4th planet
glm::mat4 g_modelMatrix[5]; // planets object model matrices
glm::mat4 g_modelMatrixCircle[5];// circle model matrices
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
Camera g_camera; // camera
float g_orbitSpeed[5] = { 0.3f, 0.5f, 0.4f, 0.2f, 0.1f }; // 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
float g_alpha = 0.5f; // transparency of 4th planet
bool g_enableAnimation = true;
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
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// 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");
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
// 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);
g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = g_modelMatrixCircle[2] = g_modelMatrixCircle[3] = g_modelMatrixCircle[4] = glm::mat4(1.0f);
g_modelMatrixSubPlanets[2] = g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// 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)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------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 (planets)
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]));
// update model matrix (orbit paths ie.circles)
g_modelMatrixCircle[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) * glm::scale(glm::vec3(0.68f, 0.68f, 0.68f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f)) * glm::scale(glm::vec3(1.35f, 1.35f, 1.35f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.0f, 2.0f, 2.0f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.7f, 2.7f, 2.7f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// update model matrix (mini planets eg. moon)
g_modelMatrixSubPlanets[2] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f))
* glm::scale(glm::vec3(0.35f, 0.35f, 0.35f))
* glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixSubPlanets[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]));
}
// 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
glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity
//Circle 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[4];;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
// Circle for Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2] * g_modelMatrixSubPlanets[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, g_slices + 2); // display the vertices based on the primitive type
glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniform1fv(g_alphaIndex, 2, &g_alpha);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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
// Moon for Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * 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
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// 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;
}
// toggle animation
else if (key == GLFW_KEY_P && action == GLFW_PRESS) {
static int count = 1;
if(count % 2 == 0)
g_enableAnimation = true;
else
g_enableAnimation = false;
count++;
}
// render in perspective view
else if (key == GLFW_KEY_1 && action == GLFW_PRESS) {
cout << "Perspective-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15.0f, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1.0f));
render_scene();
}
// render from eye-level view
else if (key == GLFW_KEY_3 && action == GLFW_PRESS) {
cout << "Eye-level View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// Randomize size, orbit speed, axis rotation speed of planets
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
// Randomize planet size
g_scaleSize[1] = generateRandomFloat(0.1, 0.75);
g_scaleSize[2] = generateRandomFloat(0.1, 0.75);
g_scaleSize[3] = generateRandomFloat(0.1, 0.75);
g_scaleSize[4] = generateRandomFloat(0.1, 0.75);
// Randomize speed of rotation (on planets own axis)
g_rotationSpeed[1] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[2] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[3] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[4] = generateRandomFloat(0.1, 2.0);
// Randomize speed of rotation around sun
g_orbitSpeed[1] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[2] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[3] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[4] = generateRandomFloat(0.1, 0.7);
// Randomize offset for axis of rotation
g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5);
// Display info for each planet
cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1]
<< "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl;
cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2]
<< "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl;
cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3]
<< "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl;
cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4]
<< "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl;
cout << endl;
render_scene();
}
}
// 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(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);
glfwSetCursorPosCallback(window, cursor_position_callback);
// use sticky mode to avoid missing state changes from polling
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// use mouse to move camera, hence use disable cursor mode
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
g_camera.update(window); // update camera
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
if (g_enableAnimation) { 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);
}
片段着色器
#version 330 core
// interpolated values from the vertex shaders
in vec3 vColor;
// uniform input data
uniform float uAlpha;
// output data
out vec3 fColor;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
顶点着色器
#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;
}
在您的片段着色器中,输出颜色为 "vec3",而您将其指定为 "vec4"。
有多种方法可以调试 opengl 代码和着色器,这可能对您有所帮助。
0.after编译或linking着色器,你可以通过glGetShaderInfoLog()
得到编译结果或link结果
1.use glGetError() 获取错误代码, 包含具体的错误信息 如果错误 exists.Once 调用此函数,上下文中的错误状态将被清除。
2.out 把中间结果放到shader里,看shading计算有没有问题
在顶点着色器程序中,您已声明类型为 float
的统一 uAlpha
。
uniform float uAlpha;
您正确读取了 uAlpha
的统一位置索引:
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
你的错误是在指定统一变量的值时:
glUniform1fv(g_alphaIndex, 2, &g_alpha);
注意,glUniform1fv
的第二个参数是元素个数。
OpenGL Reference page
Khronos Group 清楚地说明了第二个参数 count
:
For the vector (glUniform*v
) commands, specifies the number of elements that are to be modified.
This should be 1 if the targeted uniform variable is not an array, and 1 or more if it is an array.
注意,您尝试设置类型为 float
的统一数组的第一个和第二个元素,
但是你只声明了一个 float
类型的统一变量。
这是未定义的行为,可能会导致崩溃。
以某种方式更改您的代码:
glUniform1fv(g_alphaIndex, 1, &g_alpha);
我的程序是动人的"planet system"。
我想让最远的行星(立方体)到 "fade" 交替从透明到完全不透明。 我知道这与调整顶点的 alpha 值有关。但是,我对混合和透明度不熟悉。
我得到了一些可以改变对象的 alpha 值的代码。我已将它集成到我的程序中,但现在我的程序一直在崩溃。谁能告诉我它为什么会崩溃以及我如何更改我的代码来让星球淡入淡出?
这是我添加到程序中的代码
GLuint g_alphaIndex; // for transparency of 4th planet
float g_alpha = 0.5f; // transparency of 4th planet
static void init(GLFWwindow* window)
{
....
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
.....
.....
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
....
}
static void render_scene()
{
......
// Object 4
glUniform1fv(g_alphaIndex, 2, &g_alpha);
......
}
/*
In Fragment shader
*/
uniform float uAlpha;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
这是我的完整程序
#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"
#include "camera.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 3.0
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 1000
// 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,
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
GLuint g_alphaIndex; // for transparency of 4th planet
glm::mat4 g_modelMatrix[5]; // planets object model matrices
glm::mat4 g_modelMatrixCircle[5];// circle model matrices
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc)
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
Camera g_camera; // camera
float g_orbitSpeed[5] = { 0.3f, 0.5f, 0.4f, 0.2f, 0.1f }; // 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
float g_alpha = 0.5f; // transparency of 4th planet
bool g_enableAnimation = true;
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
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// 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");
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
// 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);
g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = g_modelMatrixCircle[2] = g_modelMatrixCircle[3] = g_modelMatrixCircle[4] = glm::mat4(1.0f);
g_modelMatrixSubPlanets[2] = g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// set camera's projection matrix
g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));
// 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)));
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------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 (planets)
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]));
// update model matrix (orbit paths ie.circles)
g_modelMatrixCircle[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) * glm::scale(glm::vec3(0.68f, 0.68f, 0.68f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f)) * glm::scale(glm::vec3(1.35f, 1.35f, 1.35f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.0f, 2.0f, 2.0f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixCircle[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f)) * glm::scale(glm::vec3(2.7f, 2.7f, 2.7f)) * glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
// update model matrix (mini planets eg. moon)
g_modelMatrixSubPlanets[2] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f))
* glm::scale(glm::vec3(0.35f, 0.35f, 0.35f))
* glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
g_modelMatrixSubPlanets[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]));
}
// 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
glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity
//Circle 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]); // make VAO active
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//Circle 4
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[4];;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
// Circle for Object 2
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2] * g_modelMatrixSubPlanets[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, g_slices + 2); // display the vertices based on the primitive type
glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glUniform1fv(g_alphaIndex, 2, &g_alpha);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * 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
// Moon for Object 3
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * 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
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
// variables to store mouse cursor coordinates
static double previous_xpos = xpos;
static double previous_ypos = ypos;
double delta_x = xpos - previous_xpos;
double delta_y = ypos - previous_ypos;
// pass mouse movement to camera class
g_camera.updateYaw(delta_x);
g_camera.updatePitch(delta_y);
// update previous mouse coordinates
previous_xpos = xpos;
previous_ypos = ypos;
}
// 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;
}
// toggle animation
else if (key == GLFW_KEY_P && action == GLFW_PRESS) {
static int count = 1;
if(count % 2 == 0)
g_enableAnimation = true;
else
g_enableAnimation = false;
count++;
}
// render in perspective view
else if (key == GLFW_KEY_1 && action == GLFW_PRESS) {
cout << "Perspective-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// render from top view
else if (key == GLFW_KEY_2 && action == GLFW_PRESS) {
cout << "Top-View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 15.0f, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1.0f));
render_scene();
}
// render from eye-level view
else if (key == GLFW_KEY_3 && action == GLFW_PRESS) {
cout << "Eye-level View" << endl << endl;
// set camera's view matrix
g_camera.setViewMatrix(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
render_scene();
}
// Randomize size, orbit speed, axis rotation speed of planets
else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
// Randomize planet size
g_scaleSize[1] = generateRandomFloat(0.1, 0.75);
g_scaleSize[2] = generateRandomFloat(0.1, 0.75);
g_scaleSize[3] = generateRandomFloat(0.1, 0.75);
g_scaleSize[4] = generateRandomFloat(0.1, 0.75);
// Randomize speed of rotation (on planets own axis)
g_rotationSpeed[1] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[2] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[3] = generateRandomFloat(0.1, 2.0);
g_rotationSpeed[4] = generateRandomFloat(0.1, 2.0);
// Randomize speed of rotation around sun
g_orbitSpeed[1] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[2] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[3] = generateRandomFloat(0.1, 0.7);
g_orbitSpeed[4] = generateRandomFloat(0.1, 0.7);
// Randomize offset for axis of rotation
g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5);
g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5);
// Display info for each planet
cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1]
<< "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl;
cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2]
<< "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl;
cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3]
<< "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl;
cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4]
<< "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl;
cout << endl;
render_scene();
}
}
// 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(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);
glfwSetCursorPosCallback(window, cursor_position_callback);
// use sticky mode to avoid missing state changes from polling
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// use mouse to move camera, hence use disable cursor mode
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
g_camera.update(window); // update camera
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
if (g_enableAnimation) { 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);
}
片段着色器
#version 330 core
// interpolated values from the vertex shaders
in vec3 vColor;
// uniform input data
uniform float uAlpha;
// output data
out vec3 fColor;
void main()
{
// set output color
fColor = vec4(vColor, uAlpha);
}
顶点着色器
#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;
}
在您的片段着色器中,输出颜色为 "vec3",而您将其指定为 "vec4"。
有多种方法可以调试 opengl 代码和着色器,这可能对您有所帮助。
0.after编译或linking着色器,你可以通过glGetShaderInfoLog()
得到编译结果或link结果1.use glGetError() 获取错误代码, 包含具体的错误信息 如果错误 exists.Once 调用此函数,上下文中的错误状态将被清除。
2.out 把中间结果放到shader里,看shading计算有没有问题
在顶点着色器程序中,您已声明类型为 float
的统一 uAlpha
。
uniform float uAlpha;
您正确读取了 uAlpha
的统一位置索引:
g_alphaIndex = glGetUniformLocation(g_shaderProgramID, "uAlpha");
你的错误是在指定统一变量的值时:
glUniform1fv(g_alphaIndex, 2, &g_alpha);
注意,glUniform1fv
的第二个参数是元素个数。
OpenGL Reference page
Khronos Group 清楚地说明了第二个参数 count
:
For the vector (
glUniform*v
) commands, specifies the number of elements that are to be modified. This should be 1 if the targeted uniform variable is not an array, and 1 or more if it is an array.
注意,您尝试设置类型为 float
的统一数组的第一个和第二个元素,
但是你只声明了一个 float
类型的统一变量。
这是未定义的行为,可能会导致崩溃。
以某种方式更改您的代码:
glUniform1fv(g_alphaIndex, 1, &g_alpha);