-OPENGL5 Model Import & Scene Graph & Blend Opacity-
ASSIMP构建大纲:
因为递归的原因有必要把大纲还原,类似katana和maya大纲一样
以maya为例:(输出的时候别导出obj,fbx可以保护层级,abc也可以,但是现在assimp不支持,回头可以用abc api 搞一个)
所以我在函数原型加入一个pwd
void processNode(aiNode * node, const aiScene* scene,string pwd);
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <string> using namespace std; void processNode(aiNode * node, const aiScene* scene, string pwd); int main(){ Assimp::Importer import; string path = "maya.fbx"; const aiScene * scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { cout << "ERROR::ASSIMP::" << import.GetErrorString() << endl; } string directory = path.substr(0, path.find_last_of('/')); cout << directory << endl; // Get Root Node aiNode * node = scene->mRootNode; processNode(node,scene,"/"); return 0; } void processNode(aiNode * node, const aiScene* scene,string pwd){ cout << ">>LOOP At Node:" << pwd <<" WORLD MATRIX:" << endl; aiMatrix4x4 mat = node->mTransformation; cout << "{\n"; cout << "\t" <<mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endl; cout << "\t" <<mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endl; cout << "\t" <<mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endl; cout << "\t" <<mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endl; cout << "}\n"; for(unsigned int i = 0; i < node->mNumMeshes; i++) { aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; // mesh points cout <<">>Num points:" <<mesh->mNumVertices<< endl; // Dump materials infos aiMaterial *mat = scene->mMaterials[mesh->mMaterialIndex]; cout << ">>Get Mesh Name: "<<mesh->mName.C_Str()<< " <-> MaterialName: " << mat->GetName().C_Str() << endl; cout << ">>start dumping the texture:\n"; cout << "{\n"; for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_DIFFUSE); i++) { aiString str; mat->GetTexture(aiTextureType_DIFFUSE, i, &str); cout << "\tdiffuseTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_NORMALS); i++) { aiString str; mat->GetTexture(aiTextureType_NORMALS, i, &str); cout << "\tNormalTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_AMBIENT); i++) { aiString str; mat->GetTexture(aiTextureType_AMBIENT, i, &str); cout << "\tAmbientTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_OPACITY); i++) { aiString str; mat->GetTexture(aiTextureType_OPACITY, i, &str); cout << "\tOpacityTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_SPECULAR); i++) { aiString str; mat->GetTexture(aiTextureType_SPECULAR, i, &str); cout << "\tSpecularTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_HEIGHT); i++) { aiString str; mat->GetTexture(aiTextureType_HEIGHT, i, &str); cout << "\tHeightTexture: "<<str.C_Str() << endl; } for(unsigned int i = 0; i < mat->GetTextureCount(aiTextureType_UNKNOWN); i++) { aiString str; mat->GetTexture(aiTextureType_HEIGHT, i, &str); cout << "\tUnkownTexture: "<<str.C_Str() << endl; } cout << "}\n"; } for(unsigned int i = 0; i < node->mNumChildren; i++) { string pathName = pwd + node->mChildren[i]->mName.C_Str(); pathName += "/"; processNode(node->mChildren[i], scene,pathName); } cout << "\n"; }
DUMP:
maya.fbx >>LOOP At Node:/ WORLD MATRIX: { 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 } >>LOOP At Node:/Geometry/ WORLD MATRIX: { 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 } >>LOOP At Node:/Geometry/part1/ WORLD MATRIX: { 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 } >>LOOP At Node:/Geometry/part1/pSphere1/ WORLD MATRIX: { 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere1 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part1/pSphere2/ WORLD MATRIX: { 1 0 0 0 0 1 0 2.17013 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere2 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part1/pSphere3/ WORLD MATRIX: { 1 0 0 0 0 1 0 4.34026 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere3 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part1/pSphere4/ WORLD MATRIX: { 1 0 0 0 0 1 0 6.51039 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere4 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part2/ WORLD MATRIX: { 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 } >>LOOP At Node:/Geometry/part2/pSphere5/ WORLD MATRIX: { 1 0 0 0 0 1 0 8.68052 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere5 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part2/pSphere6/ WORLD MATRIX: { 1 0 0 0 0 1 0 10.8507 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere6 <-> MaterialName: lambert1 >>start dumping the texture: { } >>LOOP At Node:/Geometry/part2/pSphere7/ WORLD MATRIX: { 1 0 0 0 0 1 0 13.0208 0 0 1 0 0 0 0 1 } >>Num points:1560 >>Get Mesh Name: pSphere7 <-> MaterialName: lambert1 >>start dumping the texture: { }
额外的我定义了我的场景描述,已经修改的跪下了,每次写代码遍历场景,发现特么的完全不科学。
json用的https://github.com/nlohmann/json
CP19会实现场景分析,加载场景。CP18修改了一些系统内部逻辑设计。
{ "name": "simple", "project_dir": "D:/plugin_dev/opengl/CP_18/Triangle/build/scene", "models": [ "model/nanosuit.obj" ], "mats": { "glass": { "shader_define": { "___comment___": "type=0 is file shader; type=1 use inline color ; type=2 use inline texture; type=3 use our json code shader,this may be use in our ui ", "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/glass_dif.png" } }, "leg": { "shader_define": { "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/leg_dif.png", "specular": "model/leg_showroom_spec.png" } }, "hand": { "shader_define": { "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/hand_dif.png", "specular": "model/hand_showroom_spec.png" } }, "body": { "shader_define": { "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/mat2_diffuse.png", "specular": "model/mat2_specular.png" } }, "helmet": { "shader_define": { "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/helmet_diff.png", "specular": "model/helmet_showroom_spec.png" } }, "arms": { "shader_define": { "code_type": 0, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/arm_dif.png", "specular": "model/arm_showroom_spec.png" } } }, "assignMaterial": { "/Visor": "glass", "/Lights": "glass", "/Legs": "leg", "/hands": "hand", "/Arms": "arms", "/Helmet": "helmet", "/Body": "body" } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <json.hpp> #include <fstream> using namespace std; using json = nlohmann::json; int main() { ifstream in("scene.json"); json j; in >> j; cout << "scene name:" << j.at("name") << endl; cout << "project dir" << j.at("project_dir") <<endl; for(auto &m: j["models"]){ cout << "load model:" << m.get<string>() <<endl; } cout << "\nParse Materials:\n"; // read "mats" json mats = j["mats"]; for(auto &mat: mats.items()){ json matNameObject = mat.key(); // json mat name json matContentObject = mat.value(); // json shader content define cout << "Inspect mat:" << matNameObject <<endl; json shaderDefineObject = matContentObject["shader_define"]; json paramDefineObject = matContentObject["params_define"]; //cout << shaderDefineObject <<endl; //cout << paramDefineObject << endl; for(auto ¶ms: paramDefineObject.items()) { json paramNameObject = params.key(); json valueObject = params.value(); // may be relative texture path , or shader value string pname = paramNameObject.get<string>(); if(pname == "diffuse"){ cout << "diffuse: " << valueObject <<endl; } if(pname == "specular"){ cout << "specular: " << valueObject <<endl; } } cout << "\n"; } return 0; }
Log:
21:36:39: Starting D:\plugin_dev\opengl\JSON_CP_01\JSON_Scene_Parse\JSON_Scene_Parse.exe ... scene name:"simple" project dir"D:/plugin_dev/opengl/CP_18/Triangle/build/scene" load model:model/nanosuit.obj Parse Materials: Inspect mat:"arms" diffuse: "model/arm_dif.png" specular: "model/arm_showroom_spec.png" Inspect mat:"body" diffuse: "model/mat2_diffuse.png" specular: "model/mat2_specular.png" Inspect mat:"glass" diffuse: "model/glass_dif.png" Inspect mat:"hand" diffuse: "model/hand_dif.png" specular: "model/hand_showroom_spec.png" Inspect mat:"helmet" diffuse: "model/helmet_diff.png" specular: "model/helmet_showroom_spec.png" Inspect mat:"leg" diffuse: "model/leg_dif.png" specular: "model/leg_showroom_spec.png" 21:36:39: D:\plugin_dev\opengl\JSON_CP_01\JSON_Scene_Parse\JSON_Scene_Parse.exe exited with code 0
CP18:
locations debug;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/21. // #ifndef TRIANGLE_ALG_MODELDELEGATE_H #define TRIANGLE_ALG_MODELDELEGATE_H #include <string> #include <vector> #include "ALG_MeshDelegate.h" #include "ALG_LoadShader.h" #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster { using namespace std; // helper method for exchange aiMatrix to glm matrix void exchange_matrix_data(glm::mat4 &DesMatrix,const aiMatrix4x4 & srcAssimpMat); // ----------------------- SCENE LOCATION -------------------------------- struct SceneLocation{ // function SceneLocation(); ~SceneLocation(); // vars string pwd; glm::mat4 worldTransform; string type; // group or Mesh Mesh *mesh; }; SceneLocation::SceneLocation():pwd(""),worldTransform(1.0f),type("group"),mesh(nullptr){ } SceneLocation::~SceneLocation() { if(mesh) delete mesh; } // ----------------------- SCENE LOCATION -------------------------------- // ----------------------- SCENE Model -------------------------------- class Model{ public: //* Read Mesh from path */ Model() = default; explicit Model(const string& path); ~Model(); void readMesh(const string& path); //* overwrite all mesh material */ void assignMaterial(const LoadShader &shader); //* paint mesh in opengl */ void draw(); //* get the locations */ vector<SceneLocation*> getLocations(); // use default shader inline void useSimpleShader(){ cout << "Model Used basic shader that should call useSimpleShaderMatrix() in render loop !\n"; for(auto &loc :locations){ loc->mesh->shader.asSimpleShader(); } } inline void useSimpleShaderMatrix(glm::mat4 &proj, glm::mat4 &view, glm::mat4 &model){ for(auto &loc :locations){ loc->mesh->shader.use(); loc->mesh->shader.setMat4("projection", proj); loc->mesh->shader.setMat4("view", view); loc->mesh->shader.setMat4("model", model); } } inline void debugLocations(){ cout << "debug locations:\n"; cout << "{\n"; for(auto&loc : locations){ cout <<"\tSceneGraph:" <<loc->pwd <<"\tType:" <<loc->type << endl; } cout << "}\n"; } private: // vars vector<SceneLocation*> locations; string directory; // the mesh location at filesystem path // functions from assimp to our struct void processNode(aiNode *assimpNode,const aiScene* assimpScene, string pwd); Mesh* processMesh(aiMesh *assimpMesh, const aiScene *assimpScene); }; // constructor Model::Model(const string &path) { readMesh(path); } Model::~Model() { for(auto & location : locations){ delete location; } locations.clear(); } vector<SceneLocation *> Model::getLocations() { return this->locations; } void Model::draw(){ for_each(locations.begin(),locations.end(),[](SceneLocation* l){l->mesh->draw();}); } void Model::assignMaterial(const LoadShader &shader) { for(auto & location : locations){ location->mesh->assignMaterial(shader); } } void Model::readMesh(const string &path) { Assimp::Importer import; const aiScene * scene = import.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); // check error if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){ cout << "ERROR::ASSIMP:: " << import.GetErrorString() << endl; return ; } // retrieve the directory path of the filepath directory = path.substr(0, path.find_last_of('/')); // process ASSIMP's root node recursively processNode(scene->mRootNode, scene,"/"); } void Model::processNode(aiNode *assimpNode, const aiScene *assimpScene, string pwd) { // process each mesh located at the current node aiMatrix4x4 mat = assimpNode->mTransformation; auto *location = new SceneLocation; location->pwd = pwd; if (assimpNode->mNumMeshes<=0) location->type = "group"; else location->type = "mesh"; location->pwd = pwd; exchange_matrix_data(location->worldTransform,mat); // loop this node's meshs for(unsigned int i = 0; i < assimpNode->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* assimpMesh = assimpScene->mMeshes[assimpNode->mMeshes[i]]; Mesh* mesh = processMesh(assimpMesh,assimpScene); location->mesh = mesh; this->locations.emplace_back(location); } // after we've processed all of the meshes (if any) we then recursively process each of the children nodes for(unsigned int i = 0; i < assimpNode->mNumChildren; i++) { string pathName = pwd + assimpNode->mChildren[i]->mName.C_Str(); pathName += "/"; processNode(assimpNode->mChildren[i], assimpScene,pathName); } } Mesh* Model::processMesh(aiMesh *assimpMesh, const aiScene *assimpScene) { // our mesh interface pointer Mesh *mesh = new Mesh; // construct mesh data from assimpMesh for(unsigned int i =0; i <assimpMesh->mNumVertices;i++){ Vertex vertex; vertex.position.x= assimpMesh->mVertices[i].x; vertex.position.y= assimpMesh->mVertices[i].y; vertex.position.z= assimpMesh->mVertices[i].z; vertex.normal.x = assimpMesh->mNormals[i].x; vertex.normal.y = assimpMesh->mNormals[i].y; vertex.normal.z = assimpMesh->mNormals[i].z; // tex if(assimpMesh->mTextureCoords[0]) // does the mesh contain texture coordinates? { // 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). vertex.texCoords.x = assimpMesh->mTextureCoords[0][i].x; vertex.texCoords.y = assimpMesh->mTextureCoords[0][i].y; } else{ vertex.texCoords.x = 0.0f; vertex.texCoords.y = 0.0f; } // tangent vertex.tangent.x = assimpMesh->mTangents[i].x; vertex.tangent.y = assimpMesh->mTangents[i].y; vertex.tangent.z = assimpMesh->mTangents[i].z; // bitangent vertex.biTangent.x = assimpMesh->mBitangents[i].x; vertex.biTangent.y = assimpMesh->mBitangents[i].y; vertex.biTangent.z = assimpMesh->mBitangents[i].z; mesh->vertices.emplace_back(vertex); } // indices for(int i=0; i<assimpMesh->mNumFaces; i++){ aiFace face = assimpMesh->mFaces[i]; for(int j=0;j<face.mNumIndices;j++){ mesh->indices.emplace_back(face.mIndices[j]); } } mesh->setupMesh(); return mesh; } // ----------------------- SCENE Model -------------------------------- // ---- Helper void exchange_matrix_data(glm::mat4 &DesMatrix,const aiMatrix4x4 & srcAssimpMat){ DesMatrix[0].x = srcAssimpMat.a1; DesMatrix[0].y = srcAssimpMat.a2; DesMatrix[0].z = srcAssimpMat.a3; DesMatrix[0].w = srcAssimpMat.a4; DesMatrix[1].x = srcAssimpMat.b1; DesMatrix[1].y = srcAssimpMat.b2; DesMatrix[1].z = srcAssimpMat.b3; DesMatrix[1].w = srcAssimpMat.b4; DesMatrix[2].x = srcAssimpMat.c1; DesMatrix[2].y = srcAssimpMat.c2; DesMatrix[2].z = srcAssimpMat.c3; DesMatrix[2].w = srcAssimpMat.c4; DesMatrix[3].x = srcAssimpMat.d1; DesMatrix[3].y = srcAssimpMat.d2; DesMatrix[3].z = srcAssimpMat.d3; DesMatrix[3].w = srcAssimpMat.d4; } } // end of namespace #endif //TRIANGLE_ALG_MODELDELEGATE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef LOADSHADER_H #define LOADSHADER_H #include <GL/glew.h> #include <iostream> #include <fstream> #include <string> #include <sstream> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster{ using namespace std; // Shaders struct LoadShader { enum ShaderIOType{FILE,INLINE_DEFAULT_PROJECTION }; void compileShaderProgram(){ // create shader program and check it GLint success; GLchar infoLog[512]; shaderProgram = glCreateProgram(); glAttachShader(shaderProgram,vertexShader); glAttachShader(shaderProgram,fragmentShader); glLinkProgram(shaderProgram ); glGetProgramiv( shaderProgram, GL_LINK_STATUS, &success ); // Get Link Status if (!success) { glGetProgramInfoLog( shaderProgram, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } // Delete the shaders as they're linked into our program now and no longer necessery glDeleteShader( vertexShader ); glDeleteShader( fragmentShader ); } void compileVertexShader(string code){ vertexShader = glCreateShader( GL_VERTEX_SHADER ); const char * src = code.c_str(); glShaderSource( vertexShader, 1, &(src), NULL ); glCompileShader( vertexShader ); GLint success; GLchar infoLog[512]; glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &success ); if ( !success ) { glGetShaderInfoLog( vertexShader, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } } void compileFragmentShader(string code){ const char * src = code.c_str(); GLint success; GLchar infoLog[512]; fragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragmentShader, 1, &src, NULL ); glCompileShader( fragmentShader ); glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &success ); // Get Compile status if ( !success ) { glGetShaderInfoLog( fragmentShader, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } } LoadShader(){ } void asSimpleShader() { const char* vertexShaderSource = "#version 450 core\n" "layout (location = 0) in vec4 v_position;\n" "layout ( location = 1 ) in vec3 v_normal;\n" "layout ( location = 2 ) in vec2 v_texCoord;\n" "out vec4 myColor;\n" "uniform mat4 model;\n" "uniform mat4 view;\n" "uniform mat4 projection;\n" "void main()\n" "{\n" "gl_Position = projection * view * model * v_position;\n" "myColor = vec4(v_normal , 1);\n" "}\0"; const char* fragmentShaderSource = "#version 450 core\n" "out vec4 fColor;\n" "in vec4 myColor;\n" "void main()\n" "{\n" "fColor = myColor;\n" "}\n\0"; shaderIOType = INLINE_DEFAULT_PROJECTION; compileVertexShader(vertexShaderSource); compileFragmentShader(fragmentShaderSource); compileShaderProgram(); } void setShaderName(const string &name){ shaderName = name; } LoadShader(const char*vertPath, const char* fragPath){ load(vertPath,fragPath); shaderIOType = FILE; } string _readFile(const char *path){ ifstream stream; stringstream ss; stream.exceptions(ifstream::badbit); try { stream.open(path); // open file ss << stream.rdbuf(); // get strings from file } catch (ifstream::failure e) { cout << "ERROR::OPEN FILE:" << path << endl; } // close file handle stream.close(); // get str() from stringstream string shaderCode = ss.str(); return shaderCode; } void _loadVertexShader(const char *path){ // read shader code auto handle = _readFile(path); const char * shaderCode = handle.c_str(); compileVertexShader(shaderCode); } void _loadFragmentShader(const char *path){ // read shader code auto handle = _readFile(path); const char * shaderCode = handle.c_str(); compileFragmentShader(shaderCode); } void load(const char* vertShaderPath, const char* fragShaderPath){ shaderIOType = FILE; _loadVertexShader(vertShaderPath); _loadFragmentShader(fragShaderPath); // create shader program and check it compileShaderProgram(); } void use(){ glUseProgram(shaderProgram); } void setBool(const char *name, bool value) const { glUniform1i(glGetUniformLocation(shaderProgram, name), (int)value); } void setInt(const char *name, int value) const { glUniform1i(glGetUniformLocation(shaderProgram,name), value); } // ------------------------------------------------------------------------ void setFloat(const char *name, float value) const { glUniform1f(glGetUniformLocation(shaderProgram, name), value); } // ------------------------------------------------------------------------ void setVec2(const char *name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec2(const char *name, float x, float y) const { glUniform2f(glGetUniformLocation(shaderProgram,name), x, y); } // ------------------------------------------------------------------------ void setVec3(const char *name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec3(const char *name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(shaderProgram,name), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const char *name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec4(const char *name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(shaderProgram,name), x, y, z, w); } void setMat2(const char*name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name), 1, GL_FALSE,glm::value_ptr(mat)); } void setMat3(const char*name, const glm::mat3 &mat){ GLuint location = glGetUniformLocation(shaderProgram, name); glUniformMatrix3fv(location,1, GL_FALSE, &mat[0][0]); } void setMat4(const char *name , const glm::mat4 &mat){ GLuint location = glGetUniformLocation(shaderProgram, name); glUniformMatrix4fv(location,1, GL_FALSE, glm::value_ptr(mat)); } GLuint shaderProgram; GLuint vertexShader; GLuint fragmentShader; ShaderIOType shaderIOType; string shaderName; }; } #endif // LOADSHADER_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef WINDOW_H #define WINDOW_H #define GLEW_STATIC #include <GL/glew.h> #undef GLFW_DLL #include <GLFW/glfw3.h> class FrameWindow { public: FrameWindow(int width,int height,const char*title="OpenGL"); virtual ~FrameWindow(); GLFWwindow *getWindow(); private: GLFWwindow *window; int w; int h; }; FrameWindow::FrameWindow(int width,int height,const char*title){ w = width; h = height; glewInit(); glfwInit(); window = glfwCreateWindow(width,height,title,NULL,NULL); glfwMakeContextCurrent(window); } FrameWindow::~FrameWindow(){ glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow * FrameWindow::getWindow(){ return window; } #endif // WINDOW_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef MESH_H #define MESH_H #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <string> #include <vector> #include "ALG_LoadShader.h" #include <GL/glew.h> namespace AlgebraMaster { using namespace std; struct Vertex{ glm::vec3 position; glm::vec3 normal; glm::vec2 texCoords; glm::vec3 tangent; glm::vec3 biTangent; }; struct Texture{ // Reference houdini principledshader enum Type { BASECOLOR_MAP, SPECULAR_MAP, EMISSION_MAP, BUMP_MAP, NORMAL_MAP, IOR_MAP, OPACITY_MAP, DISPLACE_MAP, CHAN_TEX0,CHAN_TEX1,CHAN_TEX2,CHAN_TEX3, CHAN_TEX4,CHAN_TEX5,CHAN_TEX6,CHAN_TEX7, CHAN_TEX8,CHAN_TEX9_CHAN_TEX10 }; unsigned int id; string path; Type texType; }; struct Mesh { public: Mesh()= default; //* constructor */ Mesh(const vector<Vertex> &vts, const vector<unsigned int>ids, const vector<Texture> &texs); // rendering data vector<Vertex> vertices; vector<unsigned int> indices; vector<Texture> textures; // ogl unsigned int VAO,VBO,EBO; // vertex array buffer //* this method need called manually */ void setupMesh(); // ogl draw void draw(); // shader LoadShader shader; // get mat from outside void assignMaterial(const LoadShader & rhs_shader); }; Mesh::Mesh(const vector<Vertex> &vts, const vector<unsigned int>ids, const vector<Texture> &texs):vertices(vts),indices(ids),textures(texs){ } void Mesh::assignMaterial(const LoadShader &rhs_shader) { shader.fragmentShader = rhs_shader.fragmentShader; shader.vertexShader = rhs_shader.vertexShader; shader.shaderProgram = rhs_shader.shaderProgram; } // opengl draw the mesh void Mesh::draw() { this->shader.use(); string mat_prefix = "material."; for(int i=0;i<textures.size();i++){ glActiveTexture(GL_TEXTURE0 + i); switch (this->textures[i].texType) { case Texture::BASECOLOR_MAP:{ string texchanName = mat_prefix + "diffuse_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::SPECULAR_MAP:{ string texchanName = mat_prefix + "specular_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::EMISSION_MAP:{ string texchanName = mat_prefix + "emission_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::BUMP_MAP:{ string texchanName = mat_prefix + "bump_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::NORMAL_MAP:{ string texchanName = mat_prefix + "normal_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::IOR_MAP:{ string texchanName = mat_prefix + "ior_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::OPACITY_MAP:{ string texchanName = mat_prefix + "opacity_map"; shader.setInt(texchanName.c_str(),i); break; } case Texture::DISPLACE_MAP:{ string texchanName = mat_prefix + "displace_map"; shader.setInt(texchanName.c_str(),i); break; } default: break; } // end of switch glBindTexture(GL_TEXTURE_2D, textures[i].id); // bind current id } // end of for each textures // draw mesh glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); // always good practice to set everything back to defaults once configured. glActiveTexture(GL_TEXTURE0); } // init our mesh data void Mesh::setupMesh() { glCreateVertexArrays(1,&VAO); // vertex array object glCreateBuffers(1,&VBO); // vertex buffer object glCreateBuffers(1,&EBO); // vertex element array buffer object glBindVertexArray(VAO); // bind vertex array glBindBuffer(GL_ARRAY_BUFFER,VBO); // bind vertex buffer glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); // vertex attributes // position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); // normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 3*sizeof(float)) ); //tex glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 6*sizeof(float)) ); //tangent glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 8*sizeof(float)) ); // bitangent glEnableVertexAttribArray(4); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 11*sizeof(float)) ); glBindVertexArray(0); } } // end of namespace #endif // MESH_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef LOADTEXTURE_H #define LOADTEXTURE_H #include <GL/glew.h> // IMP the stb image loader #define STB_IMAGE_IMPLEMENTATION #include <stb_image.h> #include <iostream> using namespace std; namespace AlgebraMaster { class LoadTexture { public: LoadTexture()=default; LoadTexture(const char *fileName); void load(const char *fileName); virtual ~LoadTexture(); inline GLuint getTextureID(){return textureID;} inline GLuint getImageFormat(){return format;} private: GLuint textureID; GLenum format; }; void LoadTexture::load(const char *fileName) { glGenTextures(1, &textureID); int width, height, nrComponents; unsigned char *data = stbi_load(fileName, &width, &height, &nrComponents, 0); if (data) { if (nrComponents == 1) format = GL_RED; else if (nrComponents == 3) format = GL_RGB; else if (nrComponents == 4) format = GL_RGBA; glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); 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_MIPMAP_LINEAR); stbi_image_free(data); } else { std::cout << "Texture failed to load at path: " << fileName << std::endl; stbi_image_free(data); } } LoadTexture::LoadTexture(const char *fileName){ load(fileName); } LoadTexture::~LoadTexture(){} } #endif // LOADTEXTURE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef GLFWCAMERA_H #define GLFWCAMERA_H #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster{ class GLFWCamera{ public: GLFWCamera(); ~GLFWCamera(){} enum CAMERA_MOVEMENT{ FORWARD, // Camera move to front -> key:W BACKWARD, // Camera move to back -> key:S LEFT, // Camera move to left -> key:A RIGHT // Camera move to right -> key:D }; public: glm::vec3 pos; // camera world space glm::vec3 front; glm::vec3 up; // Euler Angles float yaw; float pitch; // Camera options float movementSpeed; float mouseSensitivity; float fov; void processFov(float yoffset){ if(fov >= 1.0f && fov <= 45.0f){ fov -= yoffset; } if(fov <=1.0f){ fov = 1.0f; } if(fov >= 45.0f){ fov = 45.0f; } } // build the matrix for lookAt glm::mat4 GetViewMatrix(){ return glm::lookAt(pos , pos + front , up); } // process -Rotate the view- void processMouseMove(float xoffset, float yoffset); // process -W S A D- void processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir); void updateFront(){ glm::vec3 tempfront; tempfront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); tempfront.y = sin(glm::radians(pitch)); tempfront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); this->front = glm::normalize(tempfront); } }; GLFWCamera::GLFWCamera(){ pos = glm::vec3(0.0f,0.0f,3.0f); up = glm::vec3(0.0f,1.0f,0.0f); front = glm::vec3(0.0f,0.0f,-1.0f); yaw = -90.0f; pitch = 0.0f; fov = 45.0f; movementSpeed = 4.5f; mouseSensitivity = 0.1f; } void GLFWCamera::processMouseMove(float xoffset, float yoffset) { xoffset *= mouseSensitivity; yoffset *= mouseSensitivity; yaw += xoffset; pitch += yoffset; // make sure that when pitch is out of bounds, screen doesn't get flipped if (pitch > 89.0f) pitch = 89.0f; if (pitch < -89.0f) pitch = -89.0f; this->updateFront(); } void GLFWCamera::processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir) { float vel = movementSpeed * delta; switch (moveDir) { case FORWARD: { pos += vel * front; break; } case BACKWARD: { pos -= vel * front; break; } case LEFT: { pos -= glm::normalize(glm::cross(front, up)) * vel; break; } case RIGHT: { pos += glm::normalize(glm::cross(front, up)) * vel; } default: break; } } } #endif // GLFWCAMERA_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#define GLEW_STATIC // GLEW #include <GL/glew.h> #include <cstdlib> #undef GLFW_DLL // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "ALG_LoadShader.h" #include "ALG_LoadTexture.h" #include "ALG_GLFWCamera.h" #include "ALG_FrameWindow.h" #include "ALG_ModelDelegate.h" #include <cmath> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> using namespace AlgebraMaster; const unsigned int SRC_WIDTH = 1400; const unsigned int SRC_HEIGHT = 720; static GLuint cubeVAO,VBO; static GLuint lightVAO; //VBO stays the same; the vertices are the same for the light object which is also a 3D cube static LoadShader SurfaceShader; void init(); void display(); void processInput(GLFWwindow *window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); // camera static GLFWCamera *camera; static float lastX = float(SRC_WIDTH) / 2.0f; static float lastY = float(SRC_HEIGHT) / 2.0f; static bool firstMouse = true; static bool firstMiddowMouse = true; // timing static float deltaTime = 0.0f; // time between current frame and last frame static float lastFrame = 0.0f; // light define static glm::vec3 lightPos(0.0f, 4.0f,-2.0f); Model nanosuit_model; void init(){ camera = new GLFWCamera; camera->pos.y = 10.0f; camera->pos.z = 25.0f; // GL depth zbuffer glEnable(GL_DEPTH_TEST); //SurfaceShader.load("shaders/SurfaceShader.vert","shaders/SurfaceShader.frag"); nanosuit_model.readMesh("scene/model/nanosuit.obj"); nanosuit_model.useSimpleShader(); nanosuit_model.debugLocations(); //nanosuit_model.assignMaterial(SurfaceShader); } // ----------- Render Loop ---------- void display(){ // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // object .vert settings glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f); glm::mat4 view = camera->GetViewMatrix(); // object world transformation glm::mat4 model = glm::mat4(1.0f); nanosuit_model.useSimpleShaderMatrix(projection,view,model); //SurfaceShader.setMat4("projection", projection); //SurfaceShader.setMat4("view", view); //SurfaceShader.setMat4("model", model); nanosuit_model.draw(); } int main() { glfwInit(); FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT); glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback); glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback); glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback); init(); // RENDER-------------- while(!glfwWindowShouldClose(FrameWindow.getWindow())){ processInput(FrameWindow.getWindow()); display(); glfwSwapBuffers(FrameWindow.getWindow()); glfwPollEvents(); } delete camera; return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT); } // ROTATE VIEW DIR void mouse_callback(GLFWwindow* window, double xpos, double ypos){ int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE); int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT); int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT); // set up the camera view if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS) { if (firstMouse){ lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->processMouseMove(xoffset,yoffset); } if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){ firstMouse = true; } // Move Camera Position if( middow_mouse_state == GLFW_PRESS) { if (firstMiddowMouse){ lastX = xpos; lastY = ypos; firstMiddowMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->pos.x += xoffset*0.01f; camera->pos.y += yoffset*0.01f; } if ( middow_mouse_state == GLFW_RELEASE){ firstMiddowMouse = true; } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){ camera->processFov(yoffset); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
cmake_minimum_required(VERSION 3.5) project(Triangle) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # OPENGL find_package(OpenGL REQUIRED) include_directories(${OpenGL_INCLUDE_DIRS}) link_directories(${OpenGL_LIBRARY_DIRS}) add_definitions(${OpenGL_DEFINITIONS}) if(NOT OPENGL_FOUND) message(ERROR " OPENGL not found!") endif(NOT OPENGL_FOUND) # GLEW set(GLEW_HOME D:/plugin_dev/libs/glew-2.1.0) include_directories(${GLEW_HOME}/include) link_directories(${GLEW_HOME}/lib/Release/x64) # GLFW set(GLFW_HOME D:/plugin_dev/libs/glfw-3.3.1.bin.WIN64) include_directories(${GLFW_HOME}/include/) link_directories(${GLFW_HOME}/lib-vc2019) # STB include_directories(D:/plugin_dev/libs/stb) # GLM include_directories(D:/plugin_dev/libs/GLM_include) # Assimp include_directories(D:/plugin_dev/libs/assimp-5.0.1_bin/win_vs2019/include) if(CMAKE_BUILD_TYPE STREQUAL Debug) message(">> Cmake will use debug mode to link debug lib") link_directories(D:/plugin_dev/libs/assimp-5.0.1_bin/win_vs2019/Debug) # we first link the debug link_libraries(assimp-vc142-mtd) else() link_directories(D:/plugin_dev/libs/assimp-5.0.1_bin/win_vs2019/Release) # we first link the debug link_libraries(assimp-vc142-mt) endif() #json include_directories(D:/plugin_dev/libs/nlohmann) # output excutable dir set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build) # SRC FILE FILE( GLOB SRC *.cpp *.h ) add_executable(Triangle ${SRC} ALG_SceneDelegate.h) target_link_libraries(Triangle glew32s.lib glfw3 opengl32 )
CP19:
只做了个描述diffuse贴图的,其他的通道跟灯光有关系,普通的烂灯光,烂材质懒的写。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "name": "simple", "project_dir": "D:/plugin_dev/opengl/CP_19/Triangle/build/scene", "models": [ "model/nanosuit.obj" ], "mats": { "glass": { "shader_define": { "___comment___1": "type=0 is default no texture shader; ", "___comment___2": "type=1 use inline texture; ", "___comment___3": "type=2 use our json code shader,this may be use in our ui ", "___comment___4": "type=3 from file", "vert_file": "", "frag_file": "", "code_type": 1, "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/glass_dif.png" } }, "leg": { "shader_define": { "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/leg_dif.png", "specular": "model/leg_showroom_spec.png" } }, "hand": { "shader_define": { "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/hand_dif.png", "specular": "model/hand_showroom_spec.png" } }, "body": { "shader_define": { "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/mat2_diffuse.png", "specular": "model/mat2_specular.png" } }, "helmet": { "shader_define": { "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/helmet_diff.png", "specular": "model/helmet_showroom_spec.png" } }, "arms": { "shader_define": { "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "diffuse": "model/arm_dif.png", "specular": "model/arm_showroom_spec.png" } } }, "assignMaterial": { "/Visor": "glass", "/Lights": "glass", "/Legs": "leg", "/hands": "hand", "/Arms": "arms", "/Helmet": "helmet", "/Body": "body" }, "lights": { "lgt1": { "shader_define": { "lightType": "pointLight", "code_type": 1, "vert_file": "", "frag_file": "", "frag_code": "", "vert_code": "" }, "params_define": { "pos" : [0.0, 10.0, 0.0], "sensitive" : 1.0, "color": [1.0, 0.0, 0.0] } }, "lgt2": { "shader_define": { "lightType": "pointLight", "vert_file": "", "frag_file": "", "code_type": 1, "frag_code": "", "vert_code": "" }, "params_define": { "pos" : [0.0, 10.0, 0.0], "sensitive" : 1.0, "color": [1.0, 0.0, 0.0] } }, "lgt3": { "shader_define": { "lightType": "dirLight", "code_type": 1, "frag_code": "", "vert_code": "" }, "params_define": { "pos" : [0.0, 10.0, 0.0], "sensitive" : 1.0, "color": [1.0, 0.0, 0.0], "dir": [1.0, -1.0, 0.0] } } }, "assignLights":{ "/lights/light1": "lgt1", "/lights/light2": "lgt2", "/lights/light3": "lgt3" } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#define GLEW_STATIC // GLEW #include <GL/glew.h> #include <cstdlib> #undef GLFW_DLL // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "ALG_LoadShader.h" #include "ALG_LoadTexture.h" #include "ALG_GLFWCamera.h" #include "ALG_FrameWindow.h" #include "ALG_ModelDelegate.h" #include "ALG_SceneDelegate.h" #include "ALG_DrawGrid.h" #include <cmath> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> using namespace AlgebraMaster; const unsigned int SRC_WIDTH = 1400; const unsigned int SRC_HEIGHT = 720; static GLuint cubeVAO,VBO; static GLuint lightVAO; //VBO stays the same; the vertices are the same for the light object which is also a 3D cube static LoadShader SurfaceShader; void init(); void display(); void processInput(GLFWwindow *window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); // camera static GLFWCamera *camera; static float lastX = float(SRC_WIDTH) / 2.0f; static float lastY = float(SRC_HEIGHT) / 2.0f; static bool firstMouse = true; static bool firstMiddowMouse = true; // timing static float deltaTime = 0.0f; // time between current frame and last frame static float lastFrame = 0.0f; // light define static glm::vec3 lightPos(0.0f, 4.0f,-2.0f); static Scene scene; static DrawGrid grid; void init(){ camera = new GLFWCamera; camera->pos.y = 5.0f; camera->pos.z = 25.0f; // GL depth zbuffer glEnable(GL_DEPTH_TEST); //SurfaceShader.load("shaders/SurfaceShader.vert","shaders/SurfaceShader.frag"); scene.read("scene/scene.json"); scene.parseInitialize(); scene.parseModel(); scene.parseMats(); scene.parseAssignMats(); grid.initialize(); } // ----------- Render Loop ---------- void display(){ // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // object .vert settings glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f); glm::mat4 view = camera->GetViewMatrix(); // object world transformation glm::mat4 model = glm::mat4(1.0f); scene.setMatrix(projection,view,model); //SurfaceShader.setMatrix(model,view,projection); //scene.assignMaterial(SurfaceShader); scene.draw(); grid.draw(projection,view); } int main() { glfwInit(); FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT); glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback); glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback); glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback); init(); // RENDER-------------- while(!glfwWindowShouldClose(FrameWindow.getWindow())){ processInput(FrameWindow.getWindow()); display(); glfwSwapBuffers(FrameWindow.getWindow()); glfwPollEvents(); } delete camera; return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT); } // ROTATE VIEW DIR void mouse_callback(GLFWwindow* window, double xpos, double ypos){ int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE); int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT); int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT); // set up the camera view if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS) { if (firstMouse){ lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->processMouseMove(xoffset,yoffset); } if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){ firstMouse = true; } // Move Camera Position if( middow_mouse_state == GLFW_PRESS) { if (firstMiddowMouse){ lastX = xpos; lastY = ypos; firstMiddowMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->pos.x += xoffset*0.01f; camera->pos.y += yoffset*0.01f; } if ( middow_mouse_state == GLFW_RELEASE){ firstMiddowMouse = true; } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){ camera->processFov(yoffset); }
其他的代码可以看下面CP20。
CP20:
透明,透明只跟绘制顺序相关。
比如这个我先绘制我的网格,然后绘制我的立方体,最后对透明物体排序。
然后开启这些脑残特性,
// GL depth zbuffer glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#version 450 core // Final Color To export out vec4 FragColor; // from vert shader in vec3 f_Normal; in vec2 f_TexCoord; in vec3 f_Pos; // fragment position uniform sampler2D diffuse_map; void main() { vec4 df = texture(diffuse_map, f_TexCoord); FragColor = df; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#version 450 core // INCOMING DATA layout ( location = 0 ) in vec4 v_position; // pos //layout ( location = 1 ) in vec3 v_normal; // norm layout ( location = 1 ) in vec2 v_texCoord; // st // define out data out vec2 f_TexCoord; // normal at world matrix, we direct from C++ calcalation out vec3 f_Normal; // to world matrix : mat3( transpose(inverse(model)) ) * v_normal; out vec3 f_Pos; // INCOMING THE MATRIX FROM CLIENT to transform the gl point position uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ // Transform the world matrix to view matrix gl_Position = projection * view * model * v_position; //f_Normal = mat3(transpose(inverse(model))) * v_normal; // f_Normal at world matrix f_TexCoord = v_texCoord; // out TexCoord f_Pos = vec3(model *v_position); // out fragment position }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/27. // #ifndef TRIANGLE_OGLHELPER_H #define TRIANGLE_OGLHELPER_H #define GLEW_STATIC #include <GL/glew.h> void CreateGeometryBuffer(unsigned int &VAO, unsigned int &VBO); void CreateGeometryBuffer(unsigned int &VAO, unsigned int &VBO){ glCreateVertexArrays(1, &VAO); glCreateBuffers(1,&VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); } #endif //TRIANGLE_OGLHELPER_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/25. // #ifndef TRIANGLE_ALG_VERTEX_H #define TRIANGLE_ALG_VERTEX_H #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster { using namespace std; struct Vertex { glm::vec3 position; glm::vec3 normal; glm::vec2 texCoords; glm::vec3 tangent; glm::vec3 biTangent; }; } #endif //TRIANGLE_ALG_VERTEX_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/25. // #ifndef TRIANGLE_ALG_TEXTURE_H #define TRIANGLE_ALG_TEXTURE_H #include <iostream> namespace AlgebraMaster{ using namespace std; struct Texture{ // Reference houdini principledshader enum Type { BASECOLOR_MAP, SPECULAR_MAP, EMISSION_MAP, BUMP_MAP, NORMAL_MAP, IOR_MAP, OPACITY_MAP, DISPLACE_MAP, CHAN_TEX0,CHAN_TEX1,CHAN_TEX2,CHAN_TEX3, CHAN_TEX4,CHAN_TEX5,CHAN_TEX6,CHAN_TEX7, CHAN_TEX8,CHAN_TEX9_CHAN_TEX10 }; unsigned int id; // glBindTexture(GL_TEXTURE_2D,id); unsigned int textureUnitID; // for shaderMethod set the texture unit: gluniformli(location, texture_unit) string path; // ralative path Type texType; // type unsigned int texChannel; // glActiveTexture(texChannel); }; } #endif //TRIANGLE_ALG_TEXTURE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by Admin on 2020/2/23. // #ifndef TRIANGLE_ALG_SCENEDELEGATE_H #define TRIANGLE_ALG_SCENEDELEGATE_H #include <iostream> #include <json.hpp> #include <string> #include <fstream> #include <iomanip> #include <vector> #include "ALG_LoadShader.h" #include "ALG_ModelDelegate.h" #include "ALG_LoadTexture.h" #include "ALG_MeshDelegate.h" // texture struct namespace AlgebraMaster{ // namespace using namespace std; using json = nlohmann::json; // bool checkJsonError(json &j,string msg); bool checkJsonError(json &j,string msg) { if (j.is_null()) { cout << "ERROR JSON:" << msg<<endl; return true; } return false; } template <typename T> void FreeSTLMemory(T & container); template <typename T> void FreeSTLMemory(T & container){ // release mats mem for(auto &c: container){ delete c; } container.clear(); } Texture *CreateTexture(const LoadTexture &textureLoader, const string &relativeTexturePath, Texture::Type type, unsigned int textureChannel, unsigned int textureUnitID); Texture *CreateTexture(const LoadTexture &textureLoader, const string &relativeTexturePath, Texture::Type type, unsigned int textureChannel, unsigned int textureUnitID) { // create texture object auto *texture = new Texture; // Create our texture object texture->id = textureLoader.getTextureID(); // Assign GL_TextureID to our texture object texture->texType = type; // set texture type texture->path = relativeTexturePath; // set texture path is relative texture->texChannel = textureChannel; texture->textureUnitID = textureUnitID; //current unique texture unit return texture; } //* scene description from json object/ class Scene{ public: Scene(); virtual ~Scene(); void read(const string &path); void save(const string &path)const; virtual void draw(); string getSceneName()const; void setSceneName(const string &name); Texture * getTextureByPath(const string &path){ for(auto &t: allTextures){ if(t->path == path)return t; } return nullptr; } vector<LoadShader *> allShaders; vector<Texture*> allTextures; // all texture from json file , this index will as GL_activeTexture(TEXTURE0+i) LoadShader* getShaderByName(const string &name){ for(auto &m : allShaders){ if(m->shaderName == name) return m; } return nullptr; } void debugShaders(){ for(auto &s: allShaders){ cout <<"Scene::debugShaders debug shader pool have:" << s->shaderName <<endl; } } void parseInitialize(); // read mesh void parseModel(); void parseMats(); void parseAssignMats(); void setMatrix(glm::mat4 &proj , glm::mat4 & view , glm::mat4 model = glm::mat4(1.0f)); //override all model mats void assignMaterial(LoadShader &shader){ for(auto &m : allModels){ m->assignMaterial(shader); } } private: // * scene description json obj */ json j; vector<Model*> allModels; // proj string project_dir; // bool textureIsLoaded(const string &texturePath); public: static int currentActiveTextureChannel; static int currentTextureLoaderIndex; }; int Scene::currentActiveTextureChannel = GL_TEXTURE0; int Scene::currentTextureLoaderIndex = 0; // ------------------ DEFINE FUNCTION -------------------------- Scene::Scene(){ } Scene::~Scene() { // release mats mem cout << "---------------Memory Release----------------------\n"; cout << "free model's mem \n"; FreeSTLMemory(allModels); // cout << "free all textures mem \n"; FreeSTLMemory(allTextures); // cout << "free all shaders mem \n"; FreeSTLMemory(allShaders); cout << "---------------Memory Release----------------------\n"; } bool Scene::textureIsLoaded(const string &texturePath) { bool isLoaded = false; for(auto &tex: allTextures){ if (tex->path == texturePath){ isLoaded = true; } } return isLoaded; } void Scene::setMatrix(glm::mat4 &proj , glm::mat4 &view , glm::mat4 model) { for(auto &mod :allModels){ for(auto &loc: mod->getLocations()) { loc->mesh->shader.setMatrix(model, view, proj); } } } // Read File void Scene::read(const string &path) { ifstream in(path.c_str()); in >> j; } // Write File void Scene::save(const string &path) const{ // write prettified JSON to another file ofstream o(path.c_str()); o << setw(4) << j << std::endl; } string Scene::getSceneName() const { auto name = j["name"]; if( name){ return name; } return "ERROR SCENE NAME"; } void Scene::setSceneName(const string &name) { j["name"] = name; } void Scene::draw() { for(auto &m : allModels){ m->draw(); } } void Scene::parseInitialize() { string temp_proj_dir = j["project_dir"]; temp_proj_dir += "/"; project_dir = temp_proj_dir; } void Scene::parseModel() { cout << j["models"] <<endl; for(string path :j["models"]){ auto *model = new Model; string absPath = project_dir + path; cout << "Scene Parse Read mesh:" << absPath <<endl; model->readMesh(absPath); this->allModels.emplace_back(model); } } void Scene::parseMats() { json mats = j["mats"]; for (auto& mat : mats.items()) { json matNameObject = mat.key(); // json mat name json matContentObject = mat.value(); // json tex json shaderDefineObject = matContentObject["shader_define"]; json codeTypeObject = shaderDefineObject["code_type"]; json fragCodeObject = shaderDefineObject["frag_code"]; json vertCodeObject = shaderDefineObject["vert_code"]; auto *shader = new LoadShader; bool jsonIsError = false; // if is error , create default mat jsonIsError = checkJsonError(shaderDefineObject,"Can not find key ->shader_define ,create default color shader"); if(jsonIsError) { shader->asSimpleShader(); return; } jsonIsError = checkJsonError(codeTypeObject,"Can not find key ->code_type ,create default color shader"); if(jsonIsError){ shader->asSimpleShader(); return; } jsonIsError = checkJsonError(fragCodeObject,"Can not find key ->frag_code ,create default color shader"); if(jsonIsError){ shader->asSimpleShader(); return; } jsonIsError = checkJsonError(vertCodeObject,"Can not find key ->vert_code ,create default color shader"); if(jsonIsError){ shader->asSimpleShader(); return; } // JSON shader_define values string std_strMatName = matNameObject.get<string>(); // mat name int codeType = codeTypeObject.get<int>(); string fragCode = fragCodeObject.get<string>(); string vertCode = vertCodeObject.get<string>(); cout << "system create mat:" << std_strMatName << " codeType:" <<codeType <<endl; switch (codeType) { case 0: { shader->asSimpleShader(); shader->shaderName = std_strMatName; break; } case 1: { shader->asSimpleTextureShader(); shader->shaderName = std_strMatName; break; } case 2: { shader->fromSrc(vertCode,fragCode); shader->shaderName = std_strMatName; break; } default: // create in line shader shader->asSimpleShader(); shader->shaderName = std_strMatName; break; } // shader param define json paramDefineObject = matContentObject["params_define"]; for(auto ¶ms: paramDefineObject.items()) { json paramNameObject = params.key(); json valueObject = params.value(); // may be relative texture path , or shader value string paramName = paramNameObject.get<string>(); if(paramName == "diffuse") { string texRelativePath = valueObject.get<string>(); string texAbsPath = project_dir + texRelativePath; // create texture loader LoadTexture textureLoader; textureLoader.load(texAbsPath.c_str()); // if texture load error, pass this loading if (!textureLoader.loadStatus) continue; // if this texture have loaded if (textureIsLoaded(texRelativePath)) { shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader continue; } unsigned int texChannel = Scene::currentActiveTextureChannel; unsigned int textureUnitID = Scene::currentTextureLoaderIndex; //current unique texture unit Texture *tex = CreateTexture(textureLoader,texRelativePath, Texture::BASECOLOR_MAP, texChannel, textureUnitID); cout << "OPENGL->register <diffuse> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl; Scene::currentTextureLoaderIndex+=1; Scene::currentActiveTextureChannel+=1; allTextures.emplace_back(tex); shader->textures.emplace_back(tex);// make connection with pair shader } if(paramName == "specular") { string texRelativePath = valueObject.get<string>(); string texAbsPath = project_dir + texRelativePath; // create texture loader LoadTexture textureLoader; textureLoader.load(texAbsPath.c_str()); // if texture load error, pass this loading if (!textureLoader.loadStatus) continue; // if this texture have loaded if (textureIsLoaded(texRelativePath)){ shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader continue; } unsigned int texChannel = Scene::currentActiveTextureChannel; unsigned int textureUnitID = Scene::currentTextureLoaderIndex; //current unique texture unit Texture *tex = CreateTexture(textureLoader,texRelativePath, Texture::SPECULAR_MAP, texChannel, textureUnitID); cout << "OPENGL->register <specular> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl; Scene::currentTextureLoaderIndex+=1; Scene::currentActiveTextureChannel+=1; allTextures.emplace_back(tex); shader->textures.emplace_back(tex);// make connection with pair shader } } // end of mat param settings allShaders.emplace_back(shader); // place shader in our container }//end of loop material } void Scene::parseAssignMats() { // loop all model json matTree = j["assignMaterial"]; for(auto &tree: matTree.items()){ json locationPWDObject = tree.key(); json locationMatNameObject = tree.value(); string locationPWD = locationPWDObject.get<string>(); string locationMatName = locationMatNameObject.get<string>(); LoadShader *shader = getShaderByName(locationMatName); if (!shader){ cout << "ERROR Try to assign:"<< locationPWD <<",But can not find material in material pool:" << locationMatName <<endl; continue; } // loop all model, find the location for(auto &model: allModels){ SceneLocation *loc = model->getLocationByPath(locationPWD); loc->mesh->assignMaterial(*shader); cout << "!!!!!!!!!!!!!!!!!!!!!assign:" << shader->shaderName << " to:" << loc->pwd <<endl; } } } }// end of namespace #endif //TRIANGLE_ALG_SCENEDELEGATE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/21. // #ifndef TRIANGLE_ALG_MODELDELEGATE_H #define TRIANGLE_ALG_MODELDELEGATE_H #include <string> #include <vector> #include "ALG_MeshDelegate.h" #include "ALG_LoadShader.h" #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster { using namespace std; // helper method for exchange aiMatrix to glm matrix void exchange_matrix_data(glm::mat4 &DesMatrix,const aiMatrix4x4 & srcAssimpMat); // ----------------------- SCENE LOCATION -------------------------------- struct SceneLocation{ // function SceneLocation(); ~SceneLocation(); // vars string pwd; glm::mat4 worldTransform; string type; // group or Mesh Mesh *mesh; }; SceneLocation::SceneLocation():pwd(""),worldTransform(1.0f),type("group"),mesh(nullptr){ } SceneLocation::~SceneLocation() { if(mesh) delete mesh; } // ----------------------- SCENE LOCATION -------------------------------- // ----------------------- SCENE Model -------------------------------- class Model{ public: //* Read Mesh from path */ Model() = default; explicit Model(const string& path); ~Model(); void readMesh(const string& path); //* overwrite all mesh material */ void assignMaterial(LoadShader &shader); //* paint mesh in opengl */ void draw(); //* get the locations */ vector<SceneLocation*> &getLocations(); //* get location by name / SceneLocation * getLocationByPath(const string &path); // use default shader inline void useSimpleShader(){ cout << "Model Used basic shader that should call useSimpleShaderMatrix() in render loop !\n"; for(auto &loc :locations){ loc->mesh->shader.asSimpleShader(); } } inline void useSimpleShaderMatrix(glm::mat4 &proj, glm::mat4 &view, glm::mat4 &model){ for(auto &loc :locations){ loc->mesh->shader.use(); loc->mesh->shader.setMat4("projection", proj); loc->mesh->shader.setMat4("view", view); loc->mesh->shader.setMat4("model", model); } } inline void debugLocations(){ cout << "debug locations:\n"; cout << "{\n"; for(auto&loc : locations){ cout <<"\tSceneGraph:" <<loc->pwd <<"\tType:" <<loc->type << endl; } cout << "}\n"; } private: // vars vector<SceneLocation*> locations; string directory; // the mesh location at filesystem path // functions from assimp to our struct void processNode(aiNode *assimpNode,const aiScene* assimpScene, string pwd); Mesh* processMesh(aiMesh *assimpMesh, const aiScene *assimpScene); }; // constructor Model::Model(const string &path) { readMesh(path); } Model::~Model() { for(auto & location : locations){ delete location; } locations.clear(); } vector<SceneLocation *> &Model::getLocations() { return this->locations; } SceneLocation * Model::getLocationByPath(const string &path){ for(auto &loc: this->locations){ if(loc->pwd == path)return loc; } return nullptr; } void Model::draw(){ for(auto &loc: locations){ loc->mesh->draw(); } } void Model::assignMaterial(LoadShader &shader) { for(auto & location : locations){ location->mesh->assignMaterial(shader); } } void Model::readMesh(const string &path) { Assimp::Importer import; const aiScene * scene = import.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); // check error if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){ cout << "ERROR::ASSIMP:: " << import.GetErrorString() << endl; return ; } // retrieve the directory path of the filepath directory = path.substr(0, path.find_last_of('/')); // process ASSIMP's root node recursively processNode(scene->mRootNode, scene,"/"); // fix location pwd end with '/', we should remove it for(auto &loc : locations){ string pwd = loc->pwd; if (pwd[pwd.length()-1] == '/'){ loc->pwd = string(pwd.begin(),pwd.end()-1); } } } void Model::processNode(aiNode *assimpNode, const aiScene *assimpScene, string pwd) { // process each mesh located at the current node aiMatrix4x4 mat = assimpNode->mTransformation; auto *location = new SceneLocation; location->pwd = pwd; if (assimpNode->mNumMeshes<=0) location->type = "group"; else location->type = "mesh"; location->pwd = pwd; exchange_matrix_data(location->worldTransform,mat); // loop this node's meshs for(unsigned int i = 0; i < assimpNode->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* assimpMesh = assimpScene->mMeshes[assimpNode->mMeshes[i]]; Mesh* mesh = processMesh(assimpMesh,assimpScene); location->mesh = mesh; this->locations.emplace_back(location); } // after we've processed all of the meshes (if any) we then recursively process each of the children nodes for(unsigned int i = 0; i < assimpNode->mNumChildren; i++) { string pathName = pwd + assimpNode->mChildren[i]->mName.C_Str(); pathName += "/"; processNode(assimpNode->mChildren[i], assimpScene,pathName); } } Mesh* Model::processMesh(aiMesh *assimpMesh, const aiScene *assimpScene) { // our mesh interface pointer Mesh *mesh = new Mesh; // construct mesh data from assimpMesh for(unsigned int i =0; i <assimpMesh->mNumVertices;i++){ Vertex vertex; vertex.position.x= assimpMesh->mVertices[i].x; vertex.position.y= assimpMesh->mVertices[i].y; vertex.position.z= assimpMesh->mVertices[i].z; vertex.normal.x = assimpMesh->mNormals[i].x; vertex.normal.y = assimpMesh->mNormals[i].y; vertex.normal.z = assimpMesh->mNormals[i].z; // tex if(assimpMesh->mTextureCoords[0]) // does the mesh contain texture coordinates? { // a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't // use allModels where a vertex can have multiple texture coordinates so we always take the first set (0). vertex.texCoords.x = assimpMesh->mTextureCoords[0][i].x; vertex.texCoords.y = assimpMesh->mTextureCoords[0][i].y; } else{ vertex.texCoords.x = 0.0f; vertex.texCoords.y = 0.0f; } // tangent vertex.tangent.x = assimpMesh->mTangents[i].x; vertex.tangent.y = assimpMesh->mTangents[i].y; vertex.tangent.z = assimpMesh->mTangents[i].z; // bitangent vertex.biTangent.x = assimpMesh->mBitangents[i].x; vertex.biTangent.y = assimpMesh->mBitangents[i].y; vertex.biTangent.z = assimpMesh->mBitangents[i].z; mesh->vertices.emplace_back(vertex); } // indices for(int i=0; i<assimpMesh->mNumFaces; i++){ aiFace face = assimpMesh->mFaces[i]; for(int j=0;j<face.mNumIndices;j++){ mesh->indices.emplace_back(face.mIndices[j]); } } mesh->setupMesh(); return mesh; } // ----------------------- SCENE Model -------------------------------- // ---- Helper void exchange_matrix_data(glm::mat4 &DesMatrix,const aiMatrix4x4 & srcAssimpMat){ DesMatrix[0].x = srcAssimpMat.a1; DesMatrix[0].y = srcAssimpMat.a2; DesMatrix[0].z = srcAssimpMat.a3; DesMatrix[0].w = srcAssimpMat.a4; DesMatrix[1].x = srcAssimpMat.b1; DesMatrix[1].y = srcAssimpMat.b2; DesMatrix[1].z = srcAssimpMat.b3; DesMatrix[1].w = srcAssimpMat.b4; DesMatrix[2].x = srcAssimpMat.c1; DesMatrix[2].y = srcAssimpMat.c2; DesMatrix[2].z = srcAssimpMat.c3; DesMatrix[2].w = srcAssimpMat.c4; DesMatrix[3].x = srcAssimpMat.d1; DesMatrix[3].y = srcAssimpMat.d2; DesMatrix[3].z = srcAssimpMat.d3; DesMatrix[3].w = srcAssimpMat.d4; } } // end of namespace #endif //TRIANGLE_ALG_MODELDELEGATE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef MESH_H #define MESH_H #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <string> #include <vector> #include "ALG_LoadShader.h" #include <GL/glew.h> #include "ALG_TextureDelegate.h" #include "ALG_Vertex.h" namespace AlgebraMaster { using namespace std; struct Mesh { public: Mesh()= default; //* constructor */ Mesh(const vector<Vertex> &vts, const vector<unsigned int>ids); // rendering data vector<Vertex> vertices; vector<unsigned int> indices; // ogl unsigned int VAO,VBO,EBO; // vertex array buffer //* this method need called manually */ virtual void setupMesh(); // ogl draw virtual void draw(); // shader LoadShader shader; // get mat from outside void assignMaterial(const LoadShader & rhs_shader); }; Mesh::Mesh(const vector<Vertex> &vts, const vector<unsigned int>ids):vertices(vts),indices(ids){ } void Mesh::assignMaterial(const LoadShader &rhs_shader) { shader.fragmentShader = rhs_shader.fragmentShader; shader.vertexShader = rhs_shader.vertexShader; shader.shaderProgram = rhs_shader.shaderProgram; shader.projection = rhs_shader.projection; shader.view = rhs_shader.view; shader.model = rhs_shader.model; shader.textures = rhs_shader.textures; } // opengl draw the mesh void Mesh::draw() { this->shader.use(); shader.setMatrix(shader.model,shader.view,shader.projection); string mat_prefix = "material."; for(auto &tex: shader.textures) { glActiveTexture(tex->texChannel); switch (tex->texType) { case Texture::BASECOLOR_MAP:{ string texchanName = mat_prefix + "diffuse_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::SPECULAR_MAP:{ string texchanName = mat_prefix + "specular_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::EMISSION_MAP:{ string texchanName = mat_prefix + "emission_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::BUMP_MAP:{ string texchanName = mat_prefix + "bump_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::NORMAL_MAP:{ string texchanName = mat_prefix + "normal_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::IOR_MAP:{ string texchanName = mat_prefix + "ior_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::OPACITY_MAP:{ string texchanName = mat_prefix + "opacity_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } case Texture::DISPLACE_MAP:{ string texchanName = mat_prefix + "displace_map"; shader.setInt(texchanName.c_str(),tex->textureUnitID); break; } default: break; } // end of switch glBindTexture(GL_TEXTURE_2D, tex->id); // bind current id } // end of for each textures // draw mesh glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); // always good practice to set everything back to defaults once configured. glActiveTexture(GL_TEXTURE0); } // init our mesh data void Mesh::setupMesh() { glCreateVertexArrays(1,&VAO); // vertex array object glCreateBuffers(1,&VBO); // vertex buffer object glCreateBuffers(1,&EBO); // vertex element array buffer object glBindVertexArray(VAO); // bind vertex array glBindBuffer(GL_ARRAY_BUFFER,VBO); // bind vertex buffer glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); // vertex attributes // position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); // normal glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 3*sizeof(float)) ); //tex glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 6*sizeof(float)) ); //tangent glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 8*sizeof(float)) ); // bitangent glEnableVertexAttribArray(4); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 11*sizeof(float)) ); glBindVertexArray(0); } } // end of namespace #endif // MESH_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef LOADTEXTURE_H #define LOADTEXTURE_H #include <GL/glew.h> // IMP the stb image loader #define STB_IMAGE_IMPLEMENTATION #include <stb_image.h> #include <iostream> using namespace std; namespace AlgebraMaster { class LoadTexture { public: LoadTexture(); LoadTexture(const char *fileName); void load(const char *fileName); virtual ~LoadTexture(); inline GLuint getTextureID()const{return textureID;} inline GLuint getImageFormat()const{return format;} GLuint textureID; GLenum format; bool loadStatus; }; LoadTexture::LoadTexture() { loadStatus = false; } void LoadTexture::load(const char *fileName) { glGenTextures(1, &textureID); int width, height, nrComponents; unsigned char *data = stbi_load(fileName, &width, &height, &nrComponents, 0); if (data) { if (nrComponents == 1) format = GL_RED; else if (nrComponents == 3) format = GL_RGB; else if (nrComponents == 4) format = GL_RGBA; glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); 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_MIPMAP_LINEAR); stbi_image_free(data); loadStatus = true; } else { loadStatus = false; std::cout << "Texture failed to load at path: " << fileName << std::endl; stbi_image_free(data); } } LoadTexture::LoadTexture(const char *fileName){ loadStatus = false; load(fileName); } LoadTexture::~LoadTexture(){} } #endif // LOADTEXTURE_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef LOADSHADER_H #define LOADSHADER_H #include <GL/glew.h> #include <iostream> #include <fstream> #include <string> #include <sstream> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <vector> #include "ALG_TextureDelegate.h" namespace AlgebraMaster { using namespace std; // Shaders const char* vertexShaderSource = "#version 450 core\n" "layout (location = 0) in vec4 v_position;\n" "layout ( location = 1 ) in vec3 v_normal;\n" "layout ( location = 2 ) in vec2 v_texCoord;\n" "out vec2 myTexCoord;\n" "uniform mat4 model;\n" "uniform mat4 view;\n" "uniform mat4 projection;\n" "void main()\n" "{\n" "gl_Position = projection * view * model * v_position;\n" "myTexCoord = v_texCoord;\n" "}\0"; const char* fragmentShaderSource = "#version 450 core\n" "out vec4 fColor;\n" "void main()\n" "{\n" "fColor = vec4(0.5f, 0.5f, 0.5f , 1.0f);\n" "}\n\0"; // this have texture const char* fragmentShaderSource2 = "#version 450 core\n" "out vec4 fColor;\n" "in vec2 myTexCoord;\n" "struct Material\n" "{\n" "float Kd; // diffuse mult\n" "float kS; // specular mult\n" "float shininess; // phong pow(,shine)\n" "sampler2D diffuse_map;\n" "sampler2D specular_map;\n" "sampler2D emission_map;\n" "};\n" "uniform Material material;\n" "void main()\n" "{\n" "vec4 df_tex=texture(material.diffuse_map, myTexCoord);\n;" "fColor = vec4(df_tex.r,df_tex.g,df_tex.b,1.0f) ;\n" "}\n\0"; struct LoadShader { enum ShaderIOType{FILE,INLINE_DEFAULT_PROJECTION,INLINE_TEXTURE_PROJECTION}; void compileShaderProgram(){ // create shader program and check it GLint success; GLchar infoLog[512]; shaderProgram = glCreateProgram(); glAttachShader(shaderProgram,vertexShader); glAttachShader(shaderProgram,fragmentShader); glLinkProgram(shaderProgram ); glGetProgramiv( shaderProgram, GL_LINK_STATUS, &success ); // Get Link Status if (!success) { glGetProgramInfoLog( shaderProgram, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } // Delete the allShaders as they're linked into our program now and no longer necessery glDeleteShader( vertexShader ); glDeleteShader( fragmentShader ); } void compileVertexShader(string code){ vertexShader = glCreateShader( GL_VERTEX_SHADER ); const char * src = code.c_str(); glShaderSource( vertexShader, 1, &(src), NULL ); glCompileShader( vertexShader ); GLint success; GLchar infoLog[512]; glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &success ); if ( !success ) { glGetShaderInfoLog( vertexShader, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } } void compileFragmentShader(string code){ const char * src = code.c_str(); GLint success; GLchar infoLog[512]; fragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragmentShader, 1, &src, NULL ); glCompileShader( fragmentShader ); glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &success ); // Get Compile status if ( !success ) { glGetShaderInfoLog( fragmentShader, 512, NULL, infoLog ); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } } void fromSrc(const string &vertCode, const string &fragCode){ compileVertexShader(vertCode); compileFragmentShader(fragCode); compileShaderProgram(); } LoadShader(){ } ~LoadShader(){ } void asSimpleTextureShader(){ shaderName = "simpleTex"; shaderIOType = INLINE_TEXTURE_PROJECTION; compileVertexShader(vertexShaderSource); compileFragmentShader(fragmentShaderSource2); compileShaderProgram(); } void asSimpleShader() { shaderName = "simpleCol"; shaderIOType = INLINE_DEFAULT_PROJECTION; compileVertexShader(vertexShaderSource); compileFragmentShader(fragmentShaderSource); compileShaderProgram(); } void setShaderName(const string &name){ shaderName = name; } LoadShader(const char*vertPath, const char* fragPath){ load(vertPath,fragPath); shaderIOType = FILE; } string _readFile(const char *path){ ifstream stream; stringstream ss; stream.exceptions(ifstream::badbit); try { stream.open(path); // open file ss << stream.rdbuf(); // get strings from file } catch (ifstream::failure e) { cout << "ERROR::OPEN FILE:" << path << endl; } // close file handle stream.close(); // get str() from stringstream string shaderCode = ss.str(); return shaderCode; } void _loadVertexShader(const char *path){ // read shader code auto handle = _readFile(path); const char * shaderCode = handle.c_str(); compileVertexShader(shaderCode); } void _loadFragmentShader(const char *path){ // read shader code auto handle = _readFile(path); const char * shaderCode = handle.c_str(); compileFragmentShader(shaderCode); } void load(const char* vertShaderPath, const char* fragShaderPath){ shaderIOType = FILE; _loadVertexShader(vertShaderPath); _loadFragmentShader(fragShaderPath); // create shader program and check it compileShaderProgram(); } void use(){ glUseProgram(shaderProgram); } void setBool(const char *name, bool value) const { glUniform1i(glGetUniformLocation(shaderProgram, name), (int)value); } void setInt(const char *name, int value) const { glUniform1i(glGetUniformLocation(shaderProgram,name), value); } // ------------------------------------------------------------------------ void setFloat(const char *name, float value) const { glUniform1f(glGetUniformLocation(shaderProgram, name), value); } // ------------------------------------------------------------------------ void setVec2(const char *name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec2(const char *name, float x, float y) const { glUniform2f(glGetUniformLocation(shaderProgram,name), x, y); } // ------------------------------------------------------------------------ void setVec3(const char *name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec3(const char *name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(shaderProgram,name), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const char *name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]); } void setVec4(const char *name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(shaderProgram,name), x, y, z, w); } void setMat2(const char*name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name), 1, GL_FALSE,glm::value_ptr(mat)); } void setMat3(const char*name, const glm::mat3 &mat){ GLuint location = glGetUniformLocation(shaderProgram, name); glUniformMatrix3fv(location,1, GL_FALSE, &mat[0][0]); } void setMat4(const char *name , const glm::mat4 &mat){ GLuint location = glGetUniformLocation(shaderProgram, name); glUniformMatrix4fv(location,1, GL_FALSE, glm::value_ptr(mat)); } GLuint shaderProgram; GLuint vertexShader; GLuint fragmentShader; ShaderIOType shaderIOType; string shaderName; vector <Texture*> textures; // do not release this memory, scene will manipulate this mem glm::mat4 model; glm::mat4 view; glm::mat4 projection; void setMatrix(const glm::mat4 &matModel , const glm::mat4 &matView , const glm::mat4 &matProjection){ model = matModel; view = matView; projection = matProjection; setMat4("projection", projection); setMat4("view", view); setMat4("model", model); } }; } #endif // LOADSHADER_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // Created by admin on 2020/2/25. // #define GLEW_STATIC // GLEW #include <GL/glew.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <GL/glew.h> #include "ALG_MathFunction.h" #include "ALG_LoadShader.h" namespace AlgebraMaster{ // x line static float points[] = { -10.0f,0.0f,0.0f, 10.0f,0.0f,0.0f }; class DrawGrid{ public: void initialize(); void draw(glm::mat4 &proj, glm::mat4 &view); // members GLuint VAO,VBO; LoadShader shader; }; void DrawGrid::initialize() { glCreateVertexArrays(1, &VAO); glCreateBuffers(1,&VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER,VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); // position glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); shader.asSimpleShader(); } void DrawGrid::draw(glm::mat4 &proj, glm::mat4 &view) { glEnable(GL_LINE_SMOOTH); shader.use(); shader.setMat4("projection",proj); shader.setMat4("view",view); glLineWidth(1.0f); glBindVertexArray(VAO); // Draw X line glm::mat4 model(1.0f); shader.setMat4("model",model); glDrawArrays(GL_LINES,0, 2); // Draw Z line glm::mat4 rot(1.0f); rot = glm::rotate(rot,glm::radians(90.0f),glm::vec3(0.0f, 1.0f, 0.0f ) ); shader.setMat4("model",rot); glDrawArrays(GL_LINES,0, 2); // offset line on x // Z positive dir for(int i=1;i<11;i++){ // offset line on z glm::mat4 model(1.0f); glBindVertexArray(VAO); model = glm::translate(model,glm::vec3(0.0f, 0.0f, i ) ); shader.setMat4("model",model); glDrawArrays(GL_LINES,0, 2); } // Z negative dir for(int i=1;i<11;i++){ // offset line on z glm::mat4 model(1.0f); glBindVertexArray(VAO); model = glm::translate(model,glm::vec3(0.0f, 0.0f, -i ) ); shader.setMat4("model",model); glDrawArrays(GL_LINES,0, 2); // offset line on x } // X positive dir for(int i=1;i<11;i++){ glBindVertexArray(VAO); // offset line on x glm::mat4 rot(1.0f); rot = glm::rotate(rot,glm::radians(90.0f),glm::vec3(0.0f, 1.0f, 0.0f ) ); glm::mat4 trans(1.0f); trans = glm::translate(trans,glm::vec3(i,0.0f,0.0f)); shader.setMat4("model",trans*rot); glDrawArrays(GL_LINES,0, 2); // offset line on x } // X negative dir for(int i=1;i<11;i++){ // offset line on x glm::mat4 rot(1.0f); rot = glm::rotate(rot,glm::radians(90.0f),glm::vec3(0.0f, 1.0f, 0.0f ) ); glm::mat4 trans(1.0f); trans = glm::translate(trans,glm::vec3(-i,0.0f,0.0f)); shader.setMat4("model",trans*rot); glDrawArrays(GL_LINES,0, 2); // offset line on x } glDisable(GL_LINE_SMOOTH); } }// end of namespace #ifndef TRIANGLE_ALG_DRAWGRID_H #define TRIANGLE_ALG_DRAWGRID_H #endif //TRIANGLE_ALG_DRAWGRID_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef WINDOW_H #define WINDOW_H #undef GLFW_DLL #include <GLFW/glfw3.h> #define GLEW_STATIC #include <GL/glew.h> namespace AlgebraMaster{ class FrameWindow { public: FrameWindow(int width,int height,const char*title="日格朗拉Never Fake"); virtual ~FrameWindow(); GLFWwindow *getWindow(); private: GLFWwindow *window; int w; int h; }; FrameWindow::FrameWindow(int width,int height,const char*title){ w = width; h = height; glfwInit(); window = glfwCreateWindow(width,height,title,NULL,NULL); glfwMakeContextCurrent(window); glewInit(); } FrameWindow::~FrameWindow(){ glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow * FrameWindow::getWindow(){ return window; } } #endif // WINDOW_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef GLFWCAMERA_H #define GLFWCAMERA_H #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> namespace AlgebraMaster{ class GLFWCamera{ public: GLFWCamera(); ~GLFWCamera(){} enum CAMERA_MOVEMENT{ FORWARD, // Camera move to front -> key:W BACKWARD, // Camera move to back -> key:S LEFT, // Camera move to left -> key:A RIGHT // Camera move to right -> key:D }; public: glm::vec3 pos; // camera world space glm::vec3 front; glm::vec3 up; // Euler Angles float yaw; float pitch; // Camera options float movementSpeed; float mouseSensitivity; float fov; void processFov(float yoffset){ if(fov >= 1.0f && fov <= 45.0f){ fov -= yoffset; } if(fov <=1.0f){ fov = 1.0f; } if(fov >= 45.0f){ fov = 45.0f; } } // build the matrix for lookAt glm::mat4 GetViewMatrix(){ return glm::lookAt(pos , pos + front , up); } // process -Rotate the view- void processMouseMove(float xoffset, float yoffset); // process -W S A D- void processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir); void updateFront(){ glm::vec3 tempfront; tempfront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); tempfront.y = sin(glm::radians(pitch)); tempfront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); this->front = glm::normalize(tempfront); } }; GLFWCamera::GLFWCamera(){ pos = glm::vec3(0.0f,0.0f,3.0f); up = glm::vec3(0.0f,1.0f,0.0f); front = glm::vec3(0.0f,0.0f,-1.0f); yaw = -90.0f; pitch = 0.0f; fov = 45.0f; movementSpeed = 4.5f; mouseSensitivity = 0.1f; } void GLFWCamera::processMouseMove(float xoffset, float yoffset) { xoffset *= mouseSensitivity; yoffset *= mouseSensitivity; yaw += xoffset; pitch += yoffset; // make sure that when pitch is out of bounds, screen doesn't get flipped if (pitch > 89.0f) pitch = 89.0f; if (pitch < -89.0f) pitch = -89.0f; this->updateFront(); } void GLFWCamera::processKeyboardMove(float delta, CAMERA_MOVEMENT moveDir) { float vel = movementSpeed * delta; switch (moveDir) { case FORWARD: { pos += vel * front; break; } case BACKWARD: { pos -= vel * front; break; } case LEFT: { pos -= glm::normalize(glm::cross(front, up)) * vel; break; } case RIGHT: { pos += glm::normalize(glm::cross(front, up)) * vel; } default: break; } } } #endif // GLFWCAMERA_H
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#define GLEW_STATIC // GLEW #include <GL/glew.h> #include <cstdlib> #undef GLFW_DLL // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "ALG_LoadShader.h" #include "ALG_LoadTexture.h" #include "ALG_GLFWCamera.h" #include "ALG_FrameWindow.h" #include "ALG_ModelDelegate.h" #include "ALG_SceneDelegate.h" #include "ALG_DrawGrid.h" #include <cmath> #include "OGLHelper.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <map> using namespace AlgebraMaster; const unsigned int SRC_WIDTH = 1400; const unsigned int SRC_HEIGHT = 720; static LoadShader SurfaceShader; void init(); void display(); void processInput(GLFWwindow *window); void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); // camera static GLFWCamera *camera; static float lastX = float(SRC_WIDTH) / 2.0f; static float lastY = float(SRC_HEIGHT) / 2.0f; static bool firstMouse = true; static bool firstMiddowMouse = true; // timing static float deltaTime = 0.0f; // time between current frame and last frame static float lastFrame = 0.0f; // light define static glm::vec3 lightPos(0.0f, 4.0f,-2.0f); // Geometry static DrawGrid grid; static float cubeVertices[] = { // positions // texture Coords -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 }; static float planeVertices[] = { // positions // texture Coords 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; static float transparentVertices[] = { // positions // texture Coords (swapped y coordinates because texture is flipped upside down) 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.0f }; static vector<glm::vec3> windows { glm::vec3(-1.5f, 0.0f, -0.48f), glm::vec3( 1.5f, 0.0f, 0.51f), glm::vec3( 0.0f, 0.0f, 0.7f), glm::vec3(-0.3f, 0.0f, -2.3f), glm::vec3( 0.5f, 0.0f, -0.6f) }; // cube vao vbo static unsigned int cubeVAO,cubeVBO; static unsigned int planeVAO,planeVBO; static unsigned int transparentVAO,transparentVBO; static LoadTexture texture1; static LoadTexture texture2; static LoadTexture texture3; void init(){ camera = new GLFWCamera; camera->pos.y = 1.0f; camera->pos.z = 4.0f; // GL depth zbuffer glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); SurfaceShader.load("shaders/SurfaceShader.vert","shaders/SurfaceShader.frag"); glGenVertexArrays(1, &cubeVAO); glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(planeVAO, planeVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(planeVertices),&planeVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); CreateGeometryBuffer(transparentVAO, transparentVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(transparentVertices),&transparentVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glBindVertexArray(0); cout << "cube VAO:" << cubeVAO <<endl; texture1.load("texture/marble.jpg"); texture2.load("texture/metal.png"); texture3.load("texture/window.png"); grid.initialize(); } // ----------- Render Loop ---------- void display(){ // per-frame time logic // -------------------- float currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // object .vert settings glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f, 1000.0f); glm::mat4 view = camera->GetViewMatrix(); // object world transformation glm::mat4 model = glm::mat4(1.0f); grid.draw(projection,view); // render cube SurfaceShader.setInt("diffuse_map", 1); SurfaceShader.use(); SurfaceShader.setMat4("projection", projection); SurfaceShader.setMat4("view", view); model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); SurfaceShader.setMat4("model", model); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,texture1.textureID); glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); // floor glBindVertexArray(planeVAO); glBindTexture(GL_TEXTURE_2D, texture2.getTextureID()); model = glm::mat4(1.0f); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); std::map<float, glm::vec3> sorted; for (unsigned int i = 0; i < windows.size(); i++) { float distance = glm::length(camera->pos - windows[i]); // cal distance between camera and window position sorted[distance] = windows[i]; } // windows (from furthest to nearest) glBindVertexArray(transparentVAO); glBindTexture(GL_TEXTURE_2D, texture3.getTextureID()); for (std::map<float, glm::vec3>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it) { model = glm::mat4(1.0f); model = glm::translate(model, it->second); SurfaceShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); } } int main() { glfwInit(); FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT); glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback); glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback); glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback); init(); // RENDER-------------- while(!glfwWindowShouldClose(FrameWindow.getWindow())){ processInput(FrameWindow.getWindow()); display(); glfwSwapBuffers(FrameWindow.getWindow()); glfwPollEvents(); } delete camera; return 0; } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD); if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT); } // ROTATE VIEW DIR void mouse_callback(GLFWwindow* window, double xpos, double ypos){ int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE); int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT); int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT); // set up the camera view if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS) { if (firstMouse){ lastX = xpos; lastY = ypos; firstMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->processMouseMove(xoffset,yoffset); } if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){ firstMouse = true; } // Move Camera Position if( middow_mouse_state == GLFW_PRESS) { if (firstMiddowMouse){ lastX = xpos; lastY = ypos; firstMiddowMouse = false; } float xoffset = xpos - lastX; float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top lastX = xpos; lastY = ypos; camera->pos.x += xoffset*0.01f; camera->pos.y += yoffset*0.01f; } if ( middow_mouse_state == GLFW_RELEASE){ firstMiddowMouse = true; } } void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){ camera->processFov(yoffset); }
面剔除:
比较简单:
默认glEnable(GL_CULL_FACE); 是剔除后面
剔除front-face
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW); 把顺时针的排序定为frontface,实际上默认这个CW应该是背面,CCW才是前面。现在相当于把真正的<前面>和<后面>调换顺序了。
glCullFace(GL_BACK); 现在裁剪后面,其实在目前情况下是 前面,视窗上看相当于把前面裁剪了
也可以这样剔除front-face:默认情况下,逆时针的排序代表front-face