bilibili視頻鏈接:
【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p=5&vd_source=44b77bde056381262ee55e448b9b1973
函數網站:
docs.gl
說明:
1.之后就不再整理具體函數了,網站直接翻譯會更直觀也會有更多注意點。直接通過csdn索引查找反而會慢。
2.代碼區域會單獨注釋功能參數返回值和相關注意事項。
3.課程學習從4-本節,如果有些函數沒有注釋可以看專欄里面的前面發表的文章,一般會有解釋。 4.如果覺得代碼注釋白色字體不太直觀可以直接copy到相應軟件看。
5.有兩種版本的可供查看:注釋全面的和注釋簡潔版的,可以在索引里面找到相關代碼查看。
6.希望能幫到你。
7.有錯誤請跟我說明一下,可能整理的時候沒有檢查好。
一、知識點整理
1.1?ShaderProgramSource結構體
//功能:定義ShaderProgramSource結構體,用于存儲著色器代碼
//方便ParseShader函數返回多個著色器代碼
struct ShaderProgramSource
{std::string VertexSource;std::string FragmentSource;
};
1.2ParseShader函數
//功能:解析著色器代碼文件。
//參數:filepath:著色器代碼文件路徑
//返回值:ShaderProgramSource結構體,包含著色器代碼字符串
static ShaderProgramSource ParseShader(const std::string& filepath)
{//功能:打開文件流//參數:filepath:著色器代碼文件路徑std::ifstream stream(filepath);//定義著色器類型enum class ShaderType{NONE=-1,VERTEX=0,FRAGMENT=1};//該變量用于存儲著色器代碼std::string line;//該變量用于存儲著色器類型std::stringstream ss[2];//該變量是當前著色器類型ShaderType type = ShaderType::NONE;//功能:讀取文件中的每一行內容,直到文件結束while (getline(stream, line)){//如果當前行包含#shader,則說明接下來是著色器代碼//nposstd::string::npos 是 C++ 標準庫中 std::string 類的一個靜態成員。//它代表了一個無效的位置值,通常用于表示在字符串中未找到子字符串的情況。if (line.find("#shader") != std::string::npos){//如果當前行包含vertex,則說明接下來是頂點著色器代碼if (line.find("vertex") != std::string::npos){type = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos){type = ShaderType::FRAGMENT;}}else{//否則,將當前行添加到對應著色器代碼的stringstream中//ss[]是一個數組,用于存儲著色器代碼,通過ss[]<<line<<'\n'將當前行添加到對應著色器代碼的stringstream中ss[(int)type] << line << '\n';std::cout << line << " hhh" << std::endl;}}//返回ShaderProgramSource結構體return { ss[0].str(), ss[1].str() };
}
1.3int main函數補充
//解析著色器代碼文件
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");
std::string vertexShader = source.VertexSource;
std::string fragmentShader = source.FragmentSource;std::cout << "VERTEX" << std::endl << vertexShader << std::endl;
std::cout << "FRAGMENT" << std::endl << fragmentShader << std::endl;
二、完整代碼
1.1完全注釋代碼
#include <GL/glew.h>
#include <GLFW/glfw3.h>#include<iostream>
#include<fstream>
#include<string>
#include<sstream>//功能:定義ShaderProgramSource結構體,用于存儲著色器代碼
//方便ParseShader函數返回多個著色器代碼
struct ShaderProgramSource
{std::string VertexSource;std::string FragmentSource;
};//功能:解析著色器代碼文件。
//參數:filepath:著色器代碼文件路徑
//返回值:ShaderProgramSource結構體,包含著色器代碼字符串
static ShaderProgramSource ParseShader(const std::string& filepath)
{//功能:打開文件流//參數:filepath:著色器代碼文件路徑std::ifstream stream(filepath);//定義著色器類型enum class ShaderType{NONE=-1,VERTEX=0,FRAGMENT=1};//該變量用于存儲著色器代碼std::string line;//該變量用于存儲著色器類型std::stringstream ss[2];//該變量是當前著色器類型ShaderType type = ShaderType::NONE;//功能:讀取文件中的每一行內容,直到文件結束while (getline(stream, line)){//如果當前行包含#shader,則說明接下來是著色器代碼//nposstd::string::npos 是 C++ 標準庫中 std::string 類的一個靜態成員。//它代表了一個無效的位置值,通常用于表示在字符串中未找到子字符串的情況。if (line.find("#shader") != std::string::npos){//如果當前行包含vertex,則說明接下來是頂點著色器代碼if (line.find("vertex") != std::string::npos){type = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos){type = ShaderType::FRAGMENT;}}else{//否則,將當前行添加到對應著色器代碼的stringstream中//ss[]是一個數組,用于存儲著色器代碼,通過ss[]<<line<<'\n'將當前行添加到對應著色器代碼的stringstream中ss[(int)type] << line << '\n';}}//返回ShaderProgramSource結構體return { ss[0].str(), ss[1].str() };
}//功能:編譯著色器代碼
static unsigned int CompilesShader(unsigned int type, const std::string& source)
{//功能:創建著色器對象unsigned int id = glCreateShader(type);//功能:設置著色器源代碼.const char* src = source.c_str();//功能:替換著色器對象中的源代碼。將該id的指定著色器的源代碼設置為src指針指向的字符串glShaderSource(id, 1, &src, nullptr);//功能:編譯著色器對象的源代碼glCompileShader(id);//設置返回著色器的對象IDint result;//功能:從著色器對象返回一個參數,表示編譯是否成功。glGetShaderiv(id, GL_COMPILE_STATUS, &result);//如果編譯失敗,則輸出錯誤信息if (result == GL_FALSE){int length;//功能:獲取編譯錯誤信息的長度glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);//分配內存,用于存儲編譯錯誤信息char* message = (char*)alloca(length*sizeof(char));//功能:獲取編譯錯誤信息glGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;std::cout << message << std::endl;//刪除著色器對象glDeleteShader(id);return 0;}//TODO:錯誤處理ingreturn id;
}//功能:創建著色器程序
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{//創建程序對象unsigned int program = glCreateProgram();//編譯頂點著色器對象unsigned int vs = CompilesShader(GL_VERTEX_SHADER, vertexShader);//編譯片段著色器對象unsigned int fs = CompilesShader(GL_FRAGMENT_SHADER, fragmentShader);//功能:將編譯好的著色器對象附加到程序對象中glAttachShader(program, vs);glAttachShader(program, fs);//功能:鏈接程序對象glLinkProgram(program);//功能:驗證著色器程序對象是否可以在當前OpenGL狀態中執行。檢查著色器程序的完整性和可執行性。glValidateProgram(program);//刪除著色器對象,因為它們已經被鏈接到程序對象中glDeleteShader(vs);glDeleteShader(fs);//返回著色器程序return program;
}int main(void)
{GLFWwindow* window;//初始化glfwif (!glfwInit())return -1;//創建一個窗口模式的窗口并設置OpenGL上下文window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window)//如果窗口創建失敗,則終止程序{glfwTerminate();//釋放glfw資源return -1;}//設置當前窗口的上下文,之后所有的OpenGL調用都會在這個上下文中進行glfwMakeContextCurrent(window);//初始化GLEWif (glewInit() != GLEW_OK)std::cout << "Error!" << std::endl;//打印OpenGL版本信息std::cout << glGetString(GL_VERSION) << std::endl;//準備數據float position[6] = {0.0f, 0.5f,-0.5f, -0.5f,0.5f, -0.5f};//定義緩沖區對象unsigned int buffer;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &buffer);//功能:將緩沖區對象綁定到目標glBindBuffer(GL_ARRAY_BUFFER, buffer);//功能:將數據寫入緩沖區glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針glEnableVertexAttribArray(0);//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);//解析著色器代碼文件ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;std::cout << "VERTEX" << std::endl << vertexShader << std::endl;std::cout << "FRAGMENT" << std::endl << fragmentShader << std::endl;//創建著色器程序unsigned int shader = CreateShader(vertexShader, fragmentShader);//使用著色器程序glUseProgram(shader);//渲染循環,直到窗口被關閉while (!glfwWindowShouldClose(window)){//清除顏色緩沖區glClear(GL_COLOR_BUFFER_BIT);//功能:繪制三角形glDrawArrays(GL_TRIANGLES, 0, 3);//刷新緩沖區并交換窗口glfwSwapBuffers(window);//處理窗口事件,如鍵盤輸入、鼠標移動等glfwPollEvents();}//刪除著色器程序//glDeleteProgram(shader);//釋放 GLFW 庫占用的所有資源。glfwTerminate();return 0;
}
2.2簡潔注釋代碼
#include <GL/glew.h>
#include <GLFW/glfw3.h>#include<iostream>
#include<fstream>
#include<string>
#include<sstream>//功能:定義ShaderProgramSource結構體,用于存儲著色器代碼
struct ShaderProgramSource
{std::string VertexSource;std::string FragmentSource;
};//功能:解析著色器代碼文件。
static ShaderProgramSource ParseShader(const std::string& filepath)
{//功能:打開文件流std::ifstream stream(filepath);//定義著色器類型enum class ShaderType{NONE=-1,VERTEX=0,FRAGMENT=1};//該變量用于存儲著色器代碼std::string line;//該變量用于存儲著色器類型std::stringstream ss[2];//該變量是當前著色器類型ShaderType type = ShaderType::NONE;//功能:讀取文件中的每一行內容,直到文件結束while (getline(stream, line)){//如果當前行包含#shader,則說明接下來是著色器代碼if (line.find("#shader") != std::string::npos){//如果當前行包含vertex,則說明接下來是頂點著色器代碼if (line.find("vertex") != std::string::npos){type = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos){type = ShaderType::FRAGMENT;}}else{//否則,將當前行添加到對應著色器代碼的stringstream中ss[(int)type] << line << '\n';}}//返回ShaderProgramSource結構體return { ss[0].str(), ss[1].str() };
}//功能:編譯著色器代碼
static unsigned int CompilesShader(unsigned int type, const std::string& source)
{//功能:創建著色器對象unsigned int id = glCreateShader(type);//功能:設置著色器源代碼.const char* src = source.c_str();//功能:替換著色器對象中的源代碼。將該id的指定著色器的源代碼設置為src指針指向的字符串glShaderSource(id, 1, &src, nullptr);//功能:編譯著色器對象的源代碼glCompileShader(id);//設置返回著色器的對象IDint result;//功能:從著色器對象返回一個參數,表示編譯是否成功。glGetShaderiv(id, GL_COMPILE_STATUS, &result);//如果編譯失敗,則輸出錯誤信息if (result == GL_FALSE){int length;//功能:獲取編譯錯誤信息的長度glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);//分配內存,用于存儲編譯錯誤信息char* message = (char*)alloca(length*sizeof(char));//功能:獲取編譯錯誤信息glGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile shader!" << (type == GL_VERTEX_SHADER? "Vertex" : "Fragment") << "shader!" << std::endl;std::cout << message << std::endl;//刪除著色器對象glDeleteShader(id);return 0;}//TODO:錯誤處理ingreturn id;
}//功能:創建著色器程序
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{//創建程序對象unsigned int program = glCreateProgram();//編譯頂點著色器對象unsigned int vs = CompilesShader(GL_VERTEX_SHADER, vertexShader);//編譯片段著色器對象unsigned int fs = CompilesShader(GL_FRAGMENT_SHADER, fragmentShader);//功能:將編譯好的著色器對象附加到程序對象中glAttachShader(program, vs);glAttachShader(program, fs);//功能:鏈接程序對象glLinkProgram(program);//功能:驗證著色器程序對象是否可以在當前OpenGL狀態中執行。檢查著色器程序的完整性和可執行性。glValidateProgram(program);//刪除著色器對象,因為它們已經被鏈接到程序對象中glDeleteShader(vs);glDeleteShader(fs);//返回著色器程序return program;
}int main(void)
{GLFWwindow* window;//初始化glfwif (!glfwInit())return -1;//創建一個窗口模式的窗口并設置OpenGL上下文window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window)//如果窗口創建失敗,則終止程序{glfwTerminate();//釋放glfw資源return -1;}//設置當前窗口的上下文,之后所有的OpenGL調用都會在這個上下文中進行glfwMakeContextCurrent(window);//初始化GLEWif (glewInit() != GLEW_OK)std::cout << "Error!" << std::endl;//打印OpenGL版本信息std::cout << glGetString(GL_VERSION) << std::endl;//準備數據float position[6] = {0.0f, 0.5f,-0.5f, -0.5f,0.5f, -0.5f};//定義緩沖區對象unsigned int buffer;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &buffer);//功能:將緩沖區對象綁定到目標glBindBuffer(GL_ARRAY_BUFFER, buffer);//功能:將數據寫入緩沖區glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針glEnableVertexAttribArray(0);//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);//解析著色器代碼文件ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;std::cout << "VERTEX" << std::endl << vertexShader << std::endl;std::cout << "FRAGMENT" << std::endl << fragmentShader << std::endl;//創建著色器程序unsigned int shader = CreateShader(vertexShader, fragmentShader);//使用著色器程序glUseProgram(shader);//渲染循環,直到窗口被關閉while (!glfwWindowShouldClose(window)){//清除顏色緩沖區glClear(GL_COLOR_BUFFER_BIT);//功能:繪制三角形glDrawArrays(GL_TRIANGLES, 0, 3);//刷新緩沖區并交換窗口glfwSwapBuffers(window);//處理窗口事件,如鍵盤輸入、鼠標移動等glfwPollEvents();}//刪除著色器程序//glDeleteProgram(shader);//釋放 GLFW 庫占用的所有資源。glfwTerminate();return 0;
}