OpenGL Shader 加载3DMax模型

2 篇文章 2 订阅

OpenGL Shader 加载3DMax模型

原创yulinxx 最后发布于2016-12-20 14:50:12 阅读数 2919  收藏

展开

 

 

 

 

 

 

 

 

现在市面上有一个很流行的模型加载库,叫做Assimp,全称为Open Asset Import Library。Assimp可以导入几十种不同格式的模型文件(同样也可以导出部分模型格式)。只要Assimp加载完了模型文件,我们就可以从Assimp上获取所有我们需要的模型数据。Assimp把不同的模型文件都转换为一个统一的数据结构,所有无论我们导入何种格式的模型文件,都可以用同一个方式去访问我们需要的模型数据。

 

当导入一个模型文件时,即Assimp加载一整个包含所有模型和场景数据的模型文件到一个scene对象时,Assimp会为这个模型文件中的所有场景节点、模型节点都生成一个具有对应关系的数据结构,且将这些场景中的各种元素与模型数据对应起来。

 

http://learnopengl-cn.readthedocs.io/zh/latest/03%20Model%20Loading/01%20Assimp/

 

 

Assimp:

 

下载,解压, 然后用CMake加载,指定输出路径后

Configure,再Generate,

然后用VS2015打开 H:\assimp-3.3.1\bin\Assimp.sln 编译

在 H:\assimp-3.3.1\bin\code\Debug 中,即可生成 

assimp-vc140-mt.lib assimp-vc140-mt.dll

然后在项目中即可使用

 

VS2015 可用:

 

包含: lib , dll 以及头文件, 可以直接使用. .VS2015....assimp-3.3.1

 

http://download.csdn.net/detail/yulinxx/9714936

 

 

 

代码:

 

main.cpp

 

 

// Std. Includes

#include <string>

 

// GLEW

#define GLEW_STATIC

#include <GL/glew.h>

 

// GLFW

#include <GLFW/glfw3.h>

 

// GL includes

#include "Shader.h"

#include "Camera.h"

#include "Model.h"

 

// GLM Mathemtics

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#include <glm/gtc/type_ptr.hpp>

 

// Other Libs

#include <SOIL/SOIL.h>

 

 

#pragma comment(lib, "./SOIL.lib")

 

#pragma comment (lib, "opengl32.lib")

#pragma comment (lib, "glew32s.lib")

#pragma comment (lib, "glfw3.lib") 

#pragma comment (lib, "glfw3dll.lib") 

#pragma comment (lib, "glew32mxs.lib")

#pragma comment (lib, "assimp.lib")

 

 

// Properties

GLuint screenWidth = 800, screenHeight = 600;

 

// Function prototypes

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);

void mouse_callback(GLFWwindow* window, double xpos, double ypos);

void Do_Movement();

 

// Camera

Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));

bool keys[1024];

GLfloat lastX = 400, lastY = 300;

bool firstMouse = true;

 

GLfloat deltaTime = 0.0f;

GLfloat lastFrame = 0.0f;

 

// The MAIN function, from here we start our application and run the Game loop

int main()

{

// Init GLFW

glfwInit();

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);

glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

 

GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed

glfwMakeContextCurrent(window);

 

// Set the required callback functions

glfwSetKeyCallback(window, key_callback);

glfwSetCursorPosCallback(window, mouse_callback);

glfwSetScrollCallback(window, scroll_callback);

 

// Options

//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

 

// Initialize GLEW to setup the OpenGL Function pointers

glewExperimental = GL_TRUE;

glewInit();

 

// Define the viewport dimensions

glViewport(0, 0, screenWidth, screenHeight);

 

// Setup some OpenGL options

glEnable(GL_DEPTH_TEST);

 

// Setup and compile our shaders

Shader shader("./Shader/obj_vertex", "./Shader/obj_fragement");

Shader lampShader("./Shader/lamp_vertex", "./Shader/lamp_fragement");

 

// Load models

Model ourModel("./nanosuit.obj");

// Used a lamp object here. Find one yourself on the internet, or create your own one ;) (or be oldschool and set the VBO and VAO yourselves)

//Model lightBulb("./Bulb.obj");

Model lightBulb("./nanosuit.obj");

 

// Draw in wireframe

//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

 

// Point light positions

glm::vec3 pointLightPositions[] = {

glm::vec3(2.3f, -1.6f, -3.0f),

glm::vec3(-1.7f, 0.9f, 1.0f)

};

 

// Game loop

while (!glfwWindowShouldClose(window))

{

// Set frame time

GLfloat currentFrame = glfwGetTime();

deltaTime = currentFrame - lastFrame;

lastFrame = currentFrame;

 

// Check and call events

glfwPollEvents();

Do_Movement();

 

// Clear the colorbuffer

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 

shader.useShaderPrograme();   // <-- Don't forget this one!

// Transformation matrices

glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);

glm::mat4 view = camera.GetViewMatrix();

glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));

glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));

// Set the lighting uniforms

glUniform3f(glGetUniformLocation(shader.getPrograme(), "viewPos"), camera.Position.x, camera.Position.y, camera.Position.z);

// Point light 1

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].ambient"), 0.5f, 0.5f, 0.05f);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].diffuse"), 1.0f, 1.0f, 1.0f);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].constant"), 1.0f);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].linear"), 0.9);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].quadratic"), 0.32);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].diffuse"), 1.0f, 1.0f, 1.0f);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].constant"), 1.0f);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].linear"), 0.009);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].quadratic"), 0.0032);

// Point light 2

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].ambient"), 0.5f, 0.5f, 0.5f);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].diffuse"), 1.0f, 1.0f, 1.0f);

//glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].constant"), 1.0f);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].linear"), 0.9);

//glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].quadratic"), 0.32);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].diffuse"), 1.0f, 1.0f, 1.0f);

glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].constant"), 1.0f);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].linear"), 0.009);

glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].quadratic"), 0.0032);

// Draw the loaded model

glm::mat4 model;

model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene

model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down

glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));

ourModel.Draw(shader);

// Draw the lamps

lampShader.useShaderPrograme();

glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));

glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));

for (GLuint i = 0; i < 2; i++)

{

model = glm::mat4();

model = glm::translate(model, pointLightPositions[i]);

model = glm::scale(model, glm::vec3(0.3f, 0.3f, 0.3f)); // Downscale lamp object (a bit too large)

glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));

lightBulb.Draw(lampShader);

}

// Swap the buffers

glfwSwapBuffers(window);

}

glfwTerminate();

return 0;

}

#pragma region "User input"

// Moves/alters the camera positions based on user input

void Do_Movement()

{

// Camera controls

if (keys[GLFW_KEY_W])

camera.ProcessKeyboard(FORWARD, deltaTime);

if (keys[GLFW_KEY_S])

camera.ProcessKeyboard(BACKWARD, deltaTime);

if (keys[GLFW_KEY_A])

camera.ProcessKeyboard(LEFT, deltaTime);

if (keys[GLFW_KEY_D])

camera.ProcessKeyboard(RIGHT, deltaTime);

}

// 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 (action == GLFW_PRESS)

keys[key] = true;

else if (action == GLFW_RELEASE)

keys[key] = false;

}

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;

lastX = xpos;

lastY = ypos;

camera.ProcessMouseMovement(xoffset, yoffset);

}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)

{

camera.ProcessMouseScroll(yoffset);

}

#pragma endregion

 

 

 

 

 

 

mesh.h

 

 

 

 

#pragma once

// Std. Includes

#include <string>

#include <fstream>

#include <sstream>

#include <iostream>

#include <vector>

using namespace std;

// GL Includes

#include <GL/glew.h> // Contains all the necessery OpenGL includes

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

 

 

struct Vertex {

// Position

glm::vec3 Position;

// Normal

glm::vec3 Normal;

// TexCoords

glm::vec2 TexCoords;

};

 

struct Texture {

GLuint id;

string type;

aiString path;

};

 

class Mesh {

public:

/*  Mesh Data  */

vector<Vertex> vertices;

vector<GLuint> indices;

vector<Texture> textures;

 

/*  Functions  */

// Constructor

Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures)

{

this->vertices = vertices;

this->indices = indices;

this->textures = textures;

 

// Now that we have all the required data, set the vertex buffers and its attribute pointers.

this->setupMesh();

}

 

// Render the mesh

void Draw(Shader shader)

{

// Bind appropriate textures

GLuint diffuseNr = 1;

GLuint specularNr = 1;

for (GLuint i = 0; i < this->textures.size(); i++)

{

glActiveTexture(GL_TEXTURE0 + i); // Active proper texture unit before binding

  // Retrieve texture number (the N in diffuse_textureN)

stringstream ss;

string number;

string name = this->textures[i].type;

if (name == "texture_diffuse")

ss << diffuseNr++; // Transfer GLuint to stream

else if (name == "texture_specular")

ss << specularNr++; // Transfer GLuint to stream

number = ss.str();

// Now set the sampler to the correct texture unit

glUniform1i(glGetUniformLocation(shader.getPrograme(), (name + number).c_str()), i);

// And finally bind the texture

glBindTexture(GL_TEXTURE_2D, this->textures[i].id);

}

 

// Also set each mesh's shininess property to a default value (if you want you could extend this to another mesh property and possibly change this value)

glUniform1f(glGetUniformLocation(shader.getPrograme(), "material.shininess"), 16.0f);

 

// Draw mesh

glBindVertexArray(this->VAO);

glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);

glBindVertexArray(0);

 

// Always good practice to set everything back to defaults once configured.

for (GLuint i = 0; i < this->textures.size(); i++)

{

glActiveTexture(GL_TEXTURE0 + i);

glBindTexture(GL_TEXTURE_2D, 0);

}

}

 

private:

/*  Render data  */

GLuint VAO, VBO, EBO;

 

/*  Functions    */

// Initializes all the buffer objects/arrays

void setupMesh()

{

// Create buffers/arrays

glGenVertexArrays(1, &this->VAO);

glGenBuffers(1, &this->VBO);

glGenBuffers(1, &this->EBO);

 

glBindVertexArray(this->VAO);

// Load data into vertex buffers

glBindBuffer(GL_ARRAY_BUFFER, this->VBO);

// A great thing about structs is that their memory layout is sequential for all its items.

// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which

// again translates to 3/2 floats which translates to a byte array.

glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &this->vertices[0], GL_STATIC_DRAW);

 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW);

 

// Set the vertex attribute pointers

// Vertex Positions

glEnableVertexAttribArray(0);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);

// Vertex Normals

glEnableVertexAttribArray(1);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal));

// Vertex Texture Coords

glEnableVertexAttribArray(2);

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, TexCoords));

 

glBindVertexArray(0);

}

};

 

 

 

 

 

 

model.h

 

 

 

 

#pragma once

// Std. Includes

#include <string>

#include <fstream>

#include <sstream>

#include <iostream>

#include <map>

#include <vector>

using namespace std;

// GL Includes

#include <GL/glew.h> // Contains all the necessery OpenGL includes

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#include <SOIL/SOIL.h>

#include <assimp/Importer.hpp>

#include <assimp/scene.h>

#include <assimp/postprocess.h>

 

#include "Mesh.h"

 

GLint TextureFromFile(const char* path, string directory);

 

class Model

{

public:

/*  Functions   */

// Constructor, expects a filepath to a 3D model.

Model(GLchar* path)

{

this->loadModel(path);

}

 

// Draws the model, and thus all its meshes

void Draw(Shader shader)

{

for (GLuint i = 0; i < this->meshes.size(); i++)

this->meshes[i].Draw(shader);

}

 

private:

/*  Model Data  */

vector<Mesh> meshes;

string directory;

vector<Texture> textures_loaded; // Stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.

 

/*  Functions   */

// Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.

void loadModel(string path)

{

// Read file via ASSIMP

Assimp::Importer importer;

const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);

// Check for errors

if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero

{

cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;

return;

}

// Retrieve the directory path of the filepath

this->directory = path.substr(0, path.find_last_of('/'));

 

// Process ASSIMP's root node recursively

this->processNode(scene->mRootNode, scene);

}

 

// Processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any).

void processNode(aiNode* node, const aiScene* scene)

{

// Process each mesh located at the current node

for (GLuint i = 0; i < node->mNumMeshes; i++)

{

// The node object only contains indices to index the actual objects in the scene. 

// The scene contains all the data, node is just to keep stuff organized (like relations between nodes).

aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];

this->meshes.push_back(this->processMesh(mesh, scene));

}

// After we've processed all of the meshes (if any) we then recursively process each of the children nodes

for (GLuint i = 0; i < node->mNumChildren; i++)

{

this->processNode(node->mChildren[i], scene);

}

 

}

 

Mesh processMesh(aiMesh* mesh, const aiScene* scene)

{

// Data to fill

vector<Vertex> vertices;

vector<GLuint> indices;

vector<Texture> textures;

 

// Walk through each of the mesh's vertices

for (GLuint i = 0; i < mesh->mNumVertices; i++)

{

Vertex vertex;

glm::vec3 vector; // We declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first.

  // Positions

vector.x = mesh->mVertices[i].x;

vector.y = mesh->mVertices[i].y;

vector.z = mesh->mVertices[i].z;

vertex.Position = vector;

// Normals

vector.x = mesh->mNormals[i].x;

vector.y = mesh->mNormals[i].y;

vector.z = mesh->mNormals[i].z;

vertex.Normal = vector;

// Texture Coordinates

if (mesh->mTextureCoords[0]) // Does the mesh contain texture coordinates?

{

glm::vec2 vec;

// A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't 

// use models where a vertex can have multiple texture coordinates so we always take the first set (0).

vec.x = mesh->mTextureCoords[0][i].x;

vec.y = mesh->mTextureCoords[0][i].y;

vertex.TexCoords = vec;

}

else

vertex.TexCoords = glm::vec2(0.0f, 0.0f);

vertices.push_back(vertex);

}

// Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.

for (GLuint i = 0; i < mesh->mNumFaces; i++)

{

aiFace face = mesh->mFaces[i];

// Retrieve all indices of the face and store them in the indices vector

for (GLuint j = 0; j < face.mNumIndices; j++)

indices.push_back(face.mIndices[j]);

}

// Process materials

if (mesh->mMaterialIndex >= 0)

{

aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];

// We assume a convention for sampler names in the shaders. Each diffuse texture should be named

// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. 

// Same applies to other texture as the following list summarizes:

// Diffuse: texture_diffuseN

// Specular: texture_specularN

// Normal: texture_normalN

 

// 1. Diffuse maps

vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");

textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());

// 2. Specular maps

vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");

textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());

}

 

// Return a mesh object created from the extracted mesh data

return Mesh(vertices, indices, textures);

}

 

// Checks all material textures of a given type and loads the textures if they're not loaded yet.

// The required info is returned as a Texture struct.

vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName)

{

vector<Texture> textures;

for (GLuint i = 0; i < mat->GetTextureCount(type); i++)

{

aiString str;

mat->GetTexture(type, i, &str);

// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture

GLboolean skip = false;

for (GLuint j = 0; j < textures_loaded.size(); j++)

{

if (textures_loaded[j].path == str)

{

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)

{   // If texture hasn't been loaded already, load it

Texture texture;

texture.id = TextureFromFile(str.C_Str(), this->directory);

texture.type = typeName;

texture.path = str;

textures.push_back(texture);

this->textures_loaded.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.

}

}

return textures;

}

};

 

 

 

 

GLint TextureFromFile(const char* path, string directory)

{

//Generate texture ID and load texture data 

string filename = string(path);

filename = directory + '/' + filename;

GLuint textureID;

glGenTextures(1, &textureID);

int width, height;

unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);

// Assign texture to ID

glBindTexture(GL_TEXTURE_2D, textureID);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

glGenerateMipmap(GL_TEXTURE_2D);

 

// Parameters

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, 0);

SOIL_free_image_data(image);

return textureID;

}

 

 

 

 

 

 

 

 

camera.h

 

 

//Camera.h 

 

#pragma once

 

// Std. Includes

#include <vector>

 

// GL Includes

#include <GL/glew.h>

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

 

 

// 摄像机移动方向  程序中用WSAD控制

enum Camera_Movement {

FORWARD,

BACKWARD,

LEFT,

RIGHT

};

 

// Default camera values

const GLfloat YAW = -90.0f;

const GLfloat PITCH = 0.0f;

const GLfloat SPEED = 3.0f;

const GLfloat SENSITIVTY = 0.25f;

const GLfloat ZOOM = 45.0f;

 

 

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

glm::mat4 GetViewMatrix()

{

return glm::lookAt(this->Position, this->Position + this->Front, this->Up);

}

 

// 按键处理

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;

}

 

// 鼠标移动处理

void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, 

GLboolean 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

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

// Normalize the vectors, because their length gets closer to 0 the more 

// you look up or down which results in slower movement.

this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));  

this->Up = glm::normalize(glm::cross(this->Right, this->Front));

}

};

 

 

 

 

shader.h

 

 

 

 

//Shader.h 

#pragma once

 

#ifndef TEXTURE_SHADER_H_

#define TEXTURE_SHADER_H_

 

#include <string>

#include <fstream>

#include <sstream>

#include <iostream>

 

#include <gl/glew.h>

 

#include <string>

#include <fstream>

#include <sstream>

#include <iostream>

 

#include <GL/glew.h>

 

class Shader

{

public:

Shader(const GLchar* vertexPath, const GLchar* fragmentPath);

~Shader();

 

public:

void useShaderPrograme();

 

GLuint getPrograme() {

return this->m_nProgram;

}

 

private:

GLuint  m_nProgram;

};

 

Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)

{

std::string vertexCode;

std::string fragmentCode;

std::ifstream vertexShaderF;

std::ifstream fragementShaderF;

 

vertexShaderF.exceptions(std::ifstream::badbit);

fragementShaderF.exceptions(std::ifstream::badbit);

 

try

{

vertexShaderF.open(vertexPath); // 打开文件

fragementShaderF.open(fragmentPath);

 

std::stringstream vertexShaderStream, fragementShaderStream;

vertexShaderStream << vertexShaderF.rdbuf(); // 读取文件至stringstream中

fragementShaderStream << fragementShaderF.rdbuf();

vertexShaderF.close();

fragementShaderF.close();

vertexCode = vertexShaderStream.str(); // 转换成string类型

fragmentCode = fragementShaderStream.str();

}

catch (std::ifstream::failure e)

{

std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;

}

const GLchar* pVertexCode = vertexCode.c_str(); // string 转 char*

const GLchar* pFragementCode = fragmentCode.c_str();

GLuint nVertexShader, nFragementShader;

GLint nRes = 0;

GLchar chLogInfo[512] = { '\0' };

// 创建顶点着色器

nVertexShader = glCreateShader(GL_VERTEX_SHADER);

// 将顶点着色程序的源代码字符数组绑定到顶点着色器对象

glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);

glCompileShader(nVertexShader); // compile shader 编译着色器

// 获取编译结果

glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);

if (!nRes)

{

glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);

std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;

}

// 创建片断着色器

nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);

// 将片段着色程序的源代码字符数组绑定到片段着色器对象

glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);

glCompileShader(nFragementShader);

glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);

if (!nRes)

{

glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);

std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;

}

this->m_nProgram = glCreateProgram(); // 创建GLSL程序

glAttachShader(this->m_nProgram, nVertexShader); // 绑定shader到program

glAttachShader(this->m_nProgram, nFragementShader);

 

// glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令

glLinkProgram(this->m_nProgram); // 链接

glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);

if (!nRes)

{

glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);

std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;

}

glDeleteShader(nVertexShader);

glDeleteShader(nFragementShader);

}

Shader::~Shader()

{

}

#include <glm/glm.hpp>

#include <glm/gtc/matrix_transform.hpp>

#include <glm/gtc/type_ptr.hpp>

 

void Shader::useShaderPrograme()

{

glUseProgram(this->m_nProgram); // 使用porgram

}

 

#endif

 

 

 

 

***********************************Shader 源码部分************************************

 

obj_vertex:

 

 

 

 

// Vertex shader:

// ================

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec3 normal;

layout (location = 2) in vec2 texCoords;

 

out vec2 TexCoords;

out vec3 fragPosition;

out vec3 Normal;

 

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

 

void main()

{

    gl_Position = projection * view * model * vec4(position, 1.0f);

    fragPosition = vec3(model * vec4(position, 1.0f));

    Normal = mat3(transpose(inverse(model))) * normal;

    TexCoords = texCoords;

}

 

 

 

 

obj_fragement:

 

 

 

 

// Fragment shader:

// ================

#version 330 core

struct Material {

    sampler2D texture_diffuse1;

    sampler2D texture_specular1;

    float shininess;

}; 

/* Note: because we now use a material struct again you want to change your

mesh class to bind all the textures using material.texture_diffuseN instead of

texture_diffuseN. */

 

struct PointLight {

    vec3 position;

    

    float constant;

    float linear;

    float quadratic;

    

    vec3 ambient;

    vec3 diffuse;

    vec3 specular;

};

 

#define NR_POINT_LIGHTS 2

 

in vec3 fragPosition;

in vec3 Normal;

in vec2 TexCoords;

 

out vec4 color;

 

uniform vec3 viewPos;

uniform PointLight pointLights[NR_POINT_LIGHTS];

uniform Material material;

 

// Function prototypes

vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir);

 

void main()

{    

    vec3 result;

    vec3 viewDir = normalize(viewPos - fragPosition);

    vec3 norm = normalize(Normal);

    

    for(int i = 0; i < NR_POINT_LIGHTS; i++)

        result += CalcPointLight(pointLights[i], material, norm, fragPosition, viewDir);

        

    color = vec4(result, 1.0f);

}

// Calculates the color when using a point light.

vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir)

{

    vec3 lightDir = normalize(light.position - fragPos);

    // Diffuse shading

    float diff = max(dot(normal, lightDir), 0.0);

    // Specular shading

    vec3 reflectDir = reflect(-lightDir, normal);

    float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);

    // Attenuation

    float distance = length(light.position - fragPos);

    float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    

    // Combine results

    vec3 ambient = light.ambient * vec3(texture(mat.texture_diffuse1, TexCoords));

    vec3 diffuse = light.diffuse * diff * vec3(texture(mat.texture_diffuse1, TexCoords));

    vec3 specular = light.specular * spec * vec3(texture(mat.texture_specular1, TexCoords));

    ambient *= attenuation;

    diffuse *= attenuation;

    specular *= attenuation;

    return (ambient + diffuse + specular);

}

 

 

 

 

lamp_vertex:

 

 

 

 

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec3 normal;

layout (location = 2) in vec2 texCoords;

 

out vec2 TexCoords;

 

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

 

void main()

{

    gl_Position = projection * view * model * vec4(position, 1.0f);

    TexCoords = texCoords;

}

 

 

 

 

 

 

lamp_fragement:

 

 

 

 

 

 

#version 330 core

 

in vec2 TexCoords;

 

out vec4 color;

 

uniform sampler2D texture_diffuse1;

 

void main()

{    

    color = vec4(texture(texture_diffuse1, TexCoords));

}

 

 

 

VS2015 工程 下载:

 

http://download.csdn.net/detail/yulinxx/9716523

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值