我想不通为什么当我移动鼠标时相机不会移动。
下面是我的全部代码:
# 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>
using namespace std; // Standard namespace
/*Shader program Macro*/
# ifndef GLSL
# define GLSL(Version, Source) "#version " #Version " core \n" #Source
# endif
// Unnamed namespace
namespace
{
const char* const WINDOW_TITLE = "Tutorial 4.3"; // Macro for window title
// Variables for window width and height
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
// Stores the GL data relative to a given mesh
struct GLMesh
{
GLuint vao; // Handle for the vertex array object
GLuint vbo; // Handle for the vertex buffer object
GLuint nVertices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
// camera
//Camera gCamera(glm::vec3(0.0f, 0.0f, 0.0f));
glm::vec3 gCameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 gCameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 gCameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
float gLastX = WINDOW_WIDTH / 2.0f;
float gLastY = WINDOW_HEIGHT / 2.0f;
bool gFirstMouse = true;
// timing
float gDeltaTime = 0.0f; // time between current frame and last frame
float gLastFrame = 0.0f;
// Default camera values
float Yaw = -90.0f;
float Pitch = 0.0f;
float cameraSpeed = 2.5f;
// camera options
float MovementSpeed;
float MouseSensitivity;
float Zoom;
}
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
*/
bool UInitialize(int, char* [], GLFWwindow**window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos);
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void UCreateMesh(GLMesh& mesh);
void UDestroyMesh(GLMesh& mesh);
void URender();
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);
/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1
out vec4 vertexColor; // variable to transfer color data to the fragment shader
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates
vertexColor = color; // references incoming color data
}
);
/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
in vec4 vertexColor; // Variable to hold incoming color data from vertex shader
out vec4 fragmentColor;
void main()
{
fragmentColor = vec4(vertexColor);
}
);
int main(int argc, char* argv[])
{
if (!UInitialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh
UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
// Create the shader program
if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
return EXIT_FAILURE;
// 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);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// per-frame timing
// --------------------
float currentFrame = glfwGetTime();
gDeltaTime = currentFrame - gLastFrame;
gLastFrame = currentFrame;
// input
// -----
UProcessInput(gWindow);
// Render this frame
URender();
glfwPollEvents();
}
// Release mesh data
UDestroyMesh(gMesh);
// Release shader program
UDestroyShaderProgram(gProgramId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window
bool UInitialize(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);
# ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
# endif
// GLFW: window creation
// ---------------------
* 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;
}
glfwMakeContextCurrent(*window);
glfwSetFramebufferSizeCallback(*window, UResizeWindow);
glfwSetCursorPosCallback(*window, UMousePositionCallback);
glfwSetScrollCallback(*window, UMouseScrollCallback);
glfwSetMouseButtonCallback(*window, UMouseButtonCallback);
// tell GLFW to capture our mouse
glfwSetInputMode(*window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
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 all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float cameraOffset = cameraSpeed * gDeltaTime;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
gCameraPos += cameraOffset * gCameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
gCameraPos -= cameraOffset * gCameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
gCameraPos -= glm::normalize(glm::cross(gCameraFront, gCameraUp)) * cameraOffset;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
gCameraPos += glm::normalize(glm::cross(gCameraFront, gCameraUp)) * cameraOffset;
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
gCameraPos += cameraOffset * gCameraUp;
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
gCameraPos -= cameraOffset * gCameraUp;
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
void UResizeWindow(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos)
{
if (gFirstMouse)
{
gLastX = xpos;
gLastY = ypos;
gFirstMouse = false;
}
float xoffset = xpos - gLastX;
float yoffset = gLastY - ypos; // reversed since y-coordinates go from bottom to top
gLastX = xpos;
gLastY = ypos;
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw += xoffset;
Pitch += yoffset;
// make sure that when pitch is out of bounds, screen doesn't get flipped
if (Pitch > 89.0f)
Pitch = 89.0f;
if (Pitch < -89.0f)
Pitch = -89.0f;
// update Front, Right and Up Vectors using the updated Euler angles
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
gCameraFront = glm::normalize(front);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
cameraSpeed += yoffset;
cameraSpeed = std::fmaxf(cameraSpeed, 1);
cameraSpeed = std::fminf(cameraSpeed, 100);
}
// glfw: handle mouse button events
// --------------------------------
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
switch (button)
{
case GLFW_MOUSE_BUTTON_LEFT:
{
if (action == GLFW_PRESS)
cout << "Left mouse button pressed" << endl;
else
cout << "Left mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
{
if (action == GLFW_PRESS)
cout << "Middle mouse button pressed" << endl;
else
cout << "Middle mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_RIGHT:
{
if (action == GLFW_PRESS)
cout << "Right mouse button pressed" << endl;
else
cout << "Right mouse button released" << endl;
}
break;
default:
cout << "Unhandled mouse button event" << endl;
break;
}
}
// Function called to render a frame
void URender()
{
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. Scales the object by 2
glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
// 2. Rotates shape by 15 degrees in the x axis
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(1.0, 1.0f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// camera/view transformation
glm::mat4 view = glm::lookAt(gCameraPos, gCameraPos + gCameraFront, gCameraUp);
// Creates a perspective projection
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
// Set the shader to be used
glUseProgram(gProgramId);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.vao);
// Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, gMesh.nVertices);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame.
}
// Implements the UCreateMesh function
void UCreateMesh(GLMesh& mesh)
{
// Vertex data
GLfloat verts[] = {
// Vertex Positions // Colors (r,g,b,a)
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Vertex
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Front Bottom Right Vertex
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, // Front Bottom Left Vertex
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Vertex
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Back Bottom Right Vertex
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, // Back Bottom Left Vertex
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Vertex
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, // Back Bottom Left Vertex
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, // Front Bottom Left Vertex
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Vertex
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Back Bottom Right Vertex
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Front Bottom Right Vertex
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Back Bottom Right Vertex
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Front Bottom Right Vertex
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, // Front Bottom Left Vertex
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // Back Bottom Right Vertex
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, // Back Bottom Left Vertex
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f // Front Bottom Left Vertex
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
mesh.nVertices = sizeof(verts) / (sizeof(verts[0]) * (floatsPerVertex + floatsPerColor));
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create VBO
glGenBuffers(1, &mesh.vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
// Strides between vertex coordinates
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
}
void UDestroyMesh(GLMesh& mesh)
{
glDeleteVertexArrays(1, &mesh.vao);
glDeleteBuffers(1, &mesh.vbo);
}
// Implements the UCreateShaders function
bool UCreateShaderProgram(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);
// Retrive 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); // compile the vertex shader
// check for 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;
}
glCompileShader(fragmentShaderId); // compile the fragment shader
// check for 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);
glLinkProgram(programId); // links the shader program
// 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;
}
glUseProgram(programId); // Uses the shader program
return true;
}
void UDestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
1条答案
按热度按时间azpvetkf1#
这很傻,我花了一段时间才找到它。
float MouseSensitivity;
被声明,但没有给出默认值。因此,当我移动鼠标时,它没有输出,因为没有值。