五、OpenGL中Shader與C++數據傳輸

文章目錄

    • 一、概述
    • 二、Shader 代碼文件的基本格式
    • 三、Shader的向量語法介紹
    • 四、Shader之間的數據傳輸
    • 五、Shader與C++的數據傳輸uniform
    • 六、完整示例

一、概述

在 OpenGL 中,Shader(著色器)使用 GLSL(OpenGL Shading Language) 編寫,GLSL 是一種類似 C 語言的著色器編程語言。著色器的基本語法包括 版本聲明、變量聲明、主函數 等。

二、Shader 代碼文件的基本格式

每個 Shader 代碼文件的基本格式如下:

#version version_number
in type in_variable_name;
in type in_variable_name;out type out_variable_name;uniform type uniform_name;void main()
{out_variable_name = weird_stuff_we_processed;
}

1. 版本聲明

#version version_number

作用:指定 GLSL 版本號。
示例:

  • #version 330 core (OpenGL 3.3)
  • #version 450 core (OpenGL 4.5)

不同的 OpenGL 版本支持不同的 GLSL 語法特性,使用適當的版本號可以確保著色器代碼正確編譯。

2. 輸入變量(in)

in type in_variable_name;
in type in_variable_name;

作用:定義輸入變量,接收數據。
適用范圍:

  • 頂點著色器(Vertex Shader):接收 CPU 傳遞的頂點數據(如位置、顏色、法線等)。
  • 片段著色器(Fragment Shader):接收 來自頂點著色器的插值數據。

示例(頂點著色器輸入):

in vec3 aPos;    // 頂點坐標
in vec3 aColor;  // 頂點顏色

示例(片段著色器輸入):

in vec3 vertexColor; // 頂點著色器傳遞的顏色

3. 輸出變量(out)

out type out_variable_name;

作用:

  • 頂點著色器(Vertex Shader):將數據傳遞到片段著色器。
  • 片段著色器(Fragment Shader):輸出最終的像素顏色。

示例(頂點著色器的輸出):

out vec3 vertexColor;  // 傳遞顏色到片段著色器

示例(片段著色器的輸出):

out vec4 FragColor;  // 最終的片段顏色

4. Uniform(全局變量)

uniform type uniform_name;

作用:

  • uniform 變量是全局變量,在 CPU 側由 OpenGL 代碼設置,可用于變換矩陣、光照參數、時間變量等。
  • uniform 變量的值在 所有頂點/片段之間保持一致,不會在不同的頂點或片段間變化。

示例(用于變換矩陣):

uniform mat4 model;       // 模型變換矩陣
uniform mat4 view;        // 視圖變換矩陣
uniform mat4 projection;  // 投影變換矩陣

示例(用于紋理):

uniform sampler2D texture1;  // 紋理

5. main() 主函數

void main()
{out_variable_name = weird_stuff_we_processed;
}

作用:

  • main() 函數是 GLSL 的入口點,每個 頂點(頂點著色器)或 像素(片段著色器)都會執行一次。
  • out_variable_name = weird_stuff_we_processed; 表示計算并輸出結果。

完整示例
(1)頂點著色器

#version 330 corelayout(location = 0) in vec3 aPos;    // 頂點坐標
layout(location = 1) in vec3 aColor;  // 頂點顏色out vec3 vertexColor; // 傳遞給片段著色器的顏色uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0);vertexColor = aColor;  // 傳遞顏色
}

解析:

  • in 變量 aPos:接收 CPU 傳來的頂點坐標數據。
  • in 變量 aColor:接收 CPU 傳來的頂點顏色數據。
  • out 變量 vertexColor:將顏色傳遞到片段著色器。
  • uniform 變量 model, view, projection:用于變換矩陣,調整頂點位置。

(2) 片段著色器

#version 330 corein vec3 vertexColor; // 從頂點著色器接收的顏色
out vec4 FragColor;  // 最終顏色輸出void main()
{FragColor = vec4(vertexColor, 1.0);
}

解析:

  • in 變量 vertexColor:接收 頂點著色器傳遞的顏色。
  • out 變量 FragColor:輸出最終的片段顏色。

總結:
在這里插入圖片描述

三、Shader的向量語法介紹

在 GLSL(OpenGL Shading Language)中,向量(Vector)是圖形渲染中最常用的數據類型之一,主要用于存儲坐標、顏色、法線、紋理坐標等信息。GLSL 提供了vec2、vec3、vec4 這三種向量類型,以及多種操作方式。

1. 向量類型
GLSL 主要支持以下浮點型向量:
在這里插入圖片描述
此外,還有整型和布爾型向量:
在這里插入圖片描述
2. 向量初始化
GLSL 支持多種方式初始化向量:

(1) 直接賦值

vec2 a = vec2(1.0, 2.0);
vec3 b = vec3(0.5, 0.2, 0.7);
vec4 c = vec4(1.0, 0.0, 0.5, 1.0);

(2) 復制構造

vec3 v1 = vec3(0.5);   // v1 = (0.5, 0.5, 0.5)
vec4 v2 = vec4(v1, 1.0); // v2 = (0.5, 0.5, 0.5, 1.0)

(3) 通過其它向量構造

vec2 v = vec2(0.3, 0.6);
vec4 newVec = vec4(v, 1.0, 0.0);  // newVec = (0.3, 0.6, 1.0, 0.0)

3. 向量分量訪問(Swizzling)
GLSL 允許使用 .x, .y, .z, .w 訪問或重新排列向量的分量,類似于 struct 的成員訪問。

(1) 訪問單個分量

vec4 color = vec4(0.2, 0.5, 0.7, 1.0);
float red = color.x;   // red = 0.2
float alpha = color.w; // alpha = 1.0

(2) 訪問多個分量(Swizzling)

vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
vec2 v2 = pos.xy;   // v2 = (1.0, 2.0)
vec3 v3 = pos.zyx;  // v3 = (3.0, 2.0, 1.0)
vec4 v4 = pos.xxyy; // v4 = (1.0, 1.0, 2.0, 2.0)

(3) 組合不同分量

vec3 color = vec3(1.0, 0.5, 0.3);
vec4 newColor = vec4(color.yxz, 1.0);  // newColor = (0.5, 1.0, 0.3, 1.0)

4. 向量運算
GLSL 允許對向量進行各種運算,如加法、減法、乘法、除法、點積、叉積等。

(1) 逐元素加法、減法

vec3 a = vec3(1.0, 2.0, 3.0);
vec3 b = vec3(0.5, 0.2, 0.7);
vec3 sum = a + b;  // (1.5, 2.2, 3.7)
vec3 diff = a - b; // (0.5, 1.8, 2.3)

(2) 逐元素乘法、除法

vec3 c = vec3(2.0, 3.0, 4.0);
vec3 d = c * 2.0;  // (4.0, 6.0, 8.0) - 每個分量都乘以 2
vec3 e = c / 2.0;  // (1.0, 1.5, 2.0) - 每個分量都除以 2

(3) 點積(Dot Product)

float dotProduct = dot(vec3(1.0, 2.0, 3.0), vec3(4.0, 5.0, 6.0));  
// dotProduct = (1*4 + 2*5 + 3*6) = 32

作用:計算兩個向量的相似程度,常用于光照計算。

(4) 叉積(Cross Product)

vec3 crossProduct = cross(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
// crossProduct = (0.0, 0.0, 1.0)

作用:計算垂直于兩個向量的法向量,用于法線計算。

5. 常用數學函數
GLSL 提供了一些常見的數學函數來處理向量。

(1) 向量長度

float len = length(vec3(3.0, 4.0, 0.0));  // len = 5.0

(2) 歸一化(Normalization)

vec3 normVec = normalize(vec3(3.0, 4.0, 0.0));  
// normVec = (0.6, 0.8, 0.0)

作用:將向量變為單位向量,方向不變,但長度為 1。

(3) 線性插值(Lerp)

vec3 lerpVec = mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), 0.5);
// lerpVec = (0.5, 0.0, 0.5)

作用:在兩個向量之間進行插值,mix(a, b, t) 計算 a * (1-t) + b * t。

總結:
在這里插入圖片描述

四、Shader之間的數據傳輸

1. 頂點著色器 (Vertex Shader)

#version 330 core
layout (location = 0) in vec3 aPos; // 頂點位置,attribute 變量out vec4 vertexColor; // 輸出到片段著色器的顏色數據void main()
{gl_Position = vec4(aPos, 1.0); // 將 vec3 轉換為 vec4,賦值給 OpenGL 的 gl_PositionvertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 設置顏色,深紅色
}

輸入 (Input):

  • layout (location = 0) in vec3 aPos;
  • aPos 是從 OpenGL 的 VBO (Vertex Buffer Object) 傳入的頂點位置數據。
  • layout(location = 0) 綁定頂點數據到 attribute 位置 0。

處理 (Processing)

  • gl_Position = vec4(aPos, 1.0);
  • gl_Position 是固定的 OpenGL 變量,用于存儲變換后的頂點坐標,最終傳遞給光柵化階段。
  • aPos 是 vec3,而 gl_Position 需要 vec4,所以用 vec4(aPos, 1.0) 進行轉換。

輸出 (Output)

  • out vec4 vertexColor;
  • vertexColor 是一個 out 變量,它存儲顏色信息,并傳遞給片段著色器。
  • vertexColor = vec4(0.5, 0.0, 0.0, 1.0);比如顏色值 (0.5, 0.0, 0.0, 1.0),代表深紅色 (Dark Red)。
  • 這個顏色會插值傳遞給片段著色器。

2. 片段著色器 (Fragment Shader)

#version 330 core
out vec4 FragColor; // 輸出最終顏色in vec4 vertexColor; // 從頂點著色器傳入的顏色數據void main()
{FragColor = vertexColor; // 直接使用插值后的 vertexColor
}

輸入 (Input)

  • in vec4 vertexColor;
  • 這個變量與頂點著色器中的 out vec4 vertexColor對應,用于接收插值后的顏色數據。

處理 (Processing)
這里沒有額外的計算,直接使用 vertexColor。

輸出 (Output)

  • out vec4 FragColor;
  • FragColor 是最終的片段顏色,輸出到屏幕。

3. 頂點著色器與片段著色器的連接
頂點著色器的 out vec4 vertexColor變量自動插值后傳遞給片段著色器的 in vec4 vertexColor;
插值 (Interpolation) 機制:

  • 頂點著色器的 vertexColor 值會在片元之間進行線性插值。
  • 如果頂點著色器的顏色是 (0.5, 0.0, 0.0, 1.0),則片段著色器接收到的顏色會根據頂點插值。

4. 傳輸流程總結

VBO (aPos) → 頂點著色器 (gl_Position, vertexColor) → 片段著色器 (vertexColor → FragColor) → 顏色緩沖區

五、Shader與C++的數據傳輸uniform

在 OpenGL 中,uniform 變量用于在 C++ 代碼和 Shader 之間傳遞數據。與 in/out 不同,uniform 是全局變量,在著色器的所有 invocations(調用)中都保持相同的值。

1. uniform 在 GLSL (Shader) 中的使用
在 GLSL 著色器中,我們可以聲明 uniform 變量,例如:

#version 330 coreuniform mat4 model; // 4x4 模型矩陣
uniform mat4 view;  // 4x4 視圖矩陣
uniform mat4 projection; // 4x4 投影矩陣in vec3 aPos; // 頂點位置
void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0);
}

解析:

  • uniform mat4 model; → 模型變換矩陣(物體自身的變換)
  • uniform mat4 view; → 視圖變換矩陣(攝像機的變換)
  • uniform mat4 projection; → 投影變換矩陣(投影方式)
  • gl_Position = projection * view * model * vec4(aPos, 1.0);最終計算出的頂點位置,經過 3D 變換后傳入 OpenGL 渲染管線。

2. 在 C++ 中傳遞 uniform 數據
在 OpenGL 的 C++ 代碼中,我們需要:

  • 獲取 uniform 變量的 location
  • 傳遞數據給 uniform

步驟 1:獲取 uniform 變量的位置
在 C++ 中,我們可以使用 glGetUniformLocation 獲取著色器中 uniform 變量的位置:

GLuint shaderProgram = ...; // 已編譯和鏈接的 Shader 程序
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projectionLoc = glGetUniformLocation(shaderProgram, "projection");

例如:glGetUniformLocation(shaderProgram, “model”);獲取 model 變量在 Shader 中的地址,如果 model 變量不存在或者優化掉了,會返回 -1。

步驟 2:傳遞數據給 uniform
(1)傳遞 4x4 矩陣

glm::mat4 model = glm::mat4(1.0f);  // 單位矩陣
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);// 傳遞矩陣數據
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

解析:
glUniformMatrix4fv(location, count, transpose, value)

  • location → glGetUniformLocation() 獲取的 uniform 變量地址
  • count → 傳遞的矩陣個數(一般是 1)
  • transpose → 是否需要轉置(一般為 GL_FALSE,OpenGL 期望列優先存儲)
  • value → 指向矩陣數據的指針(glm::value_ptr(matrix))

(2)傳遞 float 類型的 uniform
Shader 代碼:

uniform float time; // 時間變量

C++ 代碼:

GLint timeLoc = glGetUniformLocation(shaderProgram, "time");
float currentTime = glfwGetTime();
glUniform1f(timeLoc, currentTime);

(3)傳遞 vec3(三維向量)
Shader 代碼:

uniform vec3 lightColor;

C++ 代碼:

GLint lightColorLoc = glGetUniformLocation(shaderProgram, "lightColor");
glUniform3f(lightColorLoc, 1.0f, 1.0f, 1.0f); // 傳遞白色光

或者使用 glm::vec3:

glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);
glUniform3fv(lightColorLoc, 1, glm::value_ptr(lightColor));

(4)傳遞 bool 和 int
Shader 代碼:

uniform bool useTexture;
uniform int lightMode;

C++ 代碼:

GLint useTextureLoc = glGetUniformLocation(shaderProgram, "useTexture");
GLint lightModeLoc = glGetUniformLocation(shaderProgram, "lightMode");// 傳遞 bool(OpenGL 沒有 glUniform1b,所以用 int 代替)
glUniform1i(useTextureLoc, true);// 傳遞 int
glUniform1i(lightModeLoc, 2);

(5)總結
在這里插入圖片描述

六、完整示例

vertex_shader.vert

#version 330 core
layout (location = 0) in vec3 aPos;void main()
{gl_Position = vec4(aPos, 1.0);
}

fragment_shader.frag

#version 330 core
out vec4 FragColor;
uniform vec4 ourColor;void main()
{FragColor = ourColor;
}

代碼如下:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include "glad/glad.h"
#include "GLFW/glfw3.h"GLuint VBO = 0;
GLuint VAO = 0;
GLuint shaderProgram = 0;void framebuffer_size_callback(GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height);
}void processInput(GLFWwindow* window) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {glfwSetWindowShouldClose(window, true);}
}void rend() {glUseProgram(shaderProgram); //需要先調用才能生效float _time = glfwGetTime();float _green = sin(_time) * 0.5f + 0.5f;int _location = glGetUniformLocation(shaderProgram, "ourColor");glUniform4f(_location, 0.0f, _green, 0.0f, 1.0f);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 3);glBindVertexArray(0);glUseProgram(0);
}void initModel() {float vertices[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f, 0.5f, 0.0f};glGenVertexArrays(1, &VAO);glBindVertexArray(VAO);glGenBuffers(1, &VBO); //獲取vbo的indexglBindBuffer(GL_ARRAY_BUFFER, VBO); //綁定vbo的index,給vbo分配顯存空間,傳輸數據//告訴shader數據解析格式glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); //激活錨點glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);
}void initShader(const char* _vertexPath, const char* _fragmPath) {std::string _vertexCode("");std::string _fragCode("");std::ifstream _vShaderFile;std::ifstream _fShaderFile;_vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);_fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);try {_vShaderFile.open(_vertexPath);_fShaderFile.open(_fragmPath);std::stringstream _vShaderStream, _fShaderStream;_vShaderStream << _vShaderFile.rdbuf();_fShaderStream << _fShaderFile.rdbuf();_vertexCode = _vShaderStream.str();_fragCode = _fShaderStream.str();} catch (const std::exception&) {std::string errStr = "read shader fail";std::cout << errStr << std::endl;}const char* _vShaderStr = _vertexCode.c_str();const char* _fShaderStr = _fragCode.c_str();//shader的編譯鏈接unsigned int _vertexID = 0, _fragID = 0;char _inforLog[512] = { 0 };int _successFlag = 0;//編譯_vertexID = glCreateShader(GL_VERTEX_SHADER);glShaderSource(_vertexID, 1, &_vShaderStr, NULL);glCompileShader(_vertexID);glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);if (_successFlag) {glGetShaderInfoLog(_vertexID, 512, NULL, _inforLog);std::string errstr(_inforLog);std::cout << _inforLog << std::endl;}_fragID = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(_fragID, 1, &_fShaderStr, NULL);glCompileShader(_fragID);glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);if (_successFlag) {glGetShaderInfoLog(_vertexID, 512, NULL, _inforLog);std::string errstr(_inforLog);std::cout << _inforLog << std::endl;}//鏈接shaderProgram = glCreateProgram();glAttachShader(shaderProgram, _vertexID);glAttachShader(shaderProgram, _fragID);glLinkProgram(shaderProgram);glGetProgramiv(shaderProgram, GL_LINK_STATUS, &_successFlag);if (!_successFlag) {glGetProgramInfoLog(shaderProgram, 512, NULL, _inforLog);std::string errStr(_inforLog);std::cout << _inforLog << std::endl;}glDeleteShader(_vertexID);glDeleteShader(_fragID);
}int main() {glfwInit();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, "OPenGL Core", NULL, NULL);if (window == NULL) {std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Failed to initialize GLAD" << std::endl;return -1;}glViewport(0, 0, 800, 600);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);initModel();initShader("vertex_shader.vert", "fragment_shader.frag");while (!glfwWindowShouldClose(window)) {processInput(window);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);rend();glfwSwapBuffers(window);glfwPollEvents();}// 刪除 VAO 和 VBOglDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);// 清理glfwTerminate();return 0;
}

輸出結果如下所示:
在這里插入圖片描述

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

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

相關文章

【3DMAX插件】3DMAX建筑大師插件MasterBuilder使用方法

3DMAX建筑大師插件是一款專為3DMAX設計的程序化&#xff08;參數化&#xff09;建筑建模工具&#xff0c;其最大特點是能夠一鍵生成建筑模型&#xff0c;極大地提升了工作效率。該插件配備了多種結構控制選項&#xff0c;涵蓋陽臺、門窗、欄桿、樓頂水塔等附屬建筑元素&#xf…

隱私保護在 Facebook 用戶身份驗證中的應用

在這個數字化的時代&#xff0c;個人隱私保護成為了公眾關注的焦點。社交媒體巨頭 Facebook 作為全球最大的社交平臺之一&#xff0c;擁有數十億用戶&#xff0c;其在用戶身份驗證過程中對隱私保護的重視程度直接影響著用戶的安全感和信任度。本文將探討 Facebook 在用戶身份驗…

Swift Package Manager (SPM) 創建并集成本地庫

在macOS 項目中&#xff0c;使用 Swift Package Manager (SPM) 創建并集成本地庫的完整步驟。 創建一個macos應用程序&#xff0c;選擇 swift、oc、swiftui都可以。 創建好應用之后&#xff0c;開始創建SPM本地庫。 打開終端app&#xff0c;進入項目根目錄&#xff0c;逐次輸…

滲透測試之利用sql拿shell(附完整流程+防御方案)【下】

導讀: 時刻保持謙遜,始終保持學習,探尋事物的本質,不要把事情復雜化 話不多說,書接上回 三、利用日志getshell 利用條件: 擁有網站的寫入權限知道網站的絕對路徑數據庫日志開啟 實際操作: (1)查看數據庫日志是否開啟以及路徑 show variables like %general%; (2…

LeetCode 熱題 100_每日溫度(72_739_中等_C++)(棧)(暴力破解;棧(從左到右);棧(從右到左))

LeetCode 熱題 100_每日溫度&#xff08;72_739&#xff09; 題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;暴力破解法(雙重循環)&#xff09;&#xff1a;思路二&#xff08;棧&#xff1a;從左到右&#xff09;&…

【HarmonyOS Next之旅】DevEco Studio使用指南(二)

目錄 1 -> 工程模板介紹 2 -> 創建一個新的工程 2.1 -> 創建和配置新工程 2.1.1 -> 創建HarmonyOS工程 2.2.2 -> 創建OpenHarmony工程 1 -> 工程模板介紹 DevEco Studio支持多種品類的應用/元服務開發&#xff0c;預置豐富的工程模板&#xff0c;可以根…

unity3d 背景是桌面3d數字人,前面是web的表單

是可以實現的&#xff0c;但涉及多個技術棧的結合&#xff0c;包括 Unity3D、Web 技術&#xff08;HTML、JavaScript&#xff09;、以及可能的 WebGL 或 WebRTC 技術。大致有以下幾種實現方案&#xff1a; 方案 1&#xff1a;Unity 作為獨立應用&#xff08;桌面端&#xff0…

貓耳大型活動提效——組件低代碼化

1. 引言 貓耳前端在開發活動的過程中&#xff0c;經歷過傳統的 pro code 階段&#xff0c;即活動頁面完全由前端開發編碼實現&#xff0c;直到 2020 年接入公司內部的低代碼活動平臺&#xff0c;滿足了大部分日常活動的需求&#xff0c;運營可自主配置活動并上線&#xff0c;釋…

深度學習系列79:Text2sql調研

參考 https://github.com/topics/text-to-sql 這里是一些資源&#xff1a;https://github.com/eosphoros-ai/Awesome-Text2SQL/blob/main/README.zh.md 這里是綜述文章&#xff1a;https://zhuanlan.zhihu.com/p/647249972 1. 數據集 Spider: 一個跨域的復雜text2sql數據集&a…

Linux 系統負載過高的排查思路

技術探討&#xff1a;Linux系統負載過高的排查思路 在Linux服務器運行過程中&#xff0c;如果系統負載過高&#xff0c;可能會導致性能下降和服務不穩定。以下是針對Linux系統負載過高問題的排查思路和解決方法&#xff1a; 1. 查看系統負載&#xff1a; 使用uptime或top命令查…

【互聯網性能指標】QPS/TPS/PV/UV/IP/GMV/DAU/MAU/RPS

&#x1f4d5;我是廖志偉&#xff0c;一名Java開發工程師、《Java項目實戰——深入理解大型互聯網企業通用技術》&#xff08;基礎篇&#xff09;、&#xff08;進階篇&#xff09;、&#xff08;架構篇&#xff09;清華大學出版社簽約作家、Java領域優質創作者、CSDN博客專家、…

linux---天氣爬蟲

代碼概述 這段代碼實現了一個天氣查詢系統&#xff0c;支持實時天氣、未來天氣和歷史天氣查詢。用戶可以通過終端菜單選擇查詢類型&#xff0c;并輸入城市名稱來獲取相應的天氣信息。程序通過 TCP 連接發送 HTTP 請求&#xff0c;并解析返回的 JSON 數據來展示天氣信息。 #in…

Java高頻面試之集合-08

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天來報道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面試官&#xff1a;詳細說說CopyOnWriteArrayList CopyOnWriteArrayList 詳解 CopyOnWriteArrayList 是 Java 并發包&#xff08;java.util…

【微信小程序 onTabItemTap:精準監聽 TabBar 點擊事件】

onTabItemTap 是微信小程序中的一個頁面生命周期函數&#xff0c;用于監聽用戶點擊 TabBar 上的某個項時的事件。以下是如何運用 onTabItemTap 的詳細說明&#xff1a; 使用場景 onTabItemTap 適用于需要在用戶點擊 TabBar 切換頁面時執行特定邏輯的場景。例如&#xff0c;你…

痙攣性斜頸需要做手術嗎?

痙攣性斜頸的治療是一個涉及多種醫學知識的話題&#xff0c;讓我們從多方面分析這個問題&#xff0c;來談談是否需要進行手術。 首先&#xff0c;我們要明確痙攣性斜頸是一種什么疾病。痙攣性斜頸是一種頸部肌肉異常收縮的疾病&#xff0c;可能導致頭部持續或間歇性地向一側旋…

AOT是什么?

https://www.bilibili.com/video/BV1Es4y1q7Bf?spm_id_from333.788.player.switch&vd_source12d5954938d20d50645e227a6a728c76&p87常規的java代碼是即時解釋執行的&#xff0c;只有熱點代碼才會提前編譯成二進制&#xff0c;并且將java代碼放到別的電腦執行時得安裝j…

【JavaWeb學習Day23】

Maven高級 分模塊設計與開發 分模塊設計&#xff1a;將一個大項目分成若干個子模塊&#xff0c;方便項目的維護、擴展&#xff0c;也方便模塊間的相互引用&#xff0c;資源共享。 策略&#xff1a; 1.策略一&#xff1a;按照功能模塊拆分&#xff0c;比如&#xff1a;公共組…

圖像的特征

圖像的特征主要包括以下幾類&#xff1a; 1. 顏色特征&#xff1a; 直方圖&#xff1a;描述圖像中顏色的分布。 顏色矩&#xff1a;通過顏色的均值、方差等統計量表示顏色分布。 主色調&#xff1a;圖像中占主導地位的顏色。 2. 紋理特征&#xff1a; 灰度共生矩陣&#xff0…

?LeetCode周賽 3468. 可行數組的數目——暴力與數學?

?LeetCode周賽 3468. 可行數組的數目——暴力與數學? 示例 1&#xff1a; 輸入&#xff1a;original [1,2,3,4], bounds [[1,2],[2,3],[3,4],[4,5]] 輸出&#xff1a;2 解釋&#xff1a; 可能的數組為&#xff1a; [1, 2, 3, 4] [2, 3, 4, 5] 示例 2&#xff1a; 輸入&…

AF3 squeeze_features函數解讀

AlphaFold3 data_transforms 模塊的 squeeze_features 函數的作用去除 蛋白質特征張量中不必要的單維度&#xff08;singleton dimensions&#xff09;和重復維度&#xff0c;以使其適配 AlphaFold3 預期的輸入格式。 源代碼&#xff1a; def squeeze_features(protein):&qu…