OpenGL学习笔记(十三)模型的加载

关于openGl模型的加载需要使用到Assimp库,非常喜闻乐见的是如果你用的编译器是Vs的话,就能通过NuGet直接获取到这个库,装载即可。我这里就不演示了!直接去网上搜索一下就知道怎么安装包了。
在这里插入图片描述
根据上图,我们可以看到模型中有一个scene场景,然后左边的是则是各种节点,我们要的做就是遍历左边的接单获取到右边的数据。
我们可以看到我们目前还缺少一个网格类。
Mesh.h

#pragma once
#include<glm/glm.hpp>
#include<string>
#include<vector>
#include"Shader.h"
#include<Gl/glew.h>
#include <assimp/Importer.hpp>

struct Vertex//顶点结构体
{
	glm::vec3 Position;
	glm::vec3 Normal;
	glm::vec2 TexCoords;
};
struct Texture{//贴图结构体
	unsigned int id;
	std::string type;
	aiString path;
};
class Mesh
{
public :
	std::vector<Vertex> vertices;//顶点容器,似乎就是个动态列表
	std::vector<Texture> textures;//贴图容器
	std::vector<unsigned int> indices;//EBO绘制的索引,
	Mesh(float vertices[]);//给你测试网格类是否出错的,输入我们前面的那个组就能直接绘画出正方体
	Mesh(std::vector<Vertex> vertices,std::vector<Texture> textures,std::vector<unsigned int> indices);//这是带三个参数构造函数
	void Draw(Shader* shader);//绘制
private:
	unsigned int VAO, VBO, EBO;//这些相信你应该还有映像吧,就是我们将顶点的绘制封装成一个类
	void SteupMesh();//初始化网格类	
};

Mesh.cpp

#include "Mesh.h"
#include <string>
#include<iostream>
Mesh::Mesh(float vertices[])//测试用的
{
	this->vertices.resize(36);
	memcpy(&(this->vertices[0]),vertices,36*8*sizeof(float));
	SteupMesh();
}

Mesh::Mesh(std::vector<Vertex> vertices, std::vector<Texture> textures, std::vector<unsigned int> indices)//构造
{
	this->vertices = vertices;
	this->indices = indices;
	this->textures = textures;
	SteupMesh();
}
void Mesh::Draw(Shader* shader)//绘制网格
{
	for (GLuint i = 0; i < this->textures.size(); i++)//遍历贴图容器
	{
		std::string name = this->textures[i].type;
		if (name == "texture_diffuse")//如果类型为diffuse,就放到0号槽位
		{
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D,this->textures[i].id);
			shader->SetUniform1i("material.diffuse",0);
		}
		else if(name =="texture_specular")//如果类型为specular,就放到1号槽位
		{ 
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
			shader->SetUniform1i("material.specular",1);
		}
	}	
	glBindVertexArray(this->VAO);
	//测试时绘制正方体时使用,
	//glDrawArrays(GL_TRIANGLES,0,36);
   //根据元素索引绘制,测试时需要注释掉
	glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSIGNED_INT,0);
	glBindVertexArray(0);
	glBindTexture(GL_TEXTURE_2D,0);
}
//这个就不讲了,就是绘制网格的流水线配置
void Mesh::SteupMesh()
{
	glGenVertexArrays(1,&VAO);
	glBindVertexArray(VAO);
	glGenBuffers(1,&VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER,sizeof(Vertex)* vertices.size(),&vertices[0],GL_STATIC_DRAW);
//测试绘制的时候,需要注释掉下面三行,因为测试绘制没有索引属性。
	glGenBuffers(1,&EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(unsigned     int)*indices.size(),&indices[0],GL_STATIC_DRAW);
	
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),(GLvoid*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(3*sizeof(GL_FLOAT)));
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(6 * sizeof(GL_FLOAT)));
	glBindVertexArray(0);
}

如要测试,只要在main.cpp中输入

Mesh mesh(vertices);
mesh.Draw(myShader);

就能得到一个正方体了,注意该注释的要注释掉。

接下来是
Model.h

#pragma once
#include<string>
#include<vector>
#include"Mesh.h"
#include"Shader.h"
#include<iostream>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

class Model
{
public :
	Model(std::string path);//构造
	void Draw(Shader* shader);
	
private:
	std::vector<Mesh> meshes;//网格容器
	std::vector<Texture> textures_loaded;//记录已经加载过的贴图
	std::string directory;//路径
	void loadModel(std::string path);//加载模型
	void processNode(aiNode* node, const aiScene *scene);//查找节点
	Mesh processMesh(aiMesh* mesh, const aiScene* scene);//转换为我们自己的Mesh类
	std::vector<Texture> loadMaterialTextures(aiMaterial *mat,aiTextureType type,std::string typeName);//通过类型加载贴图
	GLint TextureFromFile(const char* path, std::string directory);//通过文件路径下载贴图
};

Model.cpp

#include "Model.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
using namespace std;
#include<vector>

Model::Model(std::string path)//构造并加载模型
{
	loadModel(path);
}

void Model::Draw(Shader* shader)
{
	for (unsigned int i = 0; i < meshes.size(); i++)//将获取到网格全部绘制出来
	{
		meshes[i].Draw(shader);
	}
	
}

void Model::loadModel(const std::string path)//通过文件路径加载模型
{
	Assimp::Importer importer;
	//读取obj文件
	const aiScene* scene = importer.ReadFile(path,aiProcess_Triangulate|aiProcess_FlipUVs|aiProcess_CalcTangentSpace);
	if (!scene||scene->mFlags&AI_SCENE_FLAGS_INCOMPLETE||!scene->mRootNode)    //没找到就退出
	{
		std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl;
		return;
	}
	//获取到obj文件的所在文件夹地址,如...\model\one.obj,得到就是...\model
	this->directory = path .substr(0, path.find_last_of("\\"));
		processNode(scene->mRootNode,scene);//递归遍历模型的所有节点
}

void Model::processNode(aiNode* node, const aiScene* scene)//递归遍历节点
{
	for (unsigned int i = 0; i < node->mNumMeshes; i++)//遍历当前节点的所有网格,
	{
		aiMesh* curMesh = scene->mMeshes[node->mMeshes[i]];//获取到对应的网格配置
		this->meshes.push_back(processMesh(curMesh,scene));//将网格转换成我们的网格,加到我们的meshes容器里
	}
	for (unsigned int i = 0; i < node->mNumChildren; i++)//递归遍历节点
	{
		processNode(node->mChildren[i],scene);
	}
}
Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)//转换Mesh类
{
	std::vector<Vertex> vertics;
	std::vector<GLuint>indices;
	std::vector<Texture>textures;

	for (unsigned int i = 0; i < mesh->mNumVertices; i++)
	{
	//交换Vertex值
		Vertex tempVertex;
		tempVertex.Position.x = mesh->mVertices[i].x;
		tempVertex.Position.y = mesh->mVertices[i].y;
		tempVertex.Position.z = mesh->mVertices[i].z;

		tempVertex.Normal.x = mesh->mNormals[i].x;
		tempVertex.Normal.y = mesh->mNormals[i].y;
		tempVertex.Normal.z = mesh->mNormals[i].z;

		if (mesh->mTextureCoords[0])
		{
			tempVertex.TexCoords.x = mesh->mTextureCoords[0][i].x;
			tempVertex.TexCoords.y = mesh->mTextureCoords[0][i].y;
		}
		else
		{
			tempVertex.TexCoords = glm::vec2(0.0f,0.0f);
		}
		vertics.push_back(tempVertex);
	}
//获取所有索引
	for (unsigned int i = 0; i < mesh->mNumFaces; i++)//遍历所有面
	{
		for (unsigned int j = 0; j < mesh->mFaces[i].mNumIndices; j++)//遍历对应面的所有索引
		{
			indices.push_back(mesh->mFaces[i].mIndices[j]);
		}
	}
	
	if (mesh->mMaterialIndex>=0)//材质不为0时,运行
	{

		aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];//获取到aiMesh的当前材质
		std::vector<Texture> diffuseMaps = this->loadMaterialTextures(material,aiTextureType_DIFFUSE,"texture_diffuse");//获取diffuse贴图

		textures.insert(textures.end(),diffuseMaps.begin(),diffuseMaps.end());//插入diffuse贴图
		std::vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");//获取所有specular贴图
		textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());//插入specular贴图
		
	}
	return Mesh(vertics,textures,indices);//转换成我们的Mesh类


}

//获取对应类型的贴图
std::vector<Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName)
{

	std::vector < Texture > textures;
	for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)//查看所有对应类型的贴图
	{
		aiString str;
		mat->GetTexture(type,i,&str);//获取贴图
		bool skip = false;
		for (unsigned int j = 0; j < textures_loaded.size(); j++)	//检测是否已经加载过了,如果加载过,就直接获取,避免重复加载
		{
			if (std::strcmp(textures_loaded[j].path.C_Str(), str.C_Str()) == 0	)
			{
				textures.push_back(textures_loaded[j]);
				skip = true; // a texture with the same filepath has already been loaded, continue to next one. (optimization)
				break;
			}
		}
		
		if (!skip)//加载新贴图
		{
			Texture texture;
			texture.id = TextureFromFile(str.C_Str(), this->directory);
			texture.path = str;//str
			texture.type = typeName;
			textures.push_back(texture);
			this->textures_loaded.push_back(texture);//加载进当前函数贴图容器
		}
	
	}
	
	return textures;
}

GLint Model::TextureFromFile( const char* path,std::string directory)//从文件中加载贴图
{
   //配置文件路径
	std::string fileName = std::string(path);
	fileName = directory + '\\' + fileName;
   
	GLuint textureID;
	glGenTextures(1,&textureID);
	int width, height, nrChannels;
	//这就是前面那个LoadImageToGpu的内容,加载贴图。
	unsigned char* image = stbi_load(fileName.c_str(), &width, &height, &nrChannels, 0);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureID);
	if(image)
    {
		GLenum format;//判断贴图通道
		if (nrChannels == 1)
			format = GL_RED;
		else if(nrChannels == 3)
			format = GL_RGB;
		else if (nrChannels==4)
			format = GL_RGBA;
			
		glTexImage2D(GL_TEXTURE_2D,0,format,width,height,0,format,GL_UNSIGNED_BYTE,image);
		glGenerateMipmap(GL_TEXTURE_2D);
	
	}
	else
	{
		std::cout << "Error! stbi load fail!" << std::endl;
	}
	glUniform1i(glGetUniformLocation(myShader->ID, "material.diffuse"), 0);
	stbi_image_free(image);

	glBindTexture(GL_TEXTURE_2D, 0);
	return textureID;
}

main.cpp

#include<iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include<GLFW/glfw3.h>

//#define STB_IMAGE_IMPLEMENTATION
//#include "stb_image.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Shader.h"
#include "Material.h"
#include "Camera.h"
#include "LightDirectional.h"
#include "LightPoint.h"
#include "LightSpot.h"
#include "Mesh.h"
#include "Model.h"
using namespace std;
#pragma region Model Data
GLfloat vertices[] = {
	// Positions          // Normals           // Texture Coords
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
	 0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  0.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,

	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
	 0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,

	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
	-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
	-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
	-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,

	 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
	 0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
	 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
	 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
	 0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,

	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
	 0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  1.0f,
	 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
	 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,

	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
	 0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
	 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
	-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  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)
};
#pragma endregion
#pragma region Input Declare
void ProcessInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);

// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
#pragma region Camera Declare
Camera* myCamera = new Camera(glm::vec3(0, 0, 5.0f), glm::radians(-15.0f), glm::radians(180.0f), glm::vec3(0, 1.0f, 0));
#pragma endregion
#pragma region LightDriection Drclare
LightDirectional myLightD(glm::vec3(10.0f,10.0f,5.0f),glm::vec3(glm::radians(0.0f), glm::radians(0.0f),0),glm::vec3(1.0f,1.0f,1.0f));
#pragma endregion

// The MAIN function, from here we start the application and run the game loop
int main(int argc, char* argv[])
{
	std::string directory = argv[0];
	directory = directory.substr(0, directory.find_last_of("\\")) + "\\Model\\nanosuit.obj";
	#pragma region Open a Window
	// 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);
	//隐藏鼠标
	glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_DISABLED);
	//鼠标移动时呼叫mouse_callback函数
	glfwSetCursorPosCallback(window, mouse_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);
#pragma endregion 

	Model model(directory);

    #pragma region Create Matrix	
	glm::mat4 viewMat;
	glm::mat4 projMat;
	projMat = glm::perspective(glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.01f, 100.0f);
	glEnable(GL_DEPTH_TEST);
#pragma endregion

    #pragma region Init Shader
	Shader* myShader = new Shader("vertexSource.vert", "fragmentSource.frag");
#pragma endregion
	
	// Game loop
	while (!glfwWindowShouldClose(window))
	{	// 检查事件,调用相应的回调函数,如下文的glfwInput函数
		//Process Input
		ProcessInput(window);
        //Clear screen
		glClearColor(0.3f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除前台缓冲
		
		
		viewMat = myCamera->GetViewMatrix();//刷新视角
        for (size_t i = 1; i <= 2; i++)
		{
			glm::mat4 modelMat;//模型矩阵
			modelMat = glm::translate(modelMat, cubePositions[i]);
			modelMat = glm::rotate(modelMat, glm::radians(i*10.0f), glm::vec3(0, 1.0f, 0));
			//Uesd ShaderProgram
			myShader->Use();
			
			glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat));
			glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
			glUniformMatrix4fv(glGetUniformLocation(myShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));
			
			glUniform3f(glGetUniformLocation(myShader->ID, "objColor"), 1.0f, 1.0f, 1.0f);
			glUniform3f(glGetUniformLocation(myShader->ID, "ambientColor"), 0.1f, 0.1f, 0.1f);
			glUniform3f(glGetUniformLocation(myShader->ID, "CameraPos"), myCamera->Position.x, myCamera->Position.y, myCamera->Position.z);

			glUniform3f(glGetUniformLocation(myShader->ID, "lightD.color"), myLightD.color.x, myLightD.color.y, myLightD.color.z);
			glUniform3f(glGetUniformLocation(myShader->ID, "lightD.pos"), myLightD.position.x, myLightD.position.y, myLightD.position.z);
			glUniform3f(glGetUniformLocation(myShader->ID, "lightD.dirToLight"), myLightD.direction.x, myLightD.direction.y, myLightD.direction.z);
			
		

			myShader->SetUniform1f("material.shininess", 32);

			model.Draw(myShader);

		}
		
		glfwSwapBuffers(window);
		glfwPollEvents();
	}


	glfwTerminate();
	return 0;
}

#pragma region Input Fuction 
// Is called whenever a key is pressed/released via GLFW
void ProcessInput(GLFWwindow* window)//通过监控鼠标来控制相机的移动
{
	
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveZ(1);
	}
	else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveZ( -1);
	}
	else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveX(1);
	}
	else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveX(-1);
	}
	else if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveY(1);
	}
	else if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
	{
		myCamera->CameraPosMoveY(-1);
	}
}
bool firstMouse = true;
float lastx = 300, lasty = 400;
void mouse_callback(GLFWwindow* window, double xpos, double ypos)//检查鼠标输入
{
	if (firstMouse==true)//第一次调用该函数的时候直接将当前坐标给过去坐标值,已此来防止一开始的时候出现视角的巨大晃动
	{
		lastx = xpos;
		lasty = ypos;
		firstMouse = false;
	}
	float offsetx = xpos - lastx;
	float offsety = ypos - lasty;
	//std::cout << offsetx << std::endl;
	lastx = xpos;
	lasty = ypos;
	myCamera->CameraViewMove(offsetx,offsety);//调用CameraViewMove函数
}
#pragma endregion

这是效果图:
在这里插入图片描述
最后再记录一个我遇到的问题,被坑了很久,就是如果你的OpenGL加载模型的时候出现了贴图只有灰色的效果。
如下图:
在这里插入图片描述
那就是你的贴图加载通道出了问题。比如这个就是因为模型的贴图为RGBA的,可是我一开始只给了RGB,所以就成了这样。而且这种贴图还是加载成功了的。所以很难排错,所以你以后还是尽量写成那种自动配置颜色通道的会比较好。
就是这句代码:

glTexImage2D(GL_TEXTURE_2D,0, format,width,height,0, format,GL_UNSIGNED_BYTE,image);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值