OpenGL Chan視頻學習-9 Index Buffers inOpenGL

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 畫方形

1.1.1方法一

1.1.1.1代碼
//準備數據
float 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};//定義緩沖區對象
unsigned int buffer;
//功能:生成緩沖區對象,并將數據寫入緩沖區
glGenBuffers(1, &buffer);
//功能:將緩沖區對象綁定到目標
glBindBuffer(GL_ARRAY_BUFFER, buffer);
//功能:將數據寫入緩沖區
glBufferData(GL_ARRAY_BUFFER, 2 * 6 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針
glEnableVertexAttribArray(0);
//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
1.1.1.2運行結果

1.1.1.3解釋

在float數組里面直接添加組成繪制方形的兩個三角形所需的六個頂點。

1.1.1.4缺點

頂點冗余

1.1.2方法二——索引緩沖

1.1.1.1代碼
//準備數據
float position[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,0.5f,-0.5f,0.5f,
};//定義頂點索引緩存,用于標定頂點順序
unsigned int indices[] = {0,1,2,2,3,0
};//定義緩沖區對象
unsigned int buffer;
//功能:生成緩沖區對象,并將數據寫入緩沖區
glGenBuffers(1, &buffer);
//功能:將緩沖區對象綁定到目標
glBindBuffer(GL_ARRAY_BUFFER, buffer);
//功能:將數據寫入緩沖區
glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針
glEnableVertexAttribArray(0);
//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);//索引緩沖區對象
unsigned int ibo;
//功能:生成緩沖區對象,并將數據寫入緩沖區
glGenBuffers(1, &ibo);
//功能:將緩沖區對象綁定到目標.沒有綁定為數組緩沖區
//參數:1.GL_ELEMENT_ARRAY_BUFFER:指定目標為索引緩沖區對象
//2.ibo:索引緩沖區對象ID
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
//功能:將數據寫入緩沖區
//參數:1.GL_ELEMENT_ARRAY_BUFFER:指定目標為索引緩沖區對象
//2.6*sizeof(unsigned int):索引數據大小
//3.indices:索引數據指針
//4.GL_STATIC_DRAW:指定數據不會改變
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);

while繪制時改動

//glDrawArrays(GL_TRIANGLES, 0, 6);
//功能:繪制三角形
//參數:1.GL_TRIANGLES:繪制三角形
//2.6:頂點數量
//3.GL_UNSIGNED_INT:索引數據類型
//4.nullptr:索引數據指針
//因為索引緩沖區已經綁定到GL_ELEMENT_ARRAY_BUFFER目標,所以這里不需要再傳入索引數據指針
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
1.1.1.2運行結果

如果不用unsigned,如:

glDrawElements(GL_TRIANGLES, 6, GL_INT, nullptr);

會繪制錯誤

1.1.1.3解釋

利用索引緩沖。避免方法一的重復撰寫,減少內存占用(在實際應用中頂點還包含了顏色,法線等信息)。頂點數從6->4。

QS:position的坐標點怎么和indices聯系起來的

1. 頂點數據 (position?數組)

float position[] = {-0.5f, -0.5f,  // 頂點 00.5f, -0.5f,   // 頂點 10.5f, 0.5f,    // 頂點 2-0.5f, 0.5f    // 頂點 3
};
  • position數組存儲了四個頂點的坐標。
  • 每個頂點由兩個浮點數表示,分別是x和y坐標。
  • 頂點的順序是:左下、右下、右上、左上。

2. 索引數據 (indices?數組)

unsigned int indices[] = {0, 1, 2,  // 三角形 1: 左下 -> 右下 -> 右上2, 3, 0   // 三角形 2: 右上 -> 左上 -> 左下
};
  • indices數組存儲了繪制兩個三角形所需的頂點索引。
  • 索引值對應position數組中頂點的順序。
  • 例如:
    • 第一個三角形的頂點索引是?0, 1, 2,這意味著使用?position?數組中的第0個、第1個和第2個頂點來繪制一個三角形。
    • 第二個三角形的頂點索引是?2, 3, 0,這意味著使用?position?數組中的第2個、第3個和第0個頂點來繪制另一個三角形。

3. 頂點緩沖區對象 (buffer)

unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(float), position, GL_STATIC_DRAW);
  • 生成一個頂點緩沖區對象(VBO),用于存儲頂點數據。
  • 將頂點數據綁定到GL_ARRAY_BUFFER,這是一個用于存儲頂點屬性(如位置、顏色等)的緩沖區目標。
  • 使用glBufferData將頂點數據傳輸到GPU的緩沖區中。

4. 索引緩沖區對象 (ibo)

unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
  • 生成一個索引緩沖區對象(IBO),用于存儲索引數據。
  • 將索引數據綁定到GL_ELEMENT_ARRAY_BUFFER,這是一個用于存儲頂點索引的緩沖區目標。
  • 使用glBufferData將索引數據傳輸到GPU的緩沖區中。

如何聯系起來

  • 頂點緩沖區對象 (buffer)?存儲了頂點的位置數據。
  • 索引緩沖區對象 (ibo)?存儲了頂點的索引數據,這些索引數據告訴OpenGL如何使用頂點緩沖區中的頂點來繪制幾何圖形。

main函數中,使用glDrawElements函數來繪制幾何圖形:

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
  • GL_TRIANGLES:指定繪制的圖形類型為三角形。
  • 6:指定索引的數量(即indices數組的長度)。
  • GL_UNSIGNED_INT:指定索引數據的類型為無符號整數。
  • nullptr:指定索引數據在緩沖區中的偏移量為0。因為索引緩沖區已經綁定到GL_ELEMENT_ARRAY_BUFFER,OpenGL會自動從該緩沖區中讀取索引數據。

詳細聯系過程

  1. 頂點數據綁定

    • position數組中存儲了四個頂點的坐標。
    • 使用glVertexAttribPointer配置頂點屬性指針:
      glEnableVertexAttribArray(0);
      glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
      
    • 這里,0表示頂點屬性的索引,2表示每個頂點有兩個分量(x和y坐標),GL_FLOAT表示數據類型為浮點數。
  2. 索引數據綁定

    • indices數組中存儲了繪制兩個三角形所需的頂點索引。
    • 使用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)將索引數據綁定到GL_ELEMENT_ARRAY_BUFFER
  3. 繪制過程

    • 當調用glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)時,OpenGL會按照indices數組中的索引順序從position數組中獲取頂點數據。
    • 例如:
      • 第一個三角形的索引是?0, 1, 2,OpenGL會獲取position數組中的第0個、第1個和第2個頂點來繪制第一個三角形。
      • 第二個三角形的索引是?2, 3, 0,OpenGL會獲取position數組中的第2個、第3個和第0個頂點來繪制第二個三角形。

總結

  • 頂點緩沖區對象 (buffer)?和?索引緩沖區對象 (ibo)?分別存儲頂點數據和索引數據。
  • glDrawElements?函數使用索引數據來決定如何從頂點緩沖區中提取頂點數據來繪制幾何圖形。
  • 這種方法可以減少頂點數據的冗余存儲,提高內存效率。

二、完整代碼

2.1完全注釋代碼

#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[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,0.5f,-0.5f,0.5f,};//定義頂點索引緩存,用于標定頂點順序unsigned int indices[] = {0,1,2,2,3,0};//定義緩沖區對象unsigned int buffer;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &buffer);//功能:將緩沖區對象綁定到目標glBindBuffer(GL_ARRAY_BUFFER, buffer);//功能:將數據寫入緩沖區glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針glEnableVertexAttribArray(0);//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);//索引緩沖區對象unsigned int ibo;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &ibo);//功能:將緩沖區對象綁定到目標.沒有綁定為數組緩沖區//參數:1.GL_ELEMENT_ARRAY_BUFFER:指定目標為索引緩沖區對象//2.ibo:索引緩沖區對象IDglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);//功能:將數據寫入緩沖區//參數:1.GL_ELEMENT_ARRAY_BUFFER:指定目標為索引緩沖區對象//2.6*sizeof(unsigned int):索引數據大小//3.indices:索引數據指針//4.GL_STATIC_DRAW:指定數據不會改變glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);//解析著色器代碼文件ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;//創建著色器程序unsigned int shader = CreateShader(vertexShader, fragmentShader);//使用著色器程序glUseProgram(shader);//渲染循環,直到窗口被關閉while (!glfwWindowShouldClose(window)){//清除顏色緩沖區glClear(GL_COLOR_BUFFER_BIT);//glDrawArrays(GL_TRIANGLES, 0, 6);//功能:繪制三角形//參數:1.GL_TRIANGLES:繪制三角形//2.6:頂點數量//3.GL_UNSIGNED_INT:索引數據類型//4.nullptr:索引數據指針//因為索引緩沖區已經綁定到GL_ELEMENT_ARRAY_BUFFER目標,所以這里不需要再傳入索引數據指針glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);//刷新緩沖區并交換窗口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[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,0.5f,-0.5f,0.5f,};//定義頂點索引緩存,用于標定頂點順序unsigned int indices[] = {0,1,2,2,3,0};//定義緩沖區對象unsigned int buffer;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &buffer);//功能:將緩沖區對象綁定到目標glBindBuffer(GL_ARRAY_BUFFER, buffer);//功能:將數據寫入緩沖區glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(float), position, GL_STATIC_DRAW);//功能:配置頂點屬性指針glEnableVertexAttribArray(0);//功能:指定頂點屬性數組的索引、大小、數據類型、是否歸一化、偏移量、數據指針glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);//索引緩沖區對象unsigned int ibo;//功能:生成緩沖區對象,并將數據寫入緩沖區glGenBuffers(1, &ibo);//功能:將緩沖區對象綁定到目標.沒有綁定為數組緩沖區//參數:1.GL_ELEMENT_ARRAY_BUFFER:指定目標為索引緩沖區對象//2.ibo:索引緩沖區對象IDglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);//功能:將數據寫入緩沖區glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);//解析著色器代碼文件ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;//創建著色器程序unsigned int shader = CreateShader(vertexShader, fragmentShader);//使用著色器程序glUseProgram(shader);//渲染循環,直到窗口被關閉while (!glfwWindowShouldClose(window)){//清除顏色緩沖區glClear(GL_COLOR_BUFFER_BIT);//glDrawArrays(GL_TRIANGLES, 0, 6);//功能:繪制三角形//參數:1.GL_TRIANGLES:繪制三角形glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);//刷新緩沖區并交換窗口glfwSwapBuffers(window);//處理窗口事件,如鍵盤輸入、鼠標移動等glfwPollEvents();}//刪除著色器程序//glDeleteProgram(shader);//釋放 GLFW 庫占用的所有資源。glfwTerminate();return 0;
}

2.3運行結果

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82940.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82940.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82940.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于微服務架構的社交學習平臺WEB系統的設計與實現

設計&#xff08;論文&#xff09;題目 基于微服務架構的社交學習平臺WEB系統的設計與實現 摘 要 社交學習平臺 web 系統要為學習者打造一個開放、互動且社交性強的在線教育環境&#xff0c;打算采用微服務架構來設計并實現一個社交學習平臺 web 系統&#xff0c;以此適應學…

生成式人工智能:重構軟件開發的范式革命與未來生態

引言 生成式人工智能&#xff08;GenAI&#xff09;正以顛覆性力量重塑軟件開發的底層邏輯。從代碼生成到業務邏輯設計&#xff0c;從數據分析到用戶交互&#xff0c;GenAI通過其強大的推理能力與場景適應性&#xff0c;將傳統開發流程的“復雜工程”轉化為“敏捷實驗”&#…

C++17原生測試編程實踐:現代特性與分支覆蓋指南

C17原生測試編程實踐&#xff1a;現代特性與分支覆蓋指南 概述 本文將深入探討如何利用C17新特性進行原生測試代碼編寫&#xff0c;實現完全分支覆蓋。我們將不依賴任何外部測試框架&#xff0c;而是使用C17標準庫構建完整的測試解決方案。 一、C17測試核心工具集 1. 斷言工…

RK3568項目(四)--uboot啟動流程之啟動模式選擇

目錄 一、引言 二、芯片初始化 ------>2.1、io_domain ------>2.2、調頻調壓 ------>2.3、控制臺初始化 三、平臺初始化 ------>3.1、設置mac地址 ------------>3.1.1、vendor分區 ------>3.2、設置serialno ------>3.3、設置下載模式 -------…

Kotlin JVM 注解詳解

前言 Kotlin 作為一門現代 JVM 語言&#xff0c;提供了出色的 Java 互操作性。為了更好地支持與 Java 代碼的交互&#xff0c;Kotlin 提供了一系列 JVM 相關注解。這些注解不僅能幫助我們控制 Kotlin 代碼編譯成 Java 字節碼的行為&#xff0c;還能讓我們的 Kotlin 代碼更好地…

Starrocks 物化視圖的實現以及在刷新期間能否讀數據

背景 本司在用Starrocks做一些業務上的分析的時候&#xff0c;用到了物化視圖&#xff0c;并且在高QPS的情況下&#xff0c;RT也沒有很大的波動&#xff0c;所以在此研究一下Starrock的實現&#xff0c;以及在刷新的時候是不是原子性的 本文基于Starrocks 3.3.5 結論 Starro…

[網頁五子棋][對戰模塊]前后端交互接口(建立連接、連接響應、落子請求/響應),客戶端開發(實現棋盤/棋子繪制)

文章目錄 約定前后端交互接口建立連接建立連接響應針對"落子"的請求和響應 客戶端開發實現棋盤/棋子繪制部分邏輯解釋 約定前后端交互接口 對戰模塊和匹配模塊使用的是兩套邏輯&#xff0c;使用不同的 websocket 的路徑進行處理&#xff0c;做到更好的耦合 建立連接 …

電工基礎【2】自鎖、互鎖、正反轉電路

04 自鎖、正反轉電路 我們講一下這個自鎖和正反轉。 自鎖電路圖示例圖 加了一個這個 KM1 自鎖。加了 KM1 的輔助觸頭&#xff0c;它怎么實現呢&#xff1f;它怎么就自鎖了呢&#xff1f;沒加它的時候為什么是點動&#xff1f;加它為什么自鎖&#xff1f; 講解一下。首先我們…

TypeScript 中感嘆號(!)兩種位置用法

這是一個非常好的問題&#xff01; 在 TypeScript 中&#xff0c;感嘆號&#xff08;!&#xff09;有兩種位置用法&#xff0c;它們含義完全不同&#xff1a; ? 一、后置感嘆號 !&#xff08;非空斷言&#xff09; process.env.ADMIN_PRIVATE_KEY! ? 作用&#xff1a; 告…

t014-項目申報管理系統 【springBoot 含源碼】

項目演示視頻 摘 要 傳統信息的管理大部分依賴于管理人員的手工登記與管理&#xff0c;然而&#xff0c;隨著近些年信息技術的迅猛發展&#xff0c;讓許多比較老套的信息管理模式進行了更新迭代&#xff0c;項目信息因為其管理內容繁雜&#xff0c;管理數量繁多導致手工進行…

【C++】STL詳解(四)---Stack和Queue

文章目錄 Stack定義方式使用方式 Queue定義方式使用方式 Stack Stack是一種容器&#xff0c;是基本的數據結構之一&#xff0c;特點是先進后出。 定義方式 方式一&#xff1a;普通定義方式 stack<int> st1;方式二&#xff1a; stack<int,vector<int>> …

解決 xmlsec.InternalError: (-1, ‘lxml xmlsec libxml2 library version mismatch‘)

解決 xmlsec.InternalError: (-1, ‘lxml & xmlsec libxml2 library version mismatch’) 錯誤信息如下&#xff1a; Traceback (most recent call last):File "/home/mobsf/Mobile-Security-Framework-MobSF/manage.py", line 18, in <module>execute_f…

SpringBoot自定義實體類字段的校驗注解

在Spring Boot項目中&#xff0c;我們經常需要對請求參數進行格式或業務規則的校驗。雖然Spring Boot提供了如NotNull、Size等基礎校驗注解&#xff0c;但在實際開發中往往無法滿足復雜的業務需求。但是在Controller層寫大量的 if 語句的判斷邏輯又實在不優雅&#xff0c;好在 …

實現單例模式的6種方法(Python)

目錄 一. 基于模塊的實現(簡單&#xff0c;易用) 二. 重新創建時報錯(不好用) 三. 只靠方法獲取實例(不好用) 四. 類裝飾器 五. 重寫__new__方法 六. 元類 七. 總結 單例模式&#xff08;Singleton Pattern&#xff09;是一種設計模式&#xff0c;其核心目標是確保一個類…

循環神經網絡(RNN)全面教程:從原理到實踐

循環神經網絡(RNN)全面教程&#xff1a;從原理到實踐 引言 循環神經網絡(Recurrent Neural Network, RNN)是處理序列數據的經典神經網絡架構&#xff0c;在自然語言處理、語音識別、時間序列預測等領域有著廣泛應用。本文將系統介紹RNN的核心概念、常見變體、實現方法以及實際…

使用Vditor將Markdown文檔渲染成網頁(Vite+JS+Vditor)

1. 引言 編寫Markdown文檔現在可以說是程序員的必備技能了&#xff0c;因為Markdown很好地實現了內容與排版分離&#xff0c;可以讓程序員更專注于內容的創作。現在很多技術文檔&#xff0c;博客發布甚至AI文字輸出的內容都是以Markdown格式的形式輸出的。那么&#xff0c;Mar…

Day 40

單通道圖片的規范寫法 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader , Dataset from torchvision import datasets, transforms import matplotlib.pyplot as plt import warnings warnings.filterwarnings(&q…

SPSS跨域分類:自監督知識+軟模板優化

1. 圖1:SPSS方法流程圖 作用:展示了SPSS方法的整體流程,從數據預處理到模型預測的關鍵步驟。核心內容: 領域知識提取:使用三種詞性標注工具(NLTK、spaCy、TextBlob)從源域和目標域提取名詞或形容詞(如例句中提取“excellent”“good”等形容詞)。詞匯交集與聚類:對提…

2025年通用 Linux 服務器操作系統該如何選擇?

2025年通用 Linux 服務器操作系統該如何選擇&#xff1f; 服務器操作系統的選擇對一個企業IT和云服務影響很大&#xff0c;主推的操作系統在后期更換的成本很高&#xff0c;而且也有很大的遷移風險&#xff0c;所以企業在選擇服務器操作系統時要尤為重視。 之前最流行的服務器…

如何在 Django 中集成 MCP Server

目錄 背景說明第一步&#xff1a;使用 ASGI第二步&#xff1a;修改 asgi.py 中的應用第三步&#xff1a;Django 數據的異步查詢 背景說明 有幾個原因導致 Django 集成 MCP Server 比較麻煩 目前支持的 MCP 服務是 SSE 協議的&#xff0c;需要長連接&#xff0c;但一般來講 Dj…