【OpenGL ES】GLSL基礎語法

1 前言

????????本文將介紹 GLSL 中數據類型、數組、結構體、宏、運算符、向量運算、矩陣運算、函數、流程控制、精度限定符、變量限定符(in、out、inout)、函數參數限定符等內容,另外提供了一個 include 工具,方便多文件管理 glsl 代碼,實現代碼的精簡、復用。

? ? ? ? Unity 中 Shader 介紹詳見 →?【Unity3D】Shader常量、變量、結構體、函數,渲染管線介紹詳見 →?【OpenGL ES】渲染管線。

2 數據類型

2.1 基本數據類型

2.1.1 基本數據類型

類型說明案例
void空類型,即不返回任何值void fun() { }
bool布爾類型 true、falsebool a = true;
int帶符號的整數int a = 0;
float帶符號的浮點數

float a = 1.0;

float b = 2.;

vec2、vec3、vec42 維、3 維、4 維浮點數向量

vec2 a = vec2(1., 2.);

vec2 b = vec2(1.); // ? vec2(1., 1.)

vec3 c = vec3(a, 3.); // ? vec3(1., 2., 3.)

bvec2、bvec3、bvec42 維、3 維、4 維布爾向量

bvec2 a = bvec2(true, false);

bvec2 b = bvec2(true); // ? bvec2(true, true)

bec3 c = bvec3(a, true); // ? bvec3(true, false, true)

ivec2、ivec3、ivec42 維、3 維、4 維整數向量

ivec2 a = ivec2(1, 2);

ivec2 b = ivec2(1); // ? ivec2(1, 1)

ivec3 c = ivec3(a, 3); // ? ivec3(1, 2, 3)

mat2、mat3、mat42x2、3x3、4x4 浮點數矩陣 (列向量)

mat2 a = mat2(1., 2., 3., 4.);

mat2 b = mat2(1.);?// ? mat2(1., 1., 1., 1.)

sampler2D2D 紋理sampler2D sampler;
samplerCube盒紋理samplerCube sampler;

????????說明:mat2、mat3、mat4 中的元素都是按照列向量的順序排列的,即 mat2 m = mat2(m11, m21, m12, m22) 對應的公式如下。

2.1.2 向量分量訪問

????????GLSL 中的向量(vec2、vec3、vec4)可以表示一個空間坐標 (x, y, z, w),也可以表示一個顏色 (r, g, b, a),還可以表示一個紋理坐標 (s, t ,p, q),所以 GLSL 提供了多樣的分量訪問方式。

vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
float x1 = v.x; // 1.0
float x2 = v.r; // 1.0
float x3 = v.s; // 1.0
float x4 = v[0]; // 1.0vec3 xyz = v.xyz; // vec3(1.0, 2.0, 3.0)
vec3 stq = v.stq; // vec3(1.0, 2.0, 3.0)
vec3 rgb = v.rgb; // vec3(1.0, 2.0, 3.0)
vec3 abc = vec3(v[0], v[1], v[2]); // vec3(1.0, 2.0, 3.0)

2.1.3 數據類型轉換

????????GLSL 可以使用構造函數進行顯式類型轉換。

// 0或0.0轉換為false, 非0轉換為true
bool a1 = bool(1.0); // true
bool a2 = bool(0); // false// true轉換為1或1.0, false轉換為0或0.0
int a3 = int(true); // 1
float a4 = float(false); // 0.0int a5 = int(2.0); // 2
float a6 = float(1); // 1.0

2.2 數組

? ? ? ? GLSL 只支持一維數組。

// float 數組
float[3] a = float[] (1.0, 2.0, 3.0);
float b[3] = float[] (1.0, 2.0, 3.0);
float c[3] = float[3] (1.0, 2.0, 3.0);// vec 數組
vec2[2] d = vec2[] (vec2(0.0), vec2(1.0));

2.3 結構體

struct light {vec4 color;vec3 pos;
};
const light lgt = light(vec4(1.0), vec3(0.0));

? ? ? ? 說明:結構體中的字段不可用 const 修飾。

2.4 內置變量

范圍變量說明
頂點著色器的 Output 變量highp vec4 gl_Position;頂點坐標信息
mediump float gl_PointSize;頂點大小 (只在 GL_POINTS 圖元模式下有效)?? ?
片元著色器的 Input 變量mediump vec4 gl_FragCoord;

片元在屏幕空間的坐標,假設屏幕寬高分別為 width、height

x:?片元的x坐標,值域 [0, width - 1]

y:?片元的x坐標,值域 [0, height - 1]

z:?片元的深度坐標,值域 [0, 1]

w:?總是 1,通常用于透視除法

bool gl_FrontFacing;標志當前圖元是否是正面圖元的一部分
片元著色器的 Output 變量mediump vec4 gl_FragColor;設置當前片點的顏色

2.5 宏

? ? ? ? 與 C 語言一樣,GLSL 中也可以通過 #define 定義宏,如下。

#define PI 3.14159265359

? ? ? ? 另外,GLSL 也提供了一些內置宏。

__LINE__ // 當前源碼中的行號
__VERSION__ // 當前glsl版本號, 如: 300
GL_ES // 當前運行環境是否是 OPGL ES, 1 表示是
GL_FRAGMENT_PRECISION_HIGH // 當前系統的片元著色器是否支持高浮點精度, 1表示支持

3 運算符

3.1 基礎運算符

優先級 (越小越高)運算符說明結合性
1()聚組: a * (b + c)N/A
2

[]

()

.

++ --

數組下標

方法參數: fun(arg1, arg2)

屬性訪問

自增 (a++) / 自減 (a--)

L - R
3

++ --

+ -

!

自增 (++a) / 自減 (--a)

正 (+a) 負 (-a) 號

取反 (!a)

R - L
4

* /

%

乘法 / 除法運算

整數求余運算 (浮點數求余用 mod 函數)

L - R
5+ -加法 / 減法運算L - R
7< > <= >=關系運算符L - R
8== !=相等性運算符L - R
12&&邏輯與L - R
13^^邏輯排他或 (用處基本等于 !=)L - R
14||邏輯或L - R
15? :三目運算符L - R
16= += -= *= /=賦值和復合賦值L - R
17,順序分配運算L - R

? ? ? ? 說明:GLSL 中沒有隱式類型轉換,因此任何表達式左右兩側的類型必須一致,以下表達式都是錯誤的。

// 以下代碼運行時會報錯
int a = 2.;
int b = 1. + 2;
float c = 2;
float d = 2. + 1;
bool e = 0;
vec2 f = vec2(1., 2.) * 2;

3.2 向量運算符

// 標量與向量運算
vec2 a = vec2(1., 2.) + 3.; // vec2(4., 5.)
vec2 b = 3. + vec2(1., 2.); // vec2(4., 5.)
vec2 c = vec2(1., 2.) * 3.; // vec2(3., 6.)
vec2 d = 3. * vec2(1., 2.); // vec2(3., 6.)// 向量與向量運算
vec2 e = vec2(1., 2.) + vec2(3., 4.); // vec2(4., 6.)
vec2 f = vec2(1., 2.) * vec2(3., 4.); // vec2(3., 8.)

3.3 矩陣運算符

// 標量與矩陣運算
mat2 a = mat2(1.) + 2.; // mat2(3.)
mat2 b = 2. + mat2(1.); // mat2(3.)
mat2 c = mat2(1.) * 2.; // mat2(2.)
mat2 d = 2. * mat2(1.); // mat2(2.)// 向量與矩陣運算
vec2 e = vec2(1., 2.) * mat2(1., 2., 3., 4.); // vec2(5., 11.)
vec2 f = mat2(1., 2., 3., 4.) * vec2(1., 2.); // vec2(7., 10.)// 矩陣與矩陣運算(矩陣對應元素運算)
mat2 g = mat2(1.) + mat2(2.); // mat2(3.)
mat2 h = matrixCompMult(mat2(1.), mat2(2.)); // mat2(2.)// 矩陣與矩陣運算(矩陣乘法)
mat2 i = mat2(1., 2., 3., 4.) * mat2(5., 6., 7., 8.); // mat2(23., 34., 31., 46.)
mat2 j = mat2(5., 6., 7., 8.) * mat2(1., 2., 3., 4.); // mat2(19., 22., 43., 50.)

4 函數

4.1 自定義函數

????????GLSL 允許在程序的最外部聲明函數,函數不能嵌套、不能遞歸調用,且必須聲明返回值類型(無返回值時聲明為 void)在其他方面 GLSL 函數與 C 語言函數非常類似。

vec4 getPosition() { vec4 pos = vec4(0.,0.,0.,1.);return pos;
}void doubleSize(inout float size) {size = size * 2.0;
}

4.2 內置函數

? ? ? ? 1)數值運算?

sign(x)、abs(x) // 符號、絕對值
min(a, b)、max(a, b) // 最值函數
ceil(x)、floor(x)、round(x) // 取整函數
fract(x) // 取小數部分
mod(x, y) // 取余數
sqrt(x)、pow(x)、inversesqrt(x) // 冪函數, inversesqrt(x)=1/sqrt(x)
exp(x)、exp2(x) // 指數函數(e^x、2^x)
log(x)、log2(x) // 對數函數
degrees(x)、radians(x) // 角度轉換函數
sin(x)、cos(x)、tan(x)、asin(x)、acos(x)、atan(x) // 三角函數
sinh(x)、cosh(x)、tanh(x) // 雙曲線函數
clamp(x, min, max) // 將x約束在min和max之間, 超過邊界就取邊界值
smoothstep(min, max, x) // 平滑比例, 公式: k=saturate((x-min)/(max-min)), y=k*k*(3-2*k)
mix(a, b, f) // 混合, 公式: y=(1-f)*a+f*b
step(a, b) // 如果a>b, 返回0; 如果a<=b, 返回1; 當a、b是向量時, 每個分量獨立判斷, 如: step(fixed2(1,1),fixed(0,2))=(0,1)

? ? ? ? 說明:以上函數輸入的可以是:float、vec2、vec3、vec4,且可以逐分量操作;對于整數求余運算,只能用 %;對于浮點數求余運算,只能用 mod。

????????2)邏輯運算

bvec z = lessThan(x, y) // 逐分量比較x < y, 將結果寫入z的對應位置
bvec z = lessThanEqual(x, y) // 逐分量比較x <= y, 將結果寫入z的對應位置
bvec z = greaterThan(x, y) // 逐分量比較x > y, 將結果寫入z的對應位置
bvec z = greaterThanEqual(x, y) // 逐分量比較x >= y, 將結果寫入z的對應位置
bvec z = equal(x, y) // 逐分量比較x == y, 將結果寫入z的對應位置
bvec z = notEqual(x, y) // 逐分量比較x != y, 將結果寫入z的對應位置
bvec y = not(x) // bool矢量的逐分量取反
bool y = any(x) // 如果x的任意一個分量是true, 則結果為true
bool y = all(x) // 如果x的所有分量是true, 則結果為true

? ? ? ? 3)向量運算

distance(pos1, pos2) // 計算pos1與pos2之間的距離
length(vec) // 計算向量的模長
normalize(vec) // 計算向量的單位向量
dot(v1, v2) // 向量點乘
cross(v1, v2) // 向量叉乘
reflect(i, n) // 根據入射向量和法線向量, 計算反射向量(i和n不需要歸一化)
refract(i, n, ratio); // 根據入射向量、法線向量、折射率比值, 計算折射向量(i和n需要歸一化, ratio為入射介質折射率/折射介質折射率, 或sin(折射角)/sin(入射角))

? ? ? ? 4)矩陣運算

// 矩陣與矩陣運算(矩陣對應元素運算)
mat2 a = mat2(1.) + mat2(2.); // mat2(3.)
mat2 b = matrixCompMult(mat2(1.), mat2(2.)); // mat2(2.)// 矩陣與矩陣運算(矩陣乘法)
mat2 c = mat2(1., 2., 3., 4.) * mat2(5., 6., 7., 8.); // mat2(23., 34., 31., 46.)
mat2 d = mat2(5., 6., 7., 8.) * mat2(1., 2., 3., 4.); // mat2(19., 22., 43., 50.)

? ? ? ? 5)紋理查詢函數

vec4 texture(sampler2D sampler, vec2 coord);
vec4 texture2D(sampler2D sampler, vec2 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec4 coord);
vec4 textureCube(samplerCube sampler, vec3 coord);

5 流程控制

????????GLSL 的流控制與?C 語言非常相似,主要有 if、for、while、continue、break,不同的是 GLSL 中多了 discard。使用 discard 會退出片元著色器,不會執行后面的操作,片元也不會寫入幀緩沖區。

for (int i = 0; i < 10; i++) {sum += a[i];if (sum > 5.0)break;
}while (i < 10) {sum += a[i];if (i % 3 == 1)continue;i++;
}do {sum += a[i];if (sum > 5.0)discard;i++;
} while (i < 10)

6 限定符

6.1 精度限定符

? ? ? ? 片元著色器中,對于浮點數 GLSL 有?highp(高)、mediump(中)、lowp(低) 三種精度。

lowp float color;
varying mediump vec2 Coord;
lowp ivec2 foo(lowp mat3);
highp mat4 m;

????????在片元著色器的第一行加上 precision highp float,表示設定了默認的精度,所有沒有顯式表明精度的變量都會按照默認精度處理。

precision highp float;

????????通過判斷系統環境,來選擇合適的精度。

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif

6.2 變量限定符

限定符說明
none默認的變量限定符,可省略,可讀寫。
const修飾的變量為只讀類型,變量在定義時必須初始化。
attribute只能在頂點著色器中使用,修飾全局只讀變量,一般用于修飾頂點屬性,如:頂點的位置、法線、紋理坐標、顏色等。
uniform修飾全局只讀變量,一般用于修飾程序傳遞給 shader 的變量,如:屏幕寬高比、光源位置等。
varying修飾需要進行光柵化插值的變量,在片元著色器中是只讀的,如:紋理坐標等。
// 頂點著色器
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord0;void main() {gl_Position = vec4(a_position, 1.0);v_texCoord0 = a_texCoord0;
}// 片元著色器
precision highp float;
uniform sampler2D u_texture;
varying vec2 v_texCoord0;void main() {gl_FragColor = texture(u_texture, v_texCoord0);
}

6.3 函數參數限定符

????????函數的參數默認以拷貝的形式傳遞,即值傳遞,我們可以為參數添加限定符實現引用傳遞,GLSL 中提供的參數限定符如下。

限定符說明
in默認的限定符,參數是值傳遞,在函數中可讀寫。
out參數是引用傳遞,在函數中只能寫(write-only)。
inout參數是引用傳遞,在函數中可讀寫(read-write)。

? ? ? ? 除了函數的參數可以用 in、out、inout 修飾,全局變量也可以用這些限定符修飾,如下。

// 頂點著色器
in vec3 a_position;
in vec2 a_texCoord0;
out vec2 v_texCoord0;void main() {gl_Position = vec4(a_position, 1.0);v_texCoord0 = a_texCoord0;
}// 片元著色器
precision highp float;
uniform sampler2D u_texture;
in vec2 v_texCoord0;
out vec4 o_fragColor;void main() {o_fragColor = texture(u_texture, v_texCoord0);
}

7 include

????????GLSL 中沒有提供 #include 功能,如以下代碼會運行報錯。

#include <shaders/utils/constant.glsl>

????????要想實現一個 glsl 文件依賴另一個 glsl 文件,可以使用以下工具加載 glsl 字符串。

????????ShaderUtils.java

import android.content.Context;import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** Shader工具類* @author little fat sheep*/
public class ShaderUtils {// 匹配: #include <xxx> 或 #include “xxx”, 并且不以"//"開頭private static final String INCLUDE_REGEX = "(?m)^(?!//\\s*)#include\\s+(<([^>]+)>|\"([^\"]+)\")";/*** 通過asset加載shader* @param vertexShader 頂點著色器路徑, 如: "shaders/origin_vert.glsl"* @param fragmentShader 片元著色器路徑, 如: "shaders/origin_frag.glsl"*/public static String[] loadShader(Context context, String vertexShader, String fragmentShader) {String vertex = StringUtils.loadString(context, vertexShader);String fragment = StringUtils.loadString(context, fragmentShader);String vertex1 = replaceIncludeFiles(context, vertex);String fragment1 = replaceIncludeFiles(context, fragment);return new String[] { vertex1, fragment1 };}/*** 通過資源id加載shader* @param vertexShader 頂點著色器資源id, 如: R.raw.origin_vertex* @param fragmentShader 片元著色器資源id, 如: R.raw.origin_fragment*/public static String[] loadShader(Context context, int vertexShader, int fragmentShader) {String vertex = StringUtils.loadString(context, vertexShader);String fragment = StringUtils.loadString(context, fragmentShader);String vertex1 = replaceIncludeFiles(context, vertex);String fragment1 = replaceIncludeFiles(context, fragment);return new String[] { vertex1, fragment1 };}/*** 將shader字符串中#include的文件替換為文件內容*/public static String replaceIncludeFiles(Context context, String shaderContent) {Pattern pattern = Pattern.compile(INCLUDE_REGEX);HashSet<String> set = new HashSet<>(); // 用于去掉重復的includereturn replaceIncludeFiles(context, shaderContent, pattern, set);}/*** 將shader字符串中#include的文件替換為文件內容(include的文件中可能也有include, 需要遞歸調用)*/private static String replaceIncludeFiles(Context context, String shaderContent, Pattern pattern, HashSet<String> set) {Matcher matcher = pattern.matcher(shaderContent);StringBuffer sb = new StringBuffer(shaderContent.length());while (matcher.find()) {String angleBrackets = matcher.group(2); // 尖括號內的路徑String quotationMarks = matcher.group(3); // 引號內的路徑String file = angleBrackets != null ? angleBrackets : quotationMarks;if (set.contains(file)) {matcher.appendReplacement(sb, ""); // 刪除重復的include} else {set.add(file);String includeShader = StringUtils.loadString(context, file); // 加載include文件中的字符串String quoteShader = Matcher.quoteReplacement(includeShader); // 替換字符串中的轉義字符String wholeShader = replaceIncludeFiles(context, quoteShader, pattern, set); // 遞歸替換字串中的includematcher.appendReplacement(sb, wholeShader); // 將字符串添加到sb中}}matcher.appendTail(sb);return sb.toString();}
}

? ? ? ? StringUtils.java

import android.content.Context;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;/*** 字符串工具類* @author little fat sheep*/
public class StringUtils {/*** 根據資源路徑讀取字符串* @param assetPath 資源路徑, 如: "shaders/origin_vert.glsl"*/public static String loadString(Context context, String assetPath) {String str = "";try (InputStream inputStream = context.getAssets().open(assetPath)) {str = loadString(inputStream);} catch (IOException e) {e.printStackTrace();}return str;}/*** 根據資源id讀取字符串* @param rawId 資源id, 如: R.raw.origin_vertex*/public static String loadString(Context context, int rawId) {String str = "";try (InputStream inputStream = context.getResources().openRawResource(rawId)) {str = loadString(inputStream);} catch (IOException e) {e.printStackTrace();}return str;}private static String loadString(InputStream inputStream) {StringBuilder sb = new StringBuilder();try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {String line;while ((line = br.readLine()) != null) {sb.append(line).append("\n");}} catch (IOException e) {e.printStackTrace();}return sb.toString();}
}

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

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

相關文章

使用 ECharts 與 Vue 構建數據可視化組件

在前端開發中&#xff0c;數據可視化是非常重要的一部分。ECharts 作為一個功能強大且易于使用的開源數據可視化庫&#xff0c;被廣泛應用于各種圖表展示需求中。而 Vue.js 是當下流行的前端框架之一&#xff0c;它的數據驅動和組件化開發模式讓我們能輕松地將 ECharts 集成到 …

RPA系列-uipath 學習筆記4

使用Uipath 處理hover的問題 備注&#xff1a;使用uipath stversion&#xff1a;2024.10.6,所有學習來源自uipath Academy 首先&#xff0c;打開uipath給我們提供的一個網站 ACME,這個網站呢&#xff0c;需要提前注冊一下的哈。 今天呢&#xff0c;就是記錄一下&#xff0c;怎…

Linux:進程概念

1.馮諾依曼體系結構 結論&#xff1a; --- CPU不和外設直接打交道&#xff0c;和內存直接打交道。 --- 所有的外設&#xff0c;有數據需要收入&#xff0c;只能載入到內存中&#xff1b;內存寫出&#xff0c;也一定是寫道外設中。 --- 為什么程序要運行必須加載到內存&#xf…

活動預告 | Microsoft Azure 在線技術公開課:使用 Azure OpenAI 服務構建生成式應用

課程介紹 通過 Microsoft Learn 免費參加 Microsoft Azure 在線技術公開課&#xff0c;掌握創造新機遇所需的技能&#xff0c;加快對 Microsoft Cloud 技術的了解。參加我們舉辦的“使用 Azure OpenAI 服務構建生成式應用”活動&#xff0c;了解如何使用包括 GPT 在內的強大的…

Linux(Centos 7.6)常見基礎配置

1.網絡配置 網絡配置詳見&#xff1a;VMware安裝Linux(Centos 7.6)后網絡配置 2.yum源配置 yum源配置詳見&#xff1a;Linux(Centos 7.6)yum源配置 3.主機名配置 1.Linux(Centos 7.6)系統安裝后&#xff0c;沒有配置主機名時&#xff0c;root用戶登錄后&#xff0c;是如下…

【PyCharm】如何把本地整個項目同步到服務器?

在PyCharm中&#xff0c;您可以使用部署功能將項目同步到服務器。以下是步驟和示例配置&#xff1a; 打開PyCharm&#xff0c;選擇您的項目。 點擊菜單欄的 “File” -> “Settings” -> “Build, Execution, Deployment”。 在左側菜單中&#xff0c;選擇 “Deployme…

電子電器架構 ---什么是智能電動汽車上的逆變器?

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 所謂雞湯,要么蠱惑你認命,要么慫恿你拼命,但都是回避問題的根源,以現象替代邏輯,以情緒代替思考,把消極接受現實的懦弱,偽裝成樂觀面對不幸的…

Flutter:打包apk,詳細圖文介紹

困擾了一天&#xff0c;終于能正常打包apk安裝了&#xff0c;記錄下打包的流程。建議參考我這篇文章時&#xff0c;同時看下官網的構建說明。 官網構建并發布 Android 應用詳情 1、AS創建Flutter項目 2、cmd執行命令 生成一個sunluyi.jks的文件&#xff0c;可以自行把sunluyi替…

【服務器學習專欄 1.2 -- 帶外管理】

請閱讀 嵌入式學習必備專欄 文章目錄 Overview服務器帶外管理BMC 介紹BMC 特點BMC 工作原理 Overview 從技術的角度&#xff0c;網絡管理可分為帶外管理&#xff08;out-of-band&#xff09;和帶內管理&#xff08;in-band&#xff09;兩種管理模式。 帶內管理&#xff0c;是指…

南京市建鄴區南苑街道一行蒞臨園區考察交流

2024年8月28日&#xff0c;南京市建鄴區南苑街道辦事處副主任董兵、南苑街道發展服務辦公室一級主任科員王洪政、建鄴區國資集團科創公司經理杲暢&#xff0c;在樹莓集團華東區負責人田林和陳強經理的陪同下&#xff0c;蒞臨集團總部-國際數字影像產業園考察交流。 樹莓科技&am…

docker中使用nginx

宿主機和docker中nginx做映射 宿主機中nginx 映射目錄 /root/myDockerData/devnginx 在容器中相關位置分別是&#xff1a; 配置文件位置&#xff1a;/etc/nginx/ 日志位置&#xff1a;/var/log/nginx/ 項目位置&#xff1a;/usr/share/nginx/html 如下配置啟動命令行&#x…

【ES6復習筆記】對象方法擴展(17)

對象方法擴展 在 JavaScript 中&#xff0c;對象是屬性和方法的集合。除了內置的方法&#xff0c;我們還可以通過擴展對象的原型來添加新的方法。本教程將介紹如何使用 Object.is、Object.assign 和 Object.setPrototypeOf 方法來擴展對象。 1. Object.is 判斷兩個值是否完全…

基于JDK 17 編寫的Java常用工具類

文章目錄 DateUtilsEncryptUtilsFunIdCardCalibrationUtilResultResultCodeValidateNameUtilValidatePhoneUtil 廢話少說看源碼 DateUtils package com.huihang.core.utils;import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import j…

Casino Royale靶場wp

0x00 下載安裝 https://download.vulnhub.com/casinoroyale/CasinoRoyale.ova 導入vmware啟動 0x01 主機信息收集 0x02目錄掃描 index.php 獲取到一個域名 修改本地hosts 添加一行 路徑&#xff1a;C:\Windows\System32\drivers\etc 192.168.2.20 casino-royale.local 點擊…

智能家居體驗大變革 博聯 AI 方案讓智能不再繁瑣

1. 全球AI技術發展背景及智能家居市場趨勢 人工智能&#xff08;AI&#xff09;技術的飛速發展正在推動全球各行業的數字化轉型。國際電信聯盟與德勤聯合發布《人工智能向善影響》報告指出&#xff0c;全球94%的商界領袖認為&#xff0c;人工智能技術對于其企業在未來5年內的發…

鴻蒙開發(27)案例今日任務

案例為純前端實現&#xff0c;總結案例。 主頁面代碼 import { TaskStatisties } from ../view/TaskStatisties import { TaskItem } from ../view/TaskItem import CreateTaskModel, {TaskModel} from ../viewmodel/TaskModel import { router } from kit.ArkUI// xxx.ets En…

WPF編程excel表格操作

WPF編程excel表格操作 摘要NPOI安裝封裝代碼測試代碼 摘要 Excel操作幾種方式 使用開源庫NPOI(常用&#xff0c;操作豐富)使用Microsoft.Office.Interop.Excel COM組件(兼容性問題)使用OpenXml(效率高)使用OleDb(過時) NPOI安裝 封裝代碼 using System; using System.IO; u…

tcp_rcv_synsent_state_process函數

tcp_rcv_synsent_state_process 是 Linux Kernel 中用于處理 TCP 連接在 SYN-SENT 狀態下接收到報文的函數。這個函數在 TCP 三次握手階段起到了至關重要的作用,處理了在客戶端發送 SYN 請求之后收到服務器響應報文的各種情況。 以下是這個函數的解讀和剖析: int tcp_rcv_sy…

音視頻采集推流時間戳記錄方案

音視頻同步更多文章 深入理解音視頻pts&#xff0c;dts&#xff0c;time_base以及時間數學公式_視頻pts計算-CSDN博客 ffplay音視頻同步分析_ffplay 音視頻同步-CSDN博客 音視頻采集打時間戳設計 實時音視頻數據的采集和處理場景。具體來說: 采集階段: 在音視頻數據采集過…

Spark Runtime Filter

Runtime Filter 參考鏈接&#xff1a; https://docs.google.com/document/d/16IEuyLeQlubQkH8YuVuXWKo2-grVIoDJqQpHZrE7q04/edit?tabt.0https://www.modb.pro/db/557718https://issues.apache.org/jira/browse/SPARK-32268https://github.com/apache/spark/pull/35789https…