OpenGL 自定义着色器(Shaders)
生活随笔
收集整理的這篇文章主要介紹了
OpenGL 自定义着色器(Shaders)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
自定義著色器類
聲明
#pragma once#include<string>class Shaders { public:Shaders(const char* vertexPath, const char* fragmentPath);~Shaders();std::string vertexString;std::string fragmentString;const char* vertexSource;const char* fragmentSource;unsigned int ID; // shaderProgram 的idvoid use(); private:void checkCompileErrors(unsigned int id, std::string type);};源文件
#include "Shaders.h" #include<fstream> #include<iostream> #include<sstream> #define GLEW_STATIC // 這個一定要加不然報錯 靜態鏈接庫 #include<GL/glew.h> #include<GLFW/glfw3.h>Shaders::Shaders(const char* vertexPath, const char* fragmentPath ) {std::ifstream vertexFile;std::ifstream fragmentFile;std::stringstream vertexSStream;std::stringstream fragmentSStream;vertexFile.open(vertexPath);fragmentFile.open(fragmentPath);vertexFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);fragmentFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);try {if (!vertexFile.is_open() || !fragmentFile.is_open()) {throw std::exception("open file error");}// 將 輸入流的內容輸出給 stringstreamvertexSStream << vertexFile.rdbuf();fragmentSStream << fragmentFile.rdbuf();vertexString = vertexSStream.str();fragmentString = fragmentSStream.str();vertexSource = vertexString.c_str();fragmentSource = fragmentString.c_str();unsigned int vertex, fragment;// 創建這個著色器vertex = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex, 1, &vertexSource, NULL);// 編譯glCompileShader(vertex);checkCompileErrors(vertex, "VERTEX");fragment = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment, 1, &fragmentSource, NULL);// 編譯glCompileShader(fragment);checkCompileErrors(fragment, "FRAGMENT");//創建一個著色器程序對象ID = glCreateProgram();// 將之前編譯的著色器附加到程序對象上glAttachShader(ID, vertex);glAttachShader(ID, fragment);// 用glLinkProgram鏈接它們glLinkProgram(ID);checkCompileErrors(ID, "PROGRAM");//刪除著色器glDeleteShader(vertex);glDeleteShader(fragment);}catch (const std::exception& ex) {std::cout << ex.what() << std::endl;} } void Shaders::use() {glUseProgram(ID); } void Shaders::checkCompileErrors(unsigned int id, std::string type) {int success;char infoLog[512];if (type != "PROGRAM") {glGetShaderiv(id, GL_COMPILE_STATUS,&success);if (!success) {glGetShaderInfoLog(id, 512, NULL, infoLog);std::cout << "shader compile error:" << infoLog << std::endl;}}else {glGetProgramiv(id, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(id, 512, NULL, infoLog);std::cout << "program compile error:" << infoLog << std::endl;}} } Shaders::~Shaders() {}程序入口
#define GLEW_STATIC // 這個一定要加不然報錯 靜態鏈接庫 #include<GL/glew.h> #include<GLFW/glfw3.h> #include<iostream> #include "Shaders.h" using namespace std; void processInput(GLFWwindow); void processInput(GLFWwindow* window) {//如果鍵盤輸入esc 則觸發 退出if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {// 設置 要求退出glfwSetWindowShouldClose(window, true);} } // 逆時針方向繪制 默認情況下,逆時針的頂點連接順序被定義為三角形的正 // 逆時針或順時針都是相對于觀察者方向的 float vertices[] {-0.5f, 0.5f, 0.0f, 1.0f, 0,0, // 左上角 0 0.5f, -0.5f, 0.0f, 0,1.0f,0, // 右下角 10.5f, 0.5f, 0.0f, 0,0,1.0f, // 右上角 2// 第二個三角形//0.5f, -0.5f, 0.0f, // 右下角-0.5f, -0.5f, 0.0f , 1.0f,0,1.0f // 左下角 3//-0.5f, 0.5f, 0.0f // 左上角 }; // 使用索引來減小畫點的開銷 (未用索引緩沖對象時,每個點都需要畫一次(即使重復了)) unsigned int indices[] {0,1,2, //第一個三角形的索引1,3,0 //第二個三角形的索引 };int main() {// 初始化GLFWglfwInit();// 提示 我們使用的版本是3.3// 主版本glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// 次版本glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);// 簡介glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 創建一個窗口對象GLFWwindow* window = glfwCreateWindow(800, 600, "Test window", NULL, NULL);if (window == NULL) {cout << "open window failed." << endl;// 終止 glfwglfwTerminate();}// 綁定window到上下文對象 創建完窗口我們就可以通知GLFW將我們窗口的上下文設置為當前線程的主上下文了glfwMakeContextCurrent(window);glewExperimental = true;// GLEW_OK 0//init GLEWif (glewInit() != GLEW_OK) {cout << "glew init failed." << endl;// 終止 glfwglfwTerminate();return -1;}// OpenGL渲染窗口的尺寸大小 // glViewport函數前兩個參數控制窗口左下角的位置。第三個和第四個參數控制渲染窗口的寬度和高度(像素)glViewport(0, 0, 800, 600);// 設置剔除 (opegl默認正面背面都顯示(不剔除))//glEnable(GL_CULL_FACE);// 剔除背面 GL_BACK 剔除正面 GL_FRONT//glCullFace(GL_BACK);// 線框模式 //第一個參數表示我們打算將其應用到所有的三角形的正面和背面,第二個參數告訴我們用線來繪制//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//VAO對象unsigned int VAO;// 生成一個VAO對象 這個方法可以生成多個 由第一個參數決定glGenVertexArrays(1, &VAO);// 綁定 VAOglBindVertexArray(VAO);unsigned int VBO; //如果多個可以用 VBO[]數組 這個方法可以生成多個 由第一個參數決定glGenBuffers(1, &VBO);//將新創建的緩沖綁定到 GL_ARRAY_BUFFER目標上glBindBuffer(GL_ARRAY_BUFFER, VBO);// glBufferData 是一個專門用來把用戶定義的數據復制到當前綁定緩沖的函數// GL_STATIC_DRAW 數據不會或幾乎不會改變。glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);unsigned int EBO;glGenBuffers(1, &EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);Shaders* shaders = new Shaders("./vertexSource.txt", "./fragmentSource.txt");// glVertexAttribPointer函數告訴OpenGL該如何解析頂點數據(應用到逐個頂點屬性上)// 從 0號欄位 開始 將數據每三個為一組 單位為float 每次跳6*float字節 偏移為0glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);// 以頂點屬性位置值作為參數,啟用頂點屬性;頂點屬性默認是禁用的//讀取到0號欄位上glEnableVertexAttribArray(0);// 讀取顏色屬性 從 1號欄位 開始 將數據每三個為一組 單位為float 每次跳6*float字節 偏移為3個floatglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));// 讀取到1號欄位上 glEnableVertexAttribArray(1);//渲染循環 ,它能在我們讓GLFW退出前一直保持運行。下面幾行的代碼就實現了一個簡單的渲染循環://glfwWindowShouldClose 我們每次循環的開始前檢查一次GLFW是否被要求退出while (!glfwWindowShouldClose(window)) {//自定義事件 當鍵盤觸發esc 退出processInput(window);glClearColor(0.2, 0.3, 0.3, 1.0);// GL_COLOR_BUFFER_BIT 顏色,GL_DEPTH_BUFFER_BIT 深度 和 GL_STENCIL_BUFFER_BIT 模板// 清除前面的那一幀的顏色glClear(GL_COLOR_BUFFER_BIT);// 綁定 VAO glBindVertexArray(VAO);shaders->use();// 畫三角形 從0開始 繪制三個頂點 和VBO的頂點數據(通過VAO間接綁定)來繪制圖元//glDrawArrays(GL_TRIANGLES, 0, 6); 這個是不用索引畫的glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//可以不需要這個 綁定VAO的同時也會自動綁定EBO//glDrawElements函數從當前綁定到GL_ELEMENT_ARRAY_BUFFER目標的EBO中獲取索引glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//解綁VAOglBindVertexArray(0);glfwSwapBuffers(window);glfwPollEvents();}// 最后終止 glfwglfwTerminate();return 0; }著色器
頂點著色器
#version 330 core // 0號欄位讀取頂點坐標 layout (location = 0) in vec3 aPos; //1號欄位讀取顏色顏色 layout (location = 1) in vec3 aColor; out vec4 vertexColor; void main() { // gl_Position 是固定的名稱 用來保存 頂點坐標的gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); vertexColor = vec4(aColor.x+0.5,aColor.y,aColor.z,1.0); }片段著色器
#version 330 core out vec4 FragColor; //uniform vec4 outColor; in vec4 vertexColor; void main() { FragColor = vertexColor; }未報錯效果
報錯的效果
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的OpenGL 自定义着色器(Shaders)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS 7 搭建swagger A
- 下一篇: 智能指针分配动态数组