这篇文章是参考教程点击打开链接 摄像机一节 我觉得这个教程非常好所以把上面的例程都在本地实现
下面是教程的第一部分,箱子旋转,摄像机不动。具体原理教程里很清楚。这里是我实现的代码 着色器程序代码 在源码链接点击打开链接 里面的文件夹shader6中
头文件shader.h camera.h下面是shader.h的内容 前面的 文章相同
#ifndef SHADER_H
#define SHADER_H
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<GL/glew.h>
using namespace std;
class Shader
{
public:
//程序的ID
GLuint Program;
//读取渲染程序并创建Shader
Shader(const GLchar * vertexSourcePath,const GLchar *fragmentSource);
{
//1.从文件路径获得vertex/fragment源码
string vertexCode;
string fragmentCode;
try{
//打开文件Open files
ifstream vShaderFile(vertexPath);
ifstream fShaderFile(fragmentPath);
stringstream vShaderStream,fShaderStream;
//读取文件缓冲到流、
vShaderStream<<vShaderFile.rdbuf();
fShaderStream<<fShaderFile.rdbuf();
//关闭文件句柄
vShaderFile.close();
fShaderFile.close();
//将流转为GLchar数组
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::exception e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar * fShaderCode = fragmentCode.c_str();
// 2.编译着色器
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// 顶点着色器
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// 打印着色器是否错误
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 片段着色器
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// 打印是否有任何错误
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 着色器程序
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// 打印是否有错误
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// 删除着色器程序
glDeleteShader(vertex);
glDeleteShader(fragment);
}
//使用Program
void Use();
{
glUseProgram(this->Program);
}
}
#endif
下面是camera.h的代码
#pragma once
#include<vector>
//GL 包含
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
//定义几个可能关于摄像机移动的操作,利用这个抽象的去保存window系统的几种输入
enum Camera_Movement
{
FORWARD,
BACKWARD,
LEFT,
RIGHT
};
//默认的摄像机的数值
onst GLfloat YAW = -90.0f;//左右移动的角度
const GLfloat PITCH = 0.0f;//上下移动的角度
const GLfloat SPEED = 3.0f;//速度
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f;//放大
//一个抽象的摄像机的类,这个处理输入和计算欧文角度,opengl的向量和矩阵来使用
class Camera
{
public:
// Camera Attributes 照相机的属性
glm::vec3 Position;//位置
glm::vec3 Front;//方向
glm::vec3 Up;//上向量
glm::vec3 Right;//右向量
glm::vec3 WorldUp;//世界坐标的上向量
// Eular Angles 欧文角度
GLfloat Yaw;//左右的角度
GLfloat Pitch;//上下的角度
// Camera options 摄像机的操作
GLfloat MovementSpeed; //移动的速度
GLfloat MouseSensitivity;//鼠标的感应位置
GLfloat Zoom;//放大
// Constructor with vectors 构建向量
Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, GLfloat pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
{
this->Position = position;
this->WorldUp = up;
this->Yaw = yaw;
this->Pitch = pitch;
this->updateCameraVectors(); //更新相机的向量
}
// Constructor with scalar values 构建标量值
Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
{
this->Position = glm::vec3(posX, posY, posZ);
this->WorldUp = glm::vec3(upX, upY, upZ);
this->Yaw = yaw;
this->Pitch = pitch;
this->updateCameraVectors();
}
// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
//返回通过欧文角度计算的视图矩阵和lookat矩阵
glm::mat4 GetViewMatrix()
{
return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
}
// Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowingsystems)
//处理输入的按键
void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
{
GLfloat velocity = this->MovementSpeed * deltaTime; //使更新后变化相同
if (direction == FORWARD)
this->Position += this->Front * velocity;
if (direction == BACKWARD)
this->Position -= this->Front * velocity;
if (direction == LEFT)
this->Position -= this->Right * velocity;
if (direction == RIGHT)
this->Position += this->Right * velocity;
}
// Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
//把鼠标系统输入处理成标准的输入 ,期望x和y的方向,x和y的值被抵消 鼠标控制物体的旋转
void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, constrainPitch = true)
{
xoffset *= this->MouseSensitivity;
yoffset *= this->MouseSensitivity;
this->Yaw += xoffset;
this->Pitch += yoffset;
// Make sure that when pitch is out of bounds, screen doesn't get flipped
//确定当pitch(倾斜)超过边界屏幕是不过翻转
if (constrainPitch)
{
if (this->Pitch > 89.0f)
this->Pitch = 89.0f;
if (this->Pitch < -89.0f)
this->Pitch = -89.0f;
}
// Update Front, Right and Up Vectors using the updated Eular angles
//更新前面,右边和上边的向量 用来更新欧文角度
this->updateCameraVectors();
}
// Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
//处理输入的放大和缩小,仅要求顶点轴转动
void ProcessMouseScroll(GLfloat yoffset)
{
if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
this->Zoom -= yoffset;
if (this->Zoom <= 1.0f)
this->Zoom = 1.0f;
if (this->Zoom >= 45.0f)
this->Zoom = 45.0f;
}
private:
// Calculates the front vector from the Camera's (updated) Eular Angles
//计算方向向量从摄像机更新后的欧文角度
void updateCameraVectors()
{
// Calculate the new Front vector 计算新的方向向量
glm::vec3 front;
front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
front.y = sin(glm::radians(this->Pitch));
front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
this->Front = glm::normalize(front);
// Also re-calculate the Right and Up vector 重新计算右向量和上向量
this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp)); // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
this->Up = glm::normalize(glm::cross(this->Right, this->Front));
}
};
下面是camera..cpp 实现的是物品的旋转,然后摄像机不动
//自动摄像机旋转
#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other Libs
#include <FreeImage.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other includes
#include <Shader.h>
// Function prototypes 函数的原型
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
// Window dimensions windows的尺寸
const GLuint WIDTH = 800, HEIGHT = 600;
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW 初始化
glfwInit();
// Set all the required options for GLFW 设置GLFW要求设置的选项
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);
// Create a GLFWwindow object that we can use for GLFW's functions 创造一个GLFW窗口 对象这样我们利用GLFW的功能
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set the required callback functions 建立回调函数
glfwSetKeyCallback(window, key_callback);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers 初始化GLEW去设置opengl的指针功能呢
glewInit();
// Define the viewport dimensions 定义视图的尺寸
glViewport(0, 0, WIDTH, HEIGHT);
glEnable(GL_DEPTH_TEST); //开启深度测试
// Build and compile our shader program 构建和编译我们的渲染程序
Shader ourShader("D:/C语言/openglflew/shader6/shader.vs", "D:/C语言/openglflew/shader6/shader.frag");
// Set up vertex data (and buffer(s)) and attribute pointers 建立顶点数据和属性指针
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
//创建 VBO,VAO
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Position attribute 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// TexCoord attribute 纹理属性
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Unbind VAO 解绑VAO
// Load, create texture and generate mipmaps 加载,创建纹理并且形成译码
//image format
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt;
int width, height;
FIBITMAP *dib(0);
//1 获取图片格式
fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt))
dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
//if the image failed to load, return failure
if(!dib)
cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);
//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
width = FreeImage_GetWidth(dib);
height = FreeImage_GetHeight(dib);
cout<<"width:"<<width<<endl;
cout<<"height:"<<height<<endl;
///----------------------------------------加载第二个纹理图片----
FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt1;
int width1, height1;
FIBITMAP *dib1(0);
//1 获取图片格式
fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt1))
dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
//if the image failed to load, return failure
if(!dib1)
cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);
//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
width1 = FreeImage_GetWidth(dib1);
height1 = FreeImage_GetHeight(dib1);
cout<<"width1:"<<width1<<endl;
cout<<"height1:"<<height1<<endl;
// Load and create a texture 加载和创建纹理
GLuint texture1;
GLuint texture2;
// ====================
// Texture 1 纹理1
// ====================
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
// Set our texture parameters 设置我们的纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering 设置纹理过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load, create texture and generate mipmaps
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
// ===================
// Texture 2
// ===================
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load, create texture and generate mipmaps
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Game loop
while (!glfwWindowShouldClose(window))
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
// Render 渲染
// Clear the colorbuffer 清楚颜色缓存和深度缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind Textures using texture units 帮点纹理使用的的纹理单元
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
// Activate shader
ourShader.Use();
// Camera/View transformation 相机/视图 变换
glm::mat4 view; //设置视图
//我们每一帧都创建x轴坐标和z轴坐标,这要使用一个点的三角形的知识,
//x和y表示一个在一个圆圈上的一点,我们会使用它作为摄像机机的位置,通过计算x和z的坐标
//便利所有圆圈上的点,这样摄像机就会绕场景旋转了。我们预先定义这个圆的半径,使用
//glfwGetTime函数不断增加它的值,每次循环创建迭代创建新的视图矩阵
GLfloat radius = 10.0f;
GLfloat camX = sin(glfwGetTime()) * radius;
GLfloat camZ = cos(glfwGetTime()) * radius;
//我们定义一个相机的位置,一个目标位置和一个表示上向量的世界空间中的向量(我们用上向量计算右向量)。接种GLM
//就会创建一个LookAt矩阵,我们可以可以把它当作我们的视图矩阵
view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// Projection 投影
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
// Get the uniform locations 得到uniform位置
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
// Pass the matrices to the shader 通过矩阵把数据传给着色器
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
for (GLuint i = 0; i < 10; i++)
{
// Calculate the model matrix for each object and pass it to shader before drawing计算每个对象的矩阵并且把它传给着色器
glm::mat4 model;
model = glm::translate(model, cubePositions[i]);
GLfloat angle = 20.0f * i;
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
//清除
FreeImage_Unload(dib);
FreeImage_DeInitialise();
FreeImage_Unload(dib1);
FreeImage_DeInitialise();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
可以把camera.cpp更换 头文件不变实现教程其他的内容 我这里是camera1.cpp实现按键控制摄像机移动 按键wasd分别实现前左后右的移动
camera1.cpp代码
//按键移动摄像机
#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other Libs
#include <FreeImage.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other includes
#include <Shader.h>
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void do_movement();
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// Camera 相机
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); //相机位置
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); //相机的方向
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);//相机上向量
bool keys[1024];
// Deltatime 处理时间 因为不同的设备可能处理能力不一样绘制的时间也不一样导致速度不一样,为了解决这个问题
//图形和游戏应用通常有回跟踪一个deltaTime变量,它储存渲染上一帧所用的时间。
//我们把所有速度都去乘以deltaTime值。当我们的deltaTime变大时意味着上一帧渲染花了更多时间,所以这一帧使用这个更大的deltaTime的值乘以速度,会获得更高的速度,这样就与上一帧平衡了。使用这种方法时,
//无论你的机器快还是慢,摄像机的速度都会保持一致,这样每个用户的体验就都一样了。
GLfloat deltaTime = 0.0f; // Time between current frame and last frame 当前帧和上一个帧的时间差
GLfloat lastFrame = 0.0f; // Time of last frame 上次帧的时间
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW
glfwInit();
// Set all the required options for GLFW
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);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
glewInit();
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
glEnable(GL_DEPTH_TEST);
// Build and compile our shader program
Shader ourShader("D:/C语言/openglflew/shader6/shader.vs", "D:/C语言/openglflew/shader6/shader.frag");
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// TexCoord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Unbind VAO
// Load, create texture and generate mipmaps 加载,创建纹理并且形成译码
//image format
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt;
int width, height;
FIBITMAP *dib(0);
//1 获取图片格式
fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt))
dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
//if the image failed to load, return failure
if(!dib)
cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);
//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
width = FreeImage_GetWidth(dib);
height = FreeImage_GetHeight(dib);
cout<<"width:"<<width<<endl;
cout<<"height:"<<height<<endl;
///----------------------------------------加载第二个纹理图片----
FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt1;
int width1, height1;
FIBITMAP *dib1(0);
//1 获取图片格式
fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt1))
dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
//if the image failed to load, return failure
if(!dib1)
cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);
//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
width1 = FreeImage_GetWidth(dib1);
height1 = FreeImage_GetHeight(dib1);
cout<<"width1:"<<width1<<endl;
cout<<"height1:"<<height1<<endl;
// Load and create a texture
GLuint texture1;
GLuint texture2;
// ====================
// Texture 1
// ====================
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load, create texture and generate mipmaps
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
// ===================
// Texture 2
// ===================
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Load, create texture and generate mipmaps
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Game loop
while (!glfwWindowShouldClose(window))
{
// Calculate deltatime of current frame 计算当前图形处理时间
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
do_movement();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind Textures using texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
// Activate shader
ourShader.Use();
// Camera/View transformation
glm::mat4 view;
//首先我们设置之前定义的的camepos为摄像机的位置,方向(direction)是当前的位置
//加上我们刚刚定义的方向向量,这样保证无论我们这么移动,摄像机都都注视着目标我
//在按下某个按钮时更新camerapos向量
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
// Projection
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
// Get the uniform locations
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
// Pass the matrices to the shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
for (GLuint i = 0; i < 10; i++)
{
// Calculate the model matrix for each object and pass it to shader before drawing
glm::mat4 model;
model = glm::translate(model, cubePositions[i]);
GLfloat angle = 20.0f * i;
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
//清除
FreeImage_Unload(dib);
FreeImage_DeInitialise();
FreeImage_Unload(dib1);
FreeImage_DeInitialise();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(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 do_movement()
{
// Camera controls
GLfloat cameraSpeed = 2.5f*deltaTime;
if (keys[GLFW_KEY_W]) //向前一定位置向量加上方向向量
cameraPos += cameraSpeed * cameraFront;
if (keys[GLFW_KEY_S])
cameraPos -= cameraSpeed * cameraFront;
if (keys[GLFW_KEY_A])//对尤向亮进行了标准化,用叉乘求出右向量
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (keys[GLFW_KEY_D])
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
camera2.cpp在camera1的基础上加入了鼠标对摄像机拍摄方向的控制,焦点被锁定在窗口中,可能无法退出,可以按 window+d 直接回到主桌面
//鼠标控制移动物体
#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other Libs
#include <FreeImage.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other includes
#include <Shader.h>
// Function prototypes 函数的原型
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); //键盘
void mouse_callback(GLFWwindow* window, double xpos, double ypos);//监听鼠标的移动时间
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void do_movement();//具体键盘的那个按键
// Window dimensions 窗口的尺寸大小
const GLuint WIDTH = 800, HEIGHT = 600;
// Camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); //位置
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);//方向
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);//上向量
GLfloat yaw = -90.0f;
// Yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right (due to how Eular angles work) so we initially rotate a bit to the left.
//Yaw 是被初始化为-90.0度因为一个yaw 为0.0会导致一个方向向量指向右边(为了决定于这欧拉角怎么工作) 所以我们初始化向左旋转一点
GLfloat pitch = 0.0f;
GLfloat lastX = WIDTH / 2.0; //初始的时候鼠标在屏幕的中间
GLfloat lastY = HEIGHT / 2.0;
GLfloat fov = 45.0f;
bool keys[1024];
// Deltatime 模型绘制的时间
GLfloat deltaTime = 0.0f; // Time between current frame and last frame 当前模型和上次之间的时间
GLfloat lastFrame = 0.0f; // Time of last frame 上次时间
// The MAIN function, from here we start the application and run the game loop
int main()
{
// Init GLFW
glfwInit();
// Set all the required options for GLFW
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);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set the required callback functions 注册这些函数
glfwSetKeyCallback(window, key_callback);//调用注册的按键函数
glfwSetCursorPosCallback(window, mouse_callback);//调用鼠标移动的函数
glfwSetScrollCallback(window, scroll_callback);//调用注册的缩放函数
// GLFW Options
//首先告诉GLFW,应该隐藏光标,并
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
glewInit();
// Define the viewport dimensions
glViewport(0, 0, WIDTH, HEIGHT);
glEnable(GL_DEPTH_TEST);
// Build and compile our shader program
Shader ourShader("D:/C语言/openglflew/shader6/shader.vs", "D:/C语言/openglflew/shader6/shader.frag");
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3( 1.3f, -2.0f, -2.5f),
glm::vec3( 1.5f, 2.0f, -2.5f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// TexCoord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Unbind VAO
// Load, create texture and generate mipmaps 加载,创建纹理并且形成译码
//image format
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt;
int width, height;
FIBITMAP *dib(0);
//1 获取图片格式
fifmt = FreeImage_GetFileType("D:/C语言/openglflew/wall.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt))
dib = FreeImage_Load(fifmt, "D:/C语言/openglflew/wall.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib));//大小
//if the image failed to load, return failure
if(!dib)
cout<<55<<endl;
//3 转化为rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);
//4 获取数据指针
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
width = FreeImage_GetWidth(dib);
height = FreeImage_GetHeight(dib);
cout<<"width:"<<width<<endl;
cout<<"height:"<<height<<endl;
///----------------------------------------加载第二个纹理图片----
FREE_IMAGE_FORMAT fif1 = FIF_UNKNOWN;
FREE_IMAGE_FORMAT fifmt1;
int width1, height1;
FIBITMAP *dib1(0);
//1 获取图片格式
fifmt1 = FreeImage_GetFileType("D:/C语言/openglflew/face.png", 0);
//2 加载图片
if(FreeImage_FIFSupportsReading(fifmt1))
dib1 = FreeImage_Load(fifmt1, "D:/C语言/openglflew/face.png",0);
printf("bit: %d\n", FreeImage_GetBPP(dib1));//灰度
printf("type: %d\n",FreeImage_GetImageType(dib1));//返回类型
printf("bit: %d\n",FreeImage_GetColorsUsed(dib1));//调色板的大小
printf("bit: %d\n",FreeImage_GetDIBSize(dib1));//大小
//if the image failed to load, return failure
if(!dib1)
cout<<55<<endl;
//3 转化为rgb 24色
dib1= FreeImage_ConvertTo24Bits(dib1);
//4 获取数据指针
BYTE *pixels1 = (BYTE*)FreeImage_GetBits(dib1);
width1 = FreeImage_GetWidth(dib1);
height1 = FreeImage_GetHeight(dib1);
cout<<"width1:"<<width1<<endl;
cout<<"height1:"<<height1<<endl;
// Load and create a texture
GLuint texture1;
GLuint texture2;
// ====================
// Texture 1
// ====================
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture.
// ===================
// Texture 2
// ===================
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0,GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels1);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Game loop
while (!glfwWindowShouldClose(window))
{
// Calculate deltatime of current frame
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; //绘制所用的时间
lastFrame = currentFrame;
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
do_movement();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind Textures using texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);
// Activate shader
ourShader.Use();
// Camera/View transformation
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
// Projection
glm::mat4 projection;
projection = glm::perspective(fov, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f);
// Get the uniform locations
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
// Pass the matrices to the shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
for (GLuint i = 0; i < 10; i++)
{
// Calculate the model matrix for each object and pass it to shader before drawing
glm::mat4 model;
model = glm::translate(model, cubePositions[i]);
GLfloat angle = 20.0f * i;
model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
//清除
FreeImage_Unload(dib);
FreeImage_DeInitialise();
FreeImage_Unload(dib1);
FreeImage_DeInitialise();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(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 do_movement()
{
// Camera controls
GLfloat cameraSpeed = 5.0f * deltaTime;
if (keys[GLFW_KEY_W])
cameraPos += cameraSpeed * cameraFront;
if (keys[GLFW_KEY_S])
cameraPos -= cameraSpeed * cameraFront;
if (keys[GLFW_KEY_A])
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (keys[GLFW_KEY_D])
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
bool firstMouse = true;
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
//算出改变
GLfloat xoffset = xpos - lastX;
GLfloat yoffset = lastY - ypos; // Reversed since y-coordinates go from bottom to left
lastX = xpos;
lastY = ypos;
GLfloat sensitivity = 0.05; // Change this value to your liking 根据你的爱好改变这个值
xoffset *= sensitivity; //乘以这个数来改变变化的幅度
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
// Make sure that when pitch is out of bounds, screen doesn't get flipped 设置不能超越90度
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
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));
cameraFront = glm::normalize(front);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
if (fov <= 1.0f)
fov = 1.0f;
if (fov >= 45.0f)
fov = 45.0f;
}