OpenGL相机移动问题

问题描述 投票:0回答:0

我在SNHU上CS330,我很挣扎。我已经为此工作了几个小时,但似乎无法弄清楚。我一遍又一遍地查看 learnOpenGL.com,搜索了互联网,但似乎无法弄清楚如何使用 WASD 和鼠标移动来添加相机移动。如果这可能是我的问题的一部分,我的教授在基本代码和 idk 方面提供了很多帮助。并感谢指导或帮助。我在下面附上了我的代码。

#include <iostream>         // cout, cerr
#include <cstdlib>          // EXIT_FAILURE
#include <GL/glew.h>        // GLEW library
#include <GLFW/glfw3.h>     // GLFW library

// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define STB_IMAGE_IMPLEMENTATION
#include <stb-master/stb_image.h> // Image loading Utility functions

#include "meshes.h"

// Uses the standard namespace for debug output
using namespace std;

// Unnamed namespace for C++ defines //
namespace
{
    // Macro for OpenGL window title
    const char* const WINDOW_TITLE = "CS330 - Ice Cream";

    // Variables for window width and height
    const int WINDOW_WIDTH = 800;
    const int WINDOW_HEIGHT = 800;

    // Main GLFW window
    GLFWwindow* gWindow = nullptr;
    // Shader program
    GLuint gProgramId1;
    GLuint gProgramId2;
    // Texture Ids
    GLuint gTextureId;

    Meshes meshes;

    // Front Camera
    glm::vec3 cameraPos;
    glm::vec3 cameraFront;
    glm::vec3 cameraUp;

    GLuint gCurrentCameraIndex = 1;
    GLfloat gCameraZoom = 45.0f;
    GLuint gCameraOrtho = 0;

    // timing
    float deltaTime = 0.0f; // time between current frame and last frame
    float lastFrame = 0.0f;
}

// User-defined Function prototypes //
bool Initialize(int, char* [], GLFWwindow** window);
void ProcessInput(GLFWwindow* window);
void Render();
bool CreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void DestroyShaderProgram(GLuint programId);
bool CreateTexture(const char* filename, GLuint& textureId);
void DestroyTexture(GLuint textureId);

// Shader program Macro //
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif

// Vertex Shader Source Code //
const GLchar* vertexShaderSource1 = GLSL(440,
    // Load vertex data from VBO location 0
    layout(location = 0) in vec3 vertex;
// Load vertex normal data from VBO location 1
layout(location = 1) in vec3 vertexNormal;
// Load texture coordinate data from VBO location 2
layout(location = 2) in vec2 textureCoordinate;

// Output vertex normal values to fragment shader
out vec3 vs_vertexNormal;
// Output texture coordinates to fragment shader
out vec2 vs_textureCoordinate;

//Global variables for the model-view-projection
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    // Transforms vertices to clip coordinates
    gl_Position = projection * view * model * vec4(vertex, 1.0f);
    vs_textureCoordinate = textureCoordinate;
    vs_vertexNormal = vertexNormal;
}
);

// Fragment Shader Source Code //
const GLchar* fragmentShaderSource1 = GLSL(440,
    // Vertex normal from vertex shader
    in vec3 vs_vertexNormal;
// Texture coordinates from vertex shader
in vec2 vs_textureCoordinate;

// Fragment output color
out vec4 fragmentColor;

// Texture image data passed in from outside shader
uniform sampler2D uTextureBase;
uniform vec2 uvScale;
uniform bool ubHasTexture;
uniform vec4 uCustomColor;

void main()
{
    // if a texture is passed in, go ahead and use it
    if (ubHasTexture)
        fragmentColor = texture(uTextureBase, vs_textureCoordinate);// *uvScale);
    else // otherwise just use preset color
        fragmentColor = uCustomColor;
}
);

// main function. Entry point to the OpenGL program //
int main(int argc, char* argv[])
{
    if (!Initialize(argc, argv, &gWindow))
        return EXIT_FAILURE;

    // Create the mesh, send data to VBO
    meshes.CreateMeshes();

    // Create the shader program
    if (!CreateShaderProgram(vertexShaderSource1, fragmentShaderSource1, gProgramId1))
        return EXIT_FAILURE;

    // Load texture data from file
    //const char * texFilename1 = "../../resources/textures/blue_granite.jpg";
    //if (!CreateTexture(texFilename1, gTextureIdBlue))
    //{
    //  cout << "Failed to load texture " << texFilename1 << endl;
    //  return EXIT_FAILURE;
    //}

    // Activate the program that will reference the texture
    glUseProgram(gProgramId1);
    // We set the texture as texture unit 0
    glUniform1i(glGetUniformLocation(gProgramId1, "uTextureBase"), 0);

    // Sets the background color of the window to black (it will be implicitely used by glClear)
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // Set the camera parameters 
    cameraPos = glm::vec3(0.0f, .75f, 4.0f);
    cameraFront = glm::vec3(0.0f, 0.0f, -2.0f);
    cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);

    // Render loop
    while (!glfwWindowShouldClose(gWindow))
    {
        // Process keyboard input before rendering
        ProcessInput(gWindow);

        // Render this frame
        Render();

        glfwPollEvents();
    }

    // Release mesh data
    meshes.DestroyMeshes();
    // Release shader program
    DestroyShaderProgram(gProgramId1);
    // Release the textures
    //DestroyTexture(gTextureId);

    exit(EXIT_SUCCESS); // Terminates the program successfully
}

// Initialize GLFW, GLEW, and create a window //
bool Initialize(int argc, char* argv[], GLFWwindow** window)
{
    // GLFW: initialize and configure
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // GLFW: create OpenGL output window, return error if fails
    *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
    if (*window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return false;
    }

    // Set the context for the current window
    glfwMakeContextCurrent(*window);

    // GLEW: initialize
    // ----------------
    // Note: if using GLEW version 1.13 or earlier
    glewExperimental = GL_TRUE;
    GLenum GlewInitResult = glewInit();
    // If init fails, output error string, return error
    if (GLEW_OK != GlewInitResult)
    {
        std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
        return false;
    }

    // Displays GPU OpenGL version
    cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;

    return true;
}

// Process keyboard input
void ProcessInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    float cameraSpeed = static_cast<float>(2.5 * deltaTime);
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        cameraPos += cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        cameraPos -= cameraSpeed * cameraFront;
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}

// Render the next frame to the OpenGL viewport //
void Render()
{
    GLuint uHasTextureLoc;
    bool ubHasTextureVal;
    GLuint uCustomColorLoc;
    glm::mat4 scale;
    glm::mat4 rotation;
    glm::mat4 translation;
    glm::mat4 view;
    glm::mat4 projection;
    glm::mat4 model;
    GLint modelLoc;
    GLint viewLoc;
    GLint projLoc;

    // Enable z-depth
    glEnable(GL_DEPTH_TEST);

    // Clear the background
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set the current view and projection values
    view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
    projection = glm::perspective(glm::radians(gCameraZoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 1000.0f);
    //projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 1000.0f);

    // Set the program to be used
    glUseProgram(gProgramId1);

    // Get the has texture location
    uHasTextureLoc = glGetUniformLocation(gProgramId1, "ubHasTexture");
    // Get the custom color location
    uCustomColorLoc = glGetUniformLocation(gProgramId1, "uCustomColor");

    ubHasTextureVal = false;
    glUniform1i(uHasTextureLoc, ubHasTextureVal);

    // Retrieves and passes transform matrices to the Shader program
    modelLoc = glGetUniformLocation(gProgramId1, "model");
    viewLoc = glGetUniformLocation(gProgramId1, "view");
    projLoc = glGetUniformLocation(gProgramId1, "projection");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));


    // Bottom of bowl
    glBindVertexArray(meshes.gCylinderMesh.vao);

    // Set the mesh transfomation values
    scale = glm::scale(glm::vec3(0.3f, 0.08f, 0.3f));
    rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
    translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
    model = translation * rotation * scale;
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // Set the custom color before drawing
    glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.87f, 0.87f, 0.69f, 1.0f)));

    //  glDrawArrays(GL_TRIANGLE_FAN, 0, 36);       //bottom
    //  glDrawArrays(GL_TRIANGLE_FAN, 36, 72);      //top
    glDrawArrays(GL_TRIANGLE_STRIP, 72, 146);   //sides

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);

    // Bowl
    glBindVertexArray(meshes.gSphereMesh.vao);

    // Set the mesh transfomation values
    scale = glm::scale(glm::vec3(1.0f, 0.4f, 1.0f));
    rotation = glm::rotate(3.142f, glm::vec3(1.0f, 0.0f, 0.0f));
    translation = glm::translate(glm::vec3(0.0f, 0.42f, 0.0f));
    model = translation * rotation * scale;
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // Set the custom color before drawing
    glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.87f, 0.87f, 0.69f, 1.0f)));

    glDrawElements(GL_TRIANGLES, 720, GL_UNSIGNED_INT, (void*)0);

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);

    // Table
    glBindVertexArray(meshes.gPlaneMesh.vao);

    // Set the mesh transfomation values
    scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
    rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
    translation = glm::translate(glm::vec3(0.0f, -0.02f, 0.0f));
    model = translation * rotation * scale;
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // Set the custom color before drawing
    glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.43f, 0.17f, 0.01f, 1.0f)));

    glDrawElements(GL_TRIANGLES, meshes.gPlaneMesh.nIndices, GL_UNSIGNED_INT, (void*)0);

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);

    // Ice Cream scoop#1
    glBindVertexArray(meshes.gSphereMesh.vao);

    // Set the mesh transfomation values
    scale = glm::scale(glm::vec3(-0.5f, -0.25f, -0.5f));
    rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
    translation = glm::translate(glm::vec3(-0.25f, 0.5f, 0.0f));
    model = translation * rotation * scale;
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // Set the custom color before drawing
    glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.96f, 0.95f, 0.92f, 1.0f)));

    glDrawElements(GL_TRIANGLES, meshes.gSphereMesh.nIndices, GL_UNSIGNED_INT, (void*)0);

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);

    // Ice Cream scoop#2
    glBindVertexArray(meshes.gSphereMesh.vao);

    // Set the mesh transfomation values
    scale = glm::scale(glm::vec3(-0.5f, -0.25f, -0.5f));
    rotation = glm::rotate(0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
    translation = glm::translate(glm::vec3(0.25f, 0.5f, 0.0f));
    model = translation * rotation * scale;
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // Set the custom color before drawing
    glUniform4fv(uCustomColorLoc, 1, glm::value_ptr(glm::vec4(0.92f, 0.91f, 0.86f, 1.0f)));

    glDrawElements(GL_TRIANGLES, meshes.gSphereMesh.nIndices, GL_UNSIGNED_INT, (void*)0);

    // Deactivate the Vertex Array Object
    glBindVertexArray(0);


    // Flips the the back buffer with the front buffer every frame (refresh)
    glfwSwapBuffers(gWindow);
}

//****************************************************
//  const char* vtxShaderSource: vertex shader source code
//  const char* fragShaderSource: fragment shader source code
//  GLuint &programId: unique ID of program associated with shaders
//****************************************************
bool CreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
    // Compilation and linkage error reporting
    int success = 0;
    char infoLog[512];

    // Create a Shader program object.
    programId = glCreateProgram();

    // Create the vertex and fragment shader objects
    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);

    // Retrieve the shader source
    glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
    glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);

    // Compile the vertex shader, and print compilation errors (if any)
    glCompileShader(vertexShaderId);
    // Check for vertex shader compile errors
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
        return false;
    }

    // Compile the fragment shader, and print compilation errors (if any)
    glCompileShader(fragmentShaderId);
    // Check for fragment shader compile errors
    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
        return false;
    }

    // Attached compiled shaders to the shader program
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    // Links the shader program
    glLinkProgram(programId);
    // Check for linking errors
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
        return false;
    }

    // Uses the shader program
    glUseProgram(programId);

    return true;
}

// Destroy the linked shader program //
void DestroyShaderProgram(GLuint programId)
{
    glDeleteProgram(programId);
}

// Images are loaded with Y axis going down, but OpenGL's Y axis goes up, so let's flip it //
void flipImageVertically(unsigned char* image, int width, int height, int channels)
{
    for (int j = 0; j < height / 2; ++j)
    {
        int index1 = j * width * channels;
        int index2 = (height - 1 - j) * width * channels;

        for (int i = width * channels; i > 0; --i)
        {
            unsigned char tmp = image[index1];
            image[index1] = image[index2];
            image[index2] = tmp;
            ++index1;
            ++index2;
        }
    }
}

// Generate and load the texture //
bool CreateTexture(const char* filename, GLuint& textureId)
{
    /*int width, height, channels;
    unsigned char *image = stbi_load(filename, &width, &height, &channels, 0);
    if (image)
    {
        flipImageVertically(image, width, height, channels);

        glGenTextures(1, &textureId);
        glBindTexture(GL_TEXTURE_2D, textureId);

        // set the texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        if (channels == 3)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
        else if (channels == 4)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
        else
        {
            cout << "Not implemented to handle image with " << channels << " channels" << endl;
            return false;
        }

        glGenerateMipmap(GL_TEXTURE_2D);

        stbi_image_free(image);
        glBindTexture(GL_TEXTURE_2D, 0); // Unbind the texture

        return true;
    }

    // Error loading the image*/
    return false;
}

// Release the texture attached to textureId //
void DestroyTexture(GLuint textureId)
{
    glGenTextures(1, &textureId);
}

这就是我目前所拥有的,我只需要能够旋转即可。

Ice Cream

c++ visual-studio-code opengl graphics glm
© www.soinside.com 2019 - 2024. All rights reserved.