我在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);
}
这就是我目前所拥有的,我只需要能够旋转即可。