用glew,glfw,FreeImag实现opengl画图->第五课 摄像机

这篇文章是参考教程点击打开链接 摄像机一节  我觉得这个教程非常好所以把上面的例程都在本地实现

下面是教程的第一部分,箱子旋转,摄像机不动。具体原理教程里很清楚。这里是我实现的代码 着色器程序代码  在源码链接点击打开链接   里面的文件夹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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值