OpenGL南邮计算机图形学实验报告四——用键盘控制物体
计算机图形学的新题目要求
OpenGL配置参考:
南邮老前辈wonz哥的OpenGL配置(Shader.h始终不用改)、SOIL2 环境配置、GLM 环境配置
头
light.vs/light.fs/Camera.h参考上一篇实验报告
学习网站:LearnOpenGL CN
思路:
-
上一节课已经做了用键盘控制镜头
camera
,这节课用键盘控制物体就可以参考镜头的控制。
镜头camera
的位置由向量front
和right
加减来控制。
而物体我选择使用直接改变物体坐标,即x,y的值。 -
先初始化物体的坐标
ObjectPos
(0,0,0)。通过键盘来改变坐标。
然后每次循环画图的时候就按照ObjectPos
的坐标画物体即可,注意设置延迟deltaTime
和速度velocity
和灵敏度(我直接在函数里设置了)。
为了不删减功能我使用WASD控制镜头camera,用UP\DOWN\LEFT\RIGHT来控制物体。
transform = glm::translate(transform, ObjectPos);
//*
*
*
*//
void ObjectMovement(GLfloat& xPos, GLfloat& yPos,GLfloat deltaTime)
{//物体移动
GLfloat velocity =10.0f * deltaTime;//10.0f是灵敏度,也可以获取
if ( keys[GLFW_KEY_UP]) {
yPos += 1.0f * velocity;
}
if ( keys[GLFW_KEY_DOWN]) {
yPos -= 1.0f * velocity;
}
if ( keys[GLFW_KEY_LEFT]) {
xPos -= 1.0f * velocity;
}
if ( keys[GLFW_KEY_RIGHT]) {
xPos += 1.0f * velocity;
}
}
效果图如下:
话不多说上代码:
main.cpp
#include<iostream>
//GLEW
#define GLEW_STATIC
#include<GL/glew.h>
//GLFW
#include<GLFW/glfw3.h>
#include"shader.h"
#include"Camera.h"
#include"Light.h"
#include "SOIL2/SOIL2.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<glm/gtx/rotate_vector.hpp>
const GLint WIDTH = 800, HEIGTH = 600;
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);
void MouseCallback(GLFWwindow* window, double xPos, double yPos);
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffest);
void DoMovement();
void ObjectMovement(GLfloat &xPos,GLfloat &yPos,GLfloat deltaTime);
bool keys[1024];
Camera camera(glm::vec3(0.0f, 0.0f, 2.0f));
GLfloat deltaTime = 0.0f;
GLfloat lastTime = 0.0f;
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY=HEIGTH/2.0;
bool firstMouse = true;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGTH, "Learn OpenGL", nullptr, nullptr);
if (nullptr == window)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
//next two lines are for mac retina display
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback);
glfwSetCursorPosCallback(window, MouseCallback);
glfwSetScrollCallback(window, ScrollCallback);//未实现
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit())
{
std::cout << "Failed to initialise GLEW" << std::endl;
return -1;
}
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shader ourShader = Shader("res/shaders/core.vs", "res/shaders/core.fs");
Shader lightShader= Shader("res/shaders/light.vs", "res/shaders/light.fs");
Light lightModel = Light();
glm::vec3 lightPos = glm::vec3(1.0f, 1.0f, 0.0f);
glm::vec3 ObjectPos = glm::vec3(0.0f, 0.0f, 0.0f);
GLfloat vertices[] =
{
// position //color //normal
-0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
0.5f,0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
0.5f,0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
-0.5f,0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
-0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f, 0.0f,0.0f,-0.1f,
-0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
0.5f,0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
0.5f,0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
-0.5f,0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
-0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f, 0.0f,0.0f,0.1f,
-0.5f,0.5f,0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
-0.5f,0.5f,-0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
-0.5f,-0.5f,-0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
-0.5f,-0.5f,-0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
-0.5f,-0.5f,0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
-0.5f,0.5f,0.5f, 0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,
0.5f,0.5f,0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
0.5f,0.5f,-0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
0.5f,-0.5f,-0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
0.5f,-0.5f,-0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
0.5f,-0.5f,0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
0.5f,0.5f,0.5f, 1.0f,1.0f,0.0f, -1.0f,0.0f,0.0f,
-0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
0.5f,-0.5f,0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
0.5f,-0.5f,0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
-0.5f,-0.5f,0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
-0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f, 0.0f,-1.0f,0.0f,
-0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
0.5f,0.5f,0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
0.5f,0.5f,0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
-0.5f,0.5f,0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
-0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f, 0.0f,1.0f,0.0f,
};
// the data should transfer to the memory on Graphic Card
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
GLfloat currentTime = glfwGetTime();
deltaTime = currentTime - lastTime;
lastTime = currentTime;
glfwPollEvents();
DoMovement();
ObjectMovement(ObjectPos.x,ObjectPos.y, deltaTime);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glm::mat4 transform = glm::mat4(1.0f);
lightPos = glm::rotate(lightPos, glm::radians(0.1f), glm::vec3(0.0f, 0.0f, 1.0f));
transform = glm::translate(transform, lightPos);
transform = glm::scale(transform, glm::vec3(0.1f, 0.1f, 0.1f));
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(camera.GetZoom()), float(screenWidth) / float(screenHeight), 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();
lightShader.Use();
GLuint transLoc = glGetUniformLocation(lightShader.Program, "transform");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
transLoc = glGetUniformLocation(lightShader.Program, "projection");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(projection));
transLoc = glGetUniformLocation(lightShader.Program, "view");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(view));
lightModel.Draw(lightShader);
transform = glm::mat4(1.0f);
transform = glm::translate(transform, ObjectPos);//每次在ObjectPos位置画物体来达到移动
transform = glm::rotate(transform, glm::radians(90.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));
transform = glm::scale(transform, glm::vec3(0.5f, 0.5f, 0.5f));
//transform = glm::translate(transform, glm::vec3(0.1f, 0.0f,-0.8f));
ourShader.Use();
transLoc = glGetUniformLocation(ourShader.Program, "transform");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
transLoc= glGetUniformLocation(ourShader.Program, "projection");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(projection));
transLoc = glGetUniformLocation(ourShader.Program, "view");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniform3f(glGetUniformLocation(ourShader.Program, "LightPos"), lightPos.x, lightPos.y, lightPos.z);
glUniform3f(glGetUniformLocation(ourShader.Program, "ViewPos"),camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glUniform1f(glGetUniformLocation(ourShader.Program, "material.diffuse"), 0.6f);
glUniform1f(glGetUniformLocation(ourShader.Program, "material.specular"), 0.9f);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
ourShader.~Shader();
glfwTerminate();
return 0;
}
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
keys[key] = false;
}
}
void DoMovement()
{//镜头移动
if (keys[GLFW_KEY_W] ) {
camera.ProcessKeyboard(FORWARD, deltaTime);
}
if (keys[GLFW_KEY_S] ) {
camera.ProcessKeyboard(BACKWARD, deltaTime);
}
if (keys[GLFW_KEY_A] ) {
camera.ProcessKeyboard(LEFT, deltaTime);
}
if (keys[GLFW_KEY_D] ) {
camera.ProcessKeyboard(RIGHT, deltaTime);
}
}
void MouseCallback(GLFWwindow* window, double xPos, double yPos)
{
if (firstMouse)
{
lastX = xPos;
lastY = yPos;
firstMouse = false;
}
GLfloat xOffset = xPos - lastX;
GLfloat yOffset = lastY - yPos;
lastX = xPos;
lastY = yPos;
//Process the camera direction
camera.ProcessMouseMovement(xOffset, yOffset);
}
void ObjectMovement(GLfloat& xPos, GLfloat& yPos,GLfloat deltaTime)
{//物体移动
GLfloat velocity =10.0f * deltaTime;
if ( keys[GLFW_KEY_UP]) {
yPos += 1.0f * velocity;
}
if ( keys[GLFW_KEY_DOWN]) {
yPos -= 1.0f * velocity;
}
if ( keys[GLFW_KEY_LEFT]) {
xPos -= 1.0f * velocity;
}
if ( keys[GLFW_KEY_RIGHT]) {
xPos += 1.0f * velocity;
}
}
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffest)
{
}//滚轮操作暂时没写
滚轮操作可以参考wonz哥
需要在camera中添加一个函数即可