如何让我的 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);