OpenGL天空盒skybox
生活随笔
收集整理的這篇文章主要介紹了
OpenGL天空盒skybox
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
痛徹的感悟
天空盒可能的難題
天空盒代碼
痛徹的感悟
今天考完試才發現自己和別人的差距還挺大的,四五六班下午的考試題目,我很快做了出來,但是自己的班級的考試題目,我竟然一道都沒有成功!!!所以我決定把我之前準備的代碼公布一下,也希望對一些人有所幫助吧。
天空盒可能的難題
- SOIL2的配置
- glm的配置
- mac的xcode里面還有res資源庫的配置
- 主要參考網站:立方體貼圖,往下翻有源碼
- 前面的理論部分參考我的好友博客:碼辣香鍋
天空盒代碼
項目目錄概覽:(天空盒六張圖片可以在上述?立方體貼圖?鏈接下載到)
或者在我的Github上找到GitHub - NaughtyRacoon/GLskybox
?
main.cpp
//main.cpp#include <iostream> #include <vector> using namespace std; //GLEW #define GLEW_STATIC #include <GL/glew.h>//GLFW #include <GLFW/glfw3.h>//GLM #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtx/rotate_vector.hpp>//利用旋轉所需頭文件#include "SOIL2/SOIL2.h" #include "SOIL2/stb_image.h"#include "camera.h" #include "Shader.h" #include "light.h"const GLint WIDTH = 800, HEIGHT = 600; void KeyCallback(GLFWwindow *window , int key ,int scancode, int action,int mode);//退出函數 void ScrollCallback(GLFWwindow *window,double xOffset,double yOffset);//滾輪移動 void MouseCallback(GLFWwindow *window,double xPos,double yPos);//鼠標移動void DoMovement();//獲得當前這幀下按鍵處理,每次poll event之后才會有鍵盤操作GLuint loadTexture(GLchar* path); GLuint loadCubemap(vector<const GLchar*> faces);bool keys[1024];//臨時變量存儲所有鍵盤操作 Camera camera(glm::vec3(0.0f,0.0f,2.0f));//實例化,往后看GLfloat deltaTime = 0.0f; GLfloat lastTime = 0.0f; GLfloat lastX = WIDTH/2.0f; GLfloat lastY = HEIGHT/2.0f; bool firstMouse = true; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // must for Mac glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);//不讓窗口變動大小//大寫開頭是變量 GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr);//創建窗口if (nullptr == window) { std::cout<<"Failed to create GLFW window"<<std::endl;glfwTerminate(); return -1; }// next two lines are for mac retina displayint screenWidth, screenHeight;glfwGetFramebufferSize( window, &screenWidth, &screenHeight);glfwMakeContextCurrent( window );glfwSetKeyCallback(window, KeyCallback);glfwSetCursorPosCallback(window, MouseCallback);glfwSetScrollCallback(window, ScrollCallback);glewExperimental = GL_TRUE;if (GLEW_OK != glewInit() ) { std::cout << "Failed to initialise GLEW" << std::endl; return -1; }glEnable(GL_DEPTH_TEST);//深度測試開啟glDepthFunc(GL_LESS);//小于就改變glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glViewport( 0, 0, screenWidth, screenHeight );Shader ourShader = Shader("res/shaders/core.vs","res/shaders/core.fs");Shader lightShader = Shader("res/shaders/light.vs","res/shaders/light.fs");Shader skyboxShader = Shader("res/shaders/skybox.vs","res/shaders/skybox.fs");// Light lightModel = Light();GLfloat cubeVertices[]={//position //法向量nomal-0.5f,-0.5f,-0.5f, 0.0f,0.0f,-1.0f,0.5f,-0.5f,-0.5f, 0.0f,0.0f,-1.0f,0.5f, 0.5f,-0.5f, 0.0f,0.0f,-1.0f,0.5f, 0.5f,-0.5f, 0.0f,0.0f,-1.0f,-0.5f, 0.5f,-0.5f, 0.0f,0.0f,-1.0f,-0.5f,-0.5f,-0.5f, 0.0f,0.0f,-1.0f,-0.5f,-0.5f,0.5f, 0.0f,0.0f,1.0f,0.5f,-0.5f,0.5f, 0.0f,0.0f,1.0f,0.5f, 0.5f,0.5f, 0.0f,0.0f,1.0f,0.5f, 0.5f,0.5f, 0.0f,0.0f,1.0f,-0.5f, 0.5f,0.5f, 0.0f,0.0f,1.0f,-0.5f,-0.5f,0.5f, 0.0f,0.0f,1.0f,-0.5f, 0.5f, 0.5f, -1.0f,0.0f,0.0f,-0.5f, 0.5f,-0.5f, -1.0f,0.0f,0.0f,-0.5f,-0.5f,-0.5f, -1.0f,0.0f,0.0f,-0.5f,-0.5f,-0.5f, -1.0f,0.0f,0.0f,-0.5f,-0.5f, 0.5f, -1.0f,0.0f,0.0f,-0.5f, 0.5f, 0.5f, -1.0f,0.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f,0.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f,-0.5f, 0.5f, 1.0f,0.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f,0.0f,0.0f,-0.5f,-0.5f,-0.5f, 0.0f,-1.0f,0.0f,0.5f,-0.5f,-0.5f, 0.0f,-1.0f,0.0f,0.5f,-0.5f, 0.5f, 0.0f,-1.0f,0.0f,0.5f,-0.5f, 0.5f, 0.0f,-1.0f,0.0f,-0.5f,-0.5f, 0.5f, 0.0f,-1.0f,0.0f,-0.5f,-0.5f,-0.5f, 0.0f,-1.0f,0.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f,0.0f,0.5f,0.5f,-0.5f, 0.0f,1.0f,0.0f,0.5f,0.5f, 0.5f, 0.0f,1.0f,0.0f,0.5f,0.5f, 0.5f, 0.0f,1.0f,0.0f,-0.5f,0.5f, 0.5f, 0.0f,1.0f,0.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f,0.0f,};GLfloat skyboxVertices[] = {// Positions-1.0f, 1.0f, -1.0f,-1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,1.0f, 1.0f, -1.0f,-1.0f, 1.0f, -1.0f,-1.0f, -1.0f, 1.0f,-1.0f, -1.0f, -1.0f,-1.0f, 1.0f, -1.0f,-1.0f, 1.0f, -1.0f,-1.0f, 1.0f, 1.0f,-1.0f, -1.0f, 1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f, 1.0f, -1.0f,1.0f, -1.0f, -1.0f,-1.0f, -1.0f, 1.0f,-1.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f,1.0f, -1.0f, 1.0f,-1.0f, -1.0f, 1.0f,-1.0f, 1.0f, -1.0f,1.0f, 1.0f, -1.0f,1.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f,-1.0f, 1.0f, 1.0f,-1.0f, 1.0f, -1.0f,-1.0f, -1.0f, -1.0f,-1.0f, -1.0f, 1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,-1.0f, -1.0f, 1.0f,1.0f, -1.0f, 1.0f};GLfloat vertices[]={//position //color-0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,0.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,0.0f,0.0f,-0.5f, 0.5f,-0.5f, 1.0f,0.0f,0.0f,-0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.0f,-0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f,0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f,0.5f, 0.5f,0.5f, 0.0f,1.0f,0.0f,0.5f, 0.5f,0.5f, 0.0f,1.0f,0.0f,-0.5f, 0.5f,0.5f, 0.0f,1.0f,0.0f,-0.5f,-0.5f,0.5f, 0.0f,1.0f,0.0f,-0.5f, 0.5f, 0.5f, 0.0f,0.0f,1.0f,-0.5f, 0.5f,-0.5f, 0.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f, 0.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f, 0.0f,0.0f,1.0f,-0.5f,-0.5f, 0.5f, 0.0f,0.0f,1.0f,-0.5f, 0.5f, 0.5f, 0.0f,0.0f,1.0f,0.5f, 0.5f, 0.5f, 1.0f,1.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,1.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,1.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,1.0f,0.0f,0.5f,-0.5f, 0.5f, 1.0f,1.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f,1.0f,0.0f,-0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f,0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f,0.5f,-0.5f, 0.5f, 1.0f,0.0f,1.0f,0.5f,-0.5f, 0.5f, 1.0f,0.0f,1.0f,-0.5f,-0.5f, 0.5f, 1.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f, 1.0f,0.0f,1.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f,0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f,0.5f,0.5f, 0.5f, 0.0f,1.0f,1.0f,0.5f,0.5f, 0.5f, 0.0f,1.0f,1.0f,-0.5f,0.5f, 0.5f, 0.0f,1.0f,1.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f};GLuint VAO,VBO;glGenVertexArrays(1,&VAO);glGenBuffers(1,&VBO);//綁定 VAO 和 VBOglBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER,VBO);//告訴顯卡需要預留空間//傳輸數據glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);//static多次讀不改數據,dynamic多次讀并且修改//設置VAO//location=0的變量,每次讀三個浮點數,賦值到position,每隔三個浮點數取一個當作位置信息glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6*sizeof(GLfloat),(GLvoid *)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6*sizeof(GLfloat),(GLvoid *)(3*sizeof(GLfloat)));glEnableVertexAttribArray(1);//下面是解綁操作glBindBuffer(GL_ARRAY_BUFFER,0); //VBO解綁glBindVertexArray(0); //VAO解綁// Setup cube VAOGLuint cubeVAO, cubeVBO;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, 6 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glBindVertexArray(0);// Setup skybox VAOGLuint skyboxVAO, skyboxVBO;glGenVertexArrays(1, &skyboxVAO);glGenBuffers(1, &skyboxVBO);glBindVertexArray(skyboxVAO);glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);glBindVertexArray(0);vector<const GLchar*> faces;faces.push_back("res/images/right.jpg");faces.push_back("res/images/left.jpg");faces.push_back("res/images/top.jpg");faces.push_back("res/images/bottom.jpg");faces.push_back("res/images/back.jpg");faces.push_back("res/images/front.jpg");GLuint skyboxTexture = loadCubemap(faces);//draw loop 繪制循環 while (!glfwWindowShouldClose (window)) {GLfloat currentTime = glfwGetTime();deltaTime = currentTime - lastTime;lastTime = currentTime;glViewport(0, 0, screenWidth, screenHeight);glfwPollEvents();DoMovement();glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// Draw scene as normalourShader.use();glm::mat4 model;glm::mat4 view = camera.GetViewMatrix();glm::mat4 projection = glm::perspective(camera.GetZoom(), (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));glUniform3f(glGetUniformLocation(ourShader.Program, "cameraPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);// CubesglBindVertexArray(cubeVAO);glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);// Draw skybox as lastglDepthFunc(GL_LEQUAL);skyboxShader.use();view = glm::mat4(glm::mat3(camera.GetViewMatrix()));glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));// skybox cubeglBindVertexArray(skyboxVAO);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);glfwSwapBuffers (window);}glfwTerminate(); glDeleteVertexArrays(1,&skyboxVAO); glDeleteBuffers(1,&skyboxVBO);glDeleteVertexArrays(1,&VAO);glDeleteBuffers(1,&VBO);return 0;}void KeyCallback(GLFWwindow *window,int key,int scancode,int action,int mode) {if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){glfwSetWindowShouldClose(window, GL_TRUE);}if(key>=0 && key<1024){if(action==GLFW_PRESS){keys[key]=true;}else if(action==GLFW_RELEASE){keys[key]=false;}} }void DoMovement() {if(keys[GLFW_KEY_W] ){camera.ProcessKeyboard(FORWARD, deltaTime);}if(keys[GLFW_KEY_S] ){camera.ProcessKeyboard(BACKWORD, deltaTime);}if(keys[GLFW_KEY_A] ){camera.ProcessKeyboard(LEFT, deltaTime);}if(keys[GLFW_KEY_D] ){camera.ProcessKeyboard(RIGHT, deltaTime);} }void MouseCallback(GLFWwindow *window,double xPos,double yPos) {//取消第一次變換,讓圖形一開始就出現在屏幕上if (firstMouse) {lastX = xPos;lastY = yPos;firstMouse = false;}GLfloat xOffset = xPos - lastX;GLfloat yOffset = lastY - yPos;lastX = xPos;lastY = yPos;camera.ProcessMouseMovement(xOffset, yOffset);}void ScrollCallback(GLFWwindow *window,double xOffset,double yOffset) {camera.ProcessMouseScroll(yOffset);}GLuint loadCubemap(vector<const GLchar*> faces) {GLuint textureID;glGenTextures(1, &textureID);glActiveTexture(GL_TEXTURE0);int width,height;unsigned char* image;glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);for(GLuint i = 0; i < faces.size(); i++){image = SOIL_load_image(faces[i], &width, &height, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);}glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);glBindTexture(GL_TEXTURE_CUBE_MAP, 0);return textureID; } GLuint loadTexture(GLchar* path) {//Generate texture ID and load texture dataGLuint textureID;glGenTextures(1, &textureID);int width,height;unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);// Assign texture to IDglBindTexture(GL_TEXTURE_2D, textureID);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);// ParametersglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glBindTexture(GL_TEXTURE_2D, 0);SOIL_free_image_data(image);return textureID; }light.h
#ifndef Light_h #define Light_h#include <GL/glew.h>GLfloat vertices_light[] = {//position-0.5f,-0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f, 0.5f,-0.5f,0.5f, 0.5f,-0.5f,-0.5f, 0.5f,-0.5f,-0.5f,-0.5f,-0.5f,-0.5f,-0.5f,0.5f,0.5f,-0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,-0.5f,0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f,0.5f,0.5f,-0.5f,0.5f,-0.5f,-0.5f,-0.5f,-0.5f-0.5f,-0.5f,-0.5f-0.5f,-0.5f,0.5f,-0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f,0.5f,0.5f,0.5f,0.5f,-0.5f,-0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f,0.5f,0.5f,-0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f,-0.5f,-0.5f-0.5f,0.5f,-0.5f,0.5f,0.5f,-0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,-0.5f,0.5f,0.5f,-0.5f,0.5f,-0.5f }; class Light { public:Light(){this->update();}void Draw(Shader &shader){glBindVertexArray(this->VAO);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);} private:GLuint VAO,VBO;void update(){glGenVertexArrays(1,&this->VAO);glGenBuffers(1,&this->VBO);//connect the VAO and VBOglBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER,this->VBO);glBufferData(GL_ARRAY_BUFFER,sizeof(vertices_light),vertices_light,GL_STATIC_DRAW);glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GLfloat),(GLvoid *)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER,0);glBindVertexArray(0);} };#endifmesh.h
#pragma once#include <string> #include <fstream> #include <sstream> #include <iostream> #include <vector> using namespace std;#include <GL/glew.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp>struct Vertex {glm::vec3 Position;glm::vec3 Normal;glm::vec2 TexCoords; };struct Texture {GLuint id;string type;aiString path; };class Mesh { public:vector<Vertex> vertices;vector<GLuint> indices;vector<Texture> textures;Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures){this->vertices = vertices;this->indices = indices;this->textures = textures;// Now that we have all the required data, set the vertex buffers and its attribute pointers.this->setupMesh();}// Render the meshvoid Draw(Shader shader){// Bind appropriate texturesGLuint diffuseNr = 1;GLuint specularNr = 1;for(GLuint i = 0; i < this->textures.size(); i++){glActiveTexture(GL_TEXTURE0 + i); // Active proper texture unit before binding// Retrieve texture number (the N in diffuse_textureN)stringstream ss;string number;string name = this->textures[i].type;if(name == "texture_diffuse")ss << diffuseNr++; // Transfer GLuint to streamelse if(name == "texture_specular")ss << specularNr++; // Transfer GLuint to streamnumber = ss.str();// Now set the sampler to the correct texture unitglUniform1i(glGetUniformLocation(shader.Program, (name + number).c_str()), i);// And finally bind the textureglBindTexture(GL_TEXTURE_2D, this->textures[i].id);}// Also set each mesh's shininess property to a default value (if you want you could extend this to another mesh property and possibly change this value)glUniform1f(glGetUniformLocation(shader.Program, "material.shininess"), 16.0f);// Draw meshglBindVertexArray(this->VAO);glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);glBindVertexArray(0);// Always good practice to set everything back to defaults once configured.for (GLuint i = 0; i < this->textures.size(); i++){glActiveTexture(GL_TEXTURE0 + i);glBindTexture(GL_TEXTURE_2D, 0);}}private:/* Render data */GLuint VAO, VBO, EBO;/* Functions */// Initializes all the buffer objects/arraysvoid setupMesh(){// Create buffers/arraysglGenVertexArrays(1, &this->VAO);glGenBuffers(1, &this->VBO);glGenBuffers(1, &this->EBO);glBindVertexArray(this->VAO);// Load data into vertex buffersglBindBuffer(GL_ARRAY_BUFFER, this->VBO);// A great thing about structs is that their memory layout is sequential for all its items.// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which// again translates to 3/2 floats which translates to a byte array.glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &this->vertices[0], GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW);// Set the vertex attribute pointers// Vertex PositionsglEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);// Vertex NormalsglEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal));// Vertex Texture CoordsglEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, TexCoords));glBindVertexArray(0);} };model.h
#pragma once // Std. Includes #include <string> #include <fstream> #include <sstream> #include <iostream> #include <map> #include <vector> using namespace std; // GL Includes #include <GL/glew.h> // Contains all the necessery OpenGL includes #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include "SOIL2/SOIL2.h" #include "SOIL2/stb_image.h" #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h>#include "mesh.h"GLint TextureFromFile(const char* path, string directory);class Model { public:/* Functions */// Constructor, expects a filepath to a 3D model.Model(GLchar* path){this->loadModel(path);}// Draws the model, and thus all its meshesvoid Draw(Shader shader){for(GLuint i = 0; i < this->meshes.size(); i++)this->meshes[i].Draw(shader);}private:/* Model Data */vector<Mesh> meshes;string directory;vector<Texture> textures_loaded; // Stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once./* Functions */// Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.void loadModel(string path){// Read file via ASSIMPAssimp::Importer importer;const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);// Check for errorsif(!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero{cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;return;}// Retrieve the directory path of the filepaththis->directory = path.substr(0, path.find_last_of('/'));// Process ASSIMP's root node recursivelythis->processNode(scene->mRootNode, scene);}// Processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any).void processNode(aiNode* node, const aiScene* scene){// Process each mesh located at the current nodefor(GLuint i = 0; i < node->mNumMeshes; i++){// The node object only contains indices to index the actual objects in the scene.// The scene contains all the data, node is just to keep stuff organized (like relations between nodes).aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];this->meshes.push_back(this->processMesh(mesh, scene));}// After we've processed all of the meshes (if any) we then recursively process each of the children nodesfor(GLuint i = 0; i < node->mNumChildren; i++){this->processNode(node->mChildren[i], scene);}}Mesh processMesh(aiMesh* mesh, const aiScene* scene){// Data to fillvector<Vertex> vertices;vector<GLuint> indices;vector<Texture> textures;// Walk through each of the mesh's verticesfor(GLuint i = 0; i < mesh->mNumVertices; i++){Vertex vertex;glm::vec3 vector; // We declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first.// Positionsvector.x = mesh->mVertices[i].x;vector.y = mesh->mVertices[i].y;vector.z = mesh->mVertices[i].z;vertex.Position = vector;// Normalsvector.x = mesh->mNormals[i].x;vector.y = mesh->mNormals[i].y;vector.z = mesh->mNormals[i].z;vertex.Normal = vector;// Texture Coordinatesif(mesh->mTextureCoords[0]) // Does the mesh contain texture coordinates?{glm::vec2 vec;// A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't// use models where a vertex can have multiple texture coordinates so we always take the first set (0).vec.x = mesh->mTextureCoords[0][i].x;vec.y = mesh->mTextureCoords[0][i].y;vertex.TexCoords = vec;}elsevertex.TexCoords = glm::vec2(0.0f, 0.0f);vertices.push_back(vertex);}// Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.for(GLuint i = 0; i < mesh->mNumFaces; i++){aiFace face = mesh->mFaces[i];// Retrieve all indices of the face and store them in the indices vectorfor(GLuint j = 0; j < face.mNumIndices; j++)indices.push_back(face.mIndices[j]);}// Process materialsif(mesh->mMaterialIndex >= 0){aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];// We assume a convention for sampler names in the shaders. Each diffuse texture should be named// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.// Same applies to other texture as the following list summarizes:// Diffuse: texture_diffuseN// Specular: texture_specularN// Normal: texture_normalN// 1. Diffuse mapsvector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());// 2. Specular mapsvector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());}// Return a mesh object created from the extracted mesh datareturn Mesh(vertices, indices, textures);}// Checks all material textures of a given type and loads the textures if they're not loaded yet.// The required info is returned as a Texture struct.vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName){vector<Texture> textures;for(GLuint i = 0; i < mat->GetTextureCount(type); i++){aiString str;mat->GetTexture(type, i, &str);// Check if texture was loaded before and if so, continue to next iteration: skip loading a new textureGLboolean skip = false;for(GLuint j = 0; j < textures_loaded.size(); j++){if(std::strcmp(textures_loaded[j].path.C_Str(), str.C_Str()) == 0){textures.push_back(textures_loaded[j]);skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)break;}}if(!skip){ // If texture hasn't been loaded already, load itTexture texture;texture.id = TextureFromFile(str.C_Str(), this->directory);texture.type = typeName;texture.path = str;textures.push_back(texture);this->textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.}}return textures;} };GLint TextureFromFile(const char* path, string directory) {//Generate texture ID and load texture datastring filename = string(path);filename = directory + '/' + filename;GLuint textureID;glGenTextures(1, &textureID);int width,height;unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);// Assign texture to IDglBindTexture(GL_TEXTURE_2D, textureID);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);// ParametersglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glBindTexture(GL_TEXTURE_2D, 0);SOIL_free_image_data(image);return textureID; }camera.h
#ifndef camera_h #define camera_h#include <vector> #define GLEW_STATIC #include <GL/glew.h>#include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> enum Camera_Movement//解決朝向問題 {FORWARD,BACKWORD,LEFT,RIGHT }; const GLfloat YAW = -90.0f; //從外往里視角,水平角 const GLfloat PITCH = 0.0f; //俯仰角 const GLfloat ZOOM = 45.0f; //視域,控制縮放 const GLfloat SPEED = 6.0f; //設置初始速度 const GLfloat SENSITIVITY = 0.25f; //靈敏度class Camera { public://camera位置信息Camera(glm::vec3 position = glm::vec3(0.0f,0.0f,0.0f),glm::vec3 up = glm::vec3(0.0f,1.0f,0.0f),GLfloat yaw=YAW,GLfloat pitch = PITCH):front(glm::vec3(0.0f,0.0f,-1.0f)),zoom(ZOOM),movementSpeed(SPEED),mouseSensitivity(SENSITIVITY){this->position = position;this->worldUP = up;this->yaw = yaw;this->pitch = pitch;this->updateCameraVectors();}glm::mat4 GetViewMatrix()//獲得私有變量的值{return glm::lookAt(this->position,this->position + this->front,this->up);}GLfloat GetZoom() //獲得私有變量的值{return this->zoom;}glm::vec3 GetPosition(){return this->position;}void ProcessKeyboard(Camera_Movement direction,GLfloat deltaTime){GLfloat velocity = this->movementSpeed * deltaTime;if (direction == FORWARD){this->position+=this->front*velocity;}if (direction == BACKWORD){this->position-=this->front*velocity;}if (direction == LEFT){this->position-=this->right*velocity;}if (direction == RIGHT){this->position+=this->right*velocity;}}void ProcessMouseScroll(GLfloat yOffset){if ( this->zoom >= 1.0f && this->zoom <= 45.0f ){this->zoom += yOffset;}if ( this->zoom <= 1.0f ){this->zoom = 1.0f;}if ( this->zoom >= 45.0f ){this->zoom = 45.0f;}}void ProcessMouseMovement(GLfloat xOffset,GLfloat yOffset){//靈敏度調節xOffset *= this->mouseSensitivity;yOffset *= this->mouseSensitivity;this->yaw += xOffset;this->pitch += yOffset;this->updateCameraVectors();//變化完更新相機指針} private:GLfloat yaw;GLfloat pitch;GLfloat zoom;GLfloat movementSpeed;GLfloat mouseSensitivity;glm::vec3 position;glm::vec3 front;glm::vec3 right;glm::vec3 up;glm::vec3 worldUP;void updateCameraVectors(){glm::vec3 front;front.x=cos(glm::radians(this->pitch)) * cos(glm::radians(this->yaw));front.y=sin(glm::radians(this->pitch));front.z=cos(glm::radians(this->pitch)) * sin(glm::radians(this->yaw));this->front = glm::normalize(front);this->right=glm::normalize(glm::cross(this->front,this->worldUP));this->up = glm::normalize(glm::cross(this->right,this->front));} };#endif /* camera_h */Shader.h
#pragma once#include <string> #include <fstream> #include <sstream> #include <iostream>#include <GL/glew.h> #include <GLFW/glfw3.h>class Shader {GLuint vertex,fragment; public:GLuint Program;Shader(const GLchar *vertexPath,const GLchar *fragmentPath){std::string vertexCode;std::string fragmentCode;std::ifstream vShaderFile;std::ifstream fShaderFile;vShaderFile.exceptions(std::ifstream::badbit);fShaderFile.exceptions(std::ifstream::badbit);try {vShaderFile.open(vertexPath);fShaderFile.open(fragmentPath);std::stringstream vShaderStream,fShaderStream;vShaderStream<<vShaderFile.rdbuf();fShaderStream<<fShaderFile.rdbuf();vShaderFile.close();fShaderFile.close();vertexCode = vShaderStream.str();fragmentCode = fShaderStream.str();} catch (std::ifstream::failure e) {std::cout<<"ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ"<<std::endl;}const GLchar *vShaderCode = vertexCode.c_str();const GLchar *fShaderCode = fragmentCode.c_str();GLint success;GLchar infoLog[512];vertex = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex,1,&vShaderCode,NULL);glCompileShader(vertex);glGetShaderiv(vertex,GL_COMPILE_STATUS,&success);if (!success) {glGetShaderInfoLog(vertex,512,NULL,infoLog);std::cout<<"ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<<infoLog<<std::endl;}fragment = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment,1,&fShaderCode,NULL);glCompileShader(fragment);glGetShaderiv(fragment,GL_COMPILE_STATUS,&success);if (!success) {glGetShaderInfoLog(fragment,512,NULL,infoLog);std::cout<<"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<<infoLog<<std::endl;}this->Program= glCreateProgram();glAttachShader(this->Program,vertex);glAttachShader(this->Program,fragment);glLinkProgram(this->Program);glGetProgramiv(this->Program,GL_LINK_STATUS,&success);if (!success) {glGetProgramInfoLog(this->Program,512,NULL,infoLog);std::cout<<"ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<<infoLog<<std::endl;}}~Shader(){glDetachShader(this->Program,vertex);glDetachShader(this->Program,fragment);glDeleteShader(vertex);glDeleteShader(fragment);glDeleteProgram(this->Program);}void use(){glUseProgram(this->Program);} };core.vs
#version 330 core layout(location = 0) in vec3 position; //layout(location = 1) in vec3 ourColor; layout(location = 1) in vec3 normal;//out vec3 vertexColor; out vec3 Normal; out vec3 FragPos; uniform mat4 transform;//頂點位置修改 uniform mat4 view; uniform mat4 projection;void main() {gl_Position = projection * view * transform * vec4(position,1.0f);FragPos =vec3 (transform * vec4(position,1.0f)); // vertexColor = ourColor;Normal = mat3(transpose(inverse(transform)))*normal;}core.fs
#version 330 core out vec4 color; //in vec3 vertexColor; in vec3 Normal; in vec3 FragPos;//uniform運行過程中從CPU傳給我們的 uniform float time; uniform vec3 LightPos; uniform vec3 ViewPos;struct Material {float diffuse;float specular;}; uniform Material material;void main() { //color = vec4(vertexColor,1.0f);vec3 lightDirection = normalize(LightPos-FragPos);//光源方向vec3 viewDirection = normalize(ViewPos-FragPos);//視野方向vec3 norm = normalize(Normal);//ambient環境部分 // vec3 ambient = 0.5 * vertexColor;//diffusefloat diff = material.diffuse * max(dot(norm,lightDirection),0.0f);//vec3 diffuse = diff * vertexColor;//specularvec3 halfAngle = normalize(viewDirection + lightDirection);float spec = material.specular * pow(max (dot(norm,halfAngle),0.0f),64.0f);//vec3 specular = spec * vertexColor;color = vec4(1.0f,0.0f,0.0f,1.0f);}light.vs
#version 330 core layout(location = 0) in vec3 position; uniform mat4 transform;//頂點位置修改 uniform mat4 view; uniform mat4 projection; void main() {gl_Position = projection * view * transform * vec4(position,1.0f); }light.fs
#version 330 core out vec4 color; void main() { color = vec4(1.0f,1.0f,1.0f,1.0f);}skybox.vs
#version 330 core layout (location = 0) in vec3 position; out vec3 TexCoords;uniform mat4 projection; uniform mat4 view;void main() {gl_Position = projection * view * vec4(position, 1.0);TexCoords = position; }skybox.fs
#version 330 core in vec3 TexCoords; out vec4 color;uniform samplerCube skybox;void main() {color = texture(skybox, TexCoords); }總結
以上是生活随笔為你收集整理的OpenGL天空盒skybox的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【更新】iWebOffice2009全文
- 下一篇: 利用WireShark破解网站密码