自由學習記錄(63)

編碼全稱:AV1(Alliance for Open Media Video 1)。

算力消耗大:目前(截至 2025 年中)軟件解碼 AV1 的 CPU 開銷非常高,如果沒有專門的硬件解碼單元,播放高清視頻時會很吃 CPU,容易出現卡頓、發熱或掉幀。

  • 在許多視頻/圖像場景里,壓縮率常常表示為“源文件大小 ÷ 壓縮后文件大小”,比率越大代表壓縮得越厲害;但更直觀常用的是“碼率”(bitrate),比如視頻的碼率是 4 Mbps,或者圖片的 JPEG 質量參數 90%。

  • 一般情況下,碼率越高(即單位時間/單位像素所分配的數據越多),可還原的畫面細節就越豐富,相對的畫質也會更好。壓縮率越大則對應碼率越低,畫面細節和銳度就更容易丟失,出現模糊、塊狀或色帶等偽影。

如果不在意流量消耗,就讓播放器調度盡可能高的 AV1 碼率(比如 4K 甚至 8K 的高碼流)來保證最豐富的細節

ShaderForge介紹_嗶哩嗶哩_bilibili

明天了解一下吧

和Graph差不多的,但是built-in

在 Photoshop 中,“線性減淡(Linear Dodge)”與“線性減淡(添加)(Linear Dodge (Add))”實際上是同一個 Blend Mode,Photoshop 官方簡稱:“Linear Dodge (Add)”。它的核心思路就是把兩張圖像做加法,然后對結果做飽和剪裁(clamp)

濾色(Screen)融合模式通常被稱為“反相相乘”(Inverse Multiply)。數學表達式是:

C = 1 - (1 - A) * (1 - B)

更柔和的疊加效果:與 Add/Linear Dodge “一旦相加就飽和到白”相比,Screen 會在低亮度區累加時更明顯,在高亮度區飽和時更平滑。

高光到達白色的過程是漸進、滑順的,不會像簡單的加法

  • Linear Dodge 一旦 A+B > 1,就直接剪裁為 1,區域會瞬間變白。

  • Screen 則是在 A+B 越來越大時,按照 A+B?A*B 的方式漸進逼近 1,在值接近 1 之前都會有細微過渡。

暗部細節保存更好

內發光和外發光,內發光不能超出模型的邊界

用了之后任何功能都需要自己連出來,不連就沒有,右邊一下子就少了很多接口,變灰不讓接上了

unity中的fixed用宏定義了half,換了一種表示方法

在 Unity Shader 中,half 并不直接代表“固定 16 位浮點”,而是“編譯器抽象”→等同于 fixed

  • 在移動 GPU 上,使用 halffixed 可以減少寄存器壓力提高并行度

  • 在 Pixel Shader 中使用 fixed 做顏色計算可以節省資源。

  • GPU 內部的向量化 SIMD 單元更適合處理中低精度數據。

→ 所以手動標記可以讓你顯式告訴編譯器:這個變量不需要高精度,編譯器可以幫你優化。

  • 如果你在高精度 float 上做了大量運算,再賦值給一個低精度 fixed可能造成明顯的精度丟失(顏色值斷層、光照閃爍等)。

  • 所以手動標記數據類型,能讓你顯式暴露這種意圖,并對精度損失行為負責

half用給插值出來的值,fixed用來裝顏色的,,這是優雅的寫法了(pc上統一float32,不影響)

“在手機上 fixed 是小于 half 的”
“顏色需要的精度更少”

為什么 Unity/Shader 寫顏色用 fixed

fixedlowp ≈ 用于顏色值

fixed 最早其實不是 Unity 發明的,而是從舊版 Cg/HLSL 中延續而來的術語,它的名字原義是:

fixed 表示 固定精度范圍 的數值(比如 -2 到 2),比 half 更低精度,但更小更快。

不同的平臺,取模可能要用規定的函數,*也是一樣的,乘要用規定的函數

static

  • 在 Shader 里,static 表示“靜態變量”,也就是該變量只在當前編譯單元(通常是當前 .cginc/.hlsl 文件)中可見,外部無法訪問或修改它。

  • 典型場景

    • 你在同一個 Shader 文件里定義了一段公用函數,而這個函數里面需要一個只讀的臨時常量或緩存,你可以用 static 聲明它,確保不被其他包(pass、include)意外重寫

    • static 并不是“靜態內存”那種概念(不像 C/C++ 全局變量會駐留在固定內存地址)。在 GPU 編譯時,static 只是一個作用域限制:告訴編譯器“外面別來碰我”。

uniform

  • 跨階段共享:一個 uniform(如 CBUFFER 里的某個結構體、或者 samplers/紋理)能同時被頂點著色器(VS)和片段著色器(PS)訪問。

  • 外部驅動:它真正的值來源于 CPU 端代碼(C#、C++)或渲染框架主循環在每次 Draw Call 時引擎更新

在 Shader 里只能讀取它們,不能在 Shader 里寫回賦值

const

編譯期展開:一旦你寫了 const float PI = 3.14159;,編譯器會在預處理階段將所有 PI 的引用替換為 3.14159f,并且不會占用寄存器或 uniform 緩存。

對性能友好:因為它根本不占用寄存器或常量寄存器,所有對它的引用都被直接打入字節碼里,相當于純粹的“文本替換”。

只讀:與 uniform 一樣,在 Shader 代碼中不能給 const 變量重新賦值;但區別在于,它根本不是由外部賦值,而是在編譯時就固定了

GPU 在遇到 if else 時會把兩個分支都執行一遍

因為現代 GPU(無論是桌面級的 NVIDIA/AMD,還是移動端的 ARM Mali/Qualcomm Adreno)內部都是基于SIMD(或 SIMT)并行架構

簡單來說,GPU 會把若干個線程(Thread)組織成一個“線程束”(在 NVIDIA 中叫 Warp、在 AMD 中叫 Wavefront),比如一個 Warp 通常是 32 條線程。然后這 32 條線程在硬件上會同步執行同一條指令

什么是 Mipmap?

  • 假設你有一張原始紋理貼圖(比如 1024×1024 像素)。Mipmap 會在這張貼圖之上再依次生成幾個尺寸越來越小的版本,比如:

    1024×1024 → 512×512 → 256×256 → 128×128 → 64×64 → … → 一直到 1×1

  • 每一級的圖像都是對上一層用雙線性/三線性濾波之類的方法預先縮小或預過濾得到的。所以當你把同一張紋理應用到遠處(或尺寸很小)的物體時,GPU 不必去采樣原始的 1024×1024,而是直接采樣一個更低分辨率的級別(比如 128×128 或 64×64),這樣能夠減少鋸齒、閃爍和紋理閃變現象,同時提高采樣效率。

https://en.wikibooks.org/wiki/Cg_Programming/Unity/Minimal_Shader

https://enjoyphysics.cn/%E6%96%87%E4%BB%B6/soft/Hlsl/GPU-Programming-AndCgLanguage-Primer.pdf

  • 使用 HTTPS 協議,不需要專門配置 SSH Key,即使沒配置 SSH 也能正常克隆/拉取代碼。

  • 在公司網絡或學校網絡里,HTTPS 通常不被屏蔽,更容易成功下載。

GitHub Desktop 是 GitHub 官方推出的一款圖形化桌面客戶端(Windows 和 macOS 均支持),可以讓不熟悉命令行的用戶用可視化界面來管理本地 Git 倉庫。

當你點擊“Open with GitHub Desktop”時,如果本地安裝并打開了 GitHub Desktop 應用,Launcher 會自動在 GitHub Desktop 里創建一個“克隆”任務,讓你選擇存放路徑,然后把倉庫克隆到你指定的本地文件夾。

“Download ZIP” 按鈕

  • 優點

    • 極其簡單,連命令行都不需要,適合只想“拿來直接看代碼/文檔”的場景。

    • 不用擔心本地有沒有安裝 Git;只要會解壓就行。

  • 缺點

    • 你無法繼承該倉庫的版本控制歷史,也不能向遠端推送更新、創建分支,甚至都拿不到原來的 .gitignore.gitattributes 等元信息。

    • 如果后續該項目在 GitHub 上更新了,你需要手動重新下載最新的 ZIP,無法用 git pull 一鍵拉取更新。

  • 如果你:

    1. 主要在 GitHub 上做開源、個人項目;

    2. 希望操作直觀、界面干凈;

    3. 不想花時間學命令行或太多 Git 細節;
      用 GitHub Desktop 就夠了。

  • 如果你:

    1. 想用 GUI 方式做深入的 Git 操作(如多級分支管理、隱式多分支合并、交互式 rebase、子模塊、stash 等);

    2. 項目不一定只在 GitHub,還可能在 GitLab、自建私庫;

    3. 喜歡一次性把常用 Git 操作都放在一個軟件里(不用每次都切命令行);
      用 GitExtensions 會更專業,也更靈活。

shader中的函數性質

GLSL(OpenGL Shading Language)**的頂點著色器(Vertex Shader)代碼,通常用在桌面或者移動端的原生 OpenGL 項目里

  • Unity 里我們平時寫的 Surface Shader、Vertex/Fragment Shader,文件后綴一般是 .shader(里面會混合 ShaderLab 語法和 CGPROGRAM/ENDCG 段落)或者 .cginc.hlsl.compute(Compute Shader),它們的語法看起來像 HLSL/CG。

  • 你這里看到的文件名是 vert.glsl(以及右邊大概率還有 frag.glsl),這明確表明它是 OpenGL/GLSL 的程序。GLSL 在語法上用的關鍵詞是 attributevaryinggl_Position,這在 Unity 的 CG/HLSL 中并不出現。

  • attribute 關鍵字表示頂點輸入屬性(頂點位置、UV、法線等),這是 GLSL 里的寫法;varying 用來把頂點著色器算出的數據(例如頂點法線、坐標插值)傳給片元著色器;gl_Position 則是 OpenGL 里必須寫的輸出變量,決定當前頂點在屏幕上的裁剪空間位置。

這些在 Unity 的 ShaderLab/CG 里都不使用。Unity 要輸出給固定流水線的是 o.pos 或者 SV_POSITION(在 HLSL/DirectX 中)。所以從關鍵字 attributevaryinggl_Position 就能看出這是原生 GLSL,不是 Unity 的。

// 頂點屬性:從 CPU 端傳過來的每個頂點數據
attribute vec3 VaPos;     // 頂點的世界/模型空間位置 (x, y, z)
attribute vec2 VaUV;      // 原始貼圖 UV 坐標 (u, v)
attribute vec3 VaNormal;  // 頂點法線// 統一變量(Uniform),從 CPU 端傳過來,在繪制一批頂點時統一不變
uniform mat4 MVP;   // Model-View-Projection 矩陣,用于把頂點從模型空間 → 世界空間 → 視圖空間 → 裁剪空間
uniform int rows;   // 多重紋理拼接時的行數
uniform int cols;   // 多重紋理拼接時的列數
uniform int index;  // 當前要使用哪張子紋理(編號)// 這是要傳給片元著色器的插值數據(每個頂點算一次,片元階段會自動插值)
varying vec3 VNormal; 
varying vec2 VUV;void main() {// 1. 把原始頂點法線直接傳給片元著色器VNormal = VaNormal;// 2. 計算新的 UV —— 例如把一張大貼圖分割成 rows×cols 幾塊子圖,再根據 index 選其中一塊vec2 temp = vec2(VaUV.x / float(rows), VaUV.y / float(cols));vec2 ranks = vec2(0.0, 0.0);ranks.x = mod(float(index), float(rows));   // 第幾列ranks.y = floor(float(index) / float(cols)); // 第幾行temp.x += ranks.x * 1.0 / float(cols);temp.y += ranks.y * 1.0 / float(rows);VUV = temp;  // 這樣最終傳到片元階段的 VUV 就是“在大貼圖里選取子圖的坐標”// 3. 計算最終 gl_Position(OpenGL 固定變量),告訴 GPU 該頂點在裁剪空間里的坐標gl_Position = MVP * vec4(VaPos, 1.0);
}

(把一張大貼圖拆為 rows×cols 個小紋理,然后根據 index 去采樣)

shader forge

Shader Forge

應用階段的流水線化”指的就是 把渲染管線里原本只在 CPU 上按幀串行做的那塊“應用”工序(場景遍歷、剔除、動畫、排序、命令構建),拆分成多個子階段或分成多條命令緩沖,并且跟后面的 GPU 渲染階段錯開時間、同時執行。這樣才能讓 CPU+GPU 兩端都保持高吞吐、低空閑,從而推高幀率和抗卡頓能力。

Shader Graph 里,UV 坐標并 被系統強制“鉗制”到 [0,1] 區間——它只是一個浮點向量,可以讀到任意值。只要你的采樣模式是 Repeat/Tiled(而不是 Clamp),UV 超出 0–1 時就會按小數部分去“重復”取樣(也就是把紋理無縫平鋪)。

“Light Attenuation”(光照衰減) 節點,它負責根據當前光源類型和距離,給你算出一個 0~1 之間的衰減系數,用來模擬燈光在空間里“隨距離衰減”的效果。

“固定函數”著色器(Fixed-Function Shader)其實并不是一種你要手寫的 shader 腳本,而是指在早期圖形 API(如 OpenGL 2.x、Direct3D 9 以前)中,GPU 內置的一整套“流水線功能”,你只需要用一組固定的命令和參數就能完成頂點變換、光照計算、紋理映射等,而不用自己寫頂點/片元程序。

替換著色器(Replacement Shader)

  • 當你用 Camera.SetReplacementShader(shader, "RenderType") 時,Unity 會在所有渲染物體上查找他們 SubShader 里帶 "RenderType"="..." 的 Pass,并用你提供的替換著色器去渲染這一類物體。

  • 典型例子:后期效果里做“基于不透明物體的深度/法線圖”時,就用 Replacement Shader 只渲染 Opaque 物體。

xyzw四維,w維度判斷是什么類型的光源,如果是方向光,那就xyz是方向向量,如果是點光源,則是具體的世界位置

盡量寫小數的0.0,(一些奇葩機型可能自動轉換出錯)

在 Unity 編輯器里,只要讓鼠標焦點在 Scene 視圖窗口上,按下:

Shift + Space

就可以切換該窗口的最大化/恢復(全屏化)狀態。

一般從光照節點開始分析一個新的shader

scene繞著某個物體旋轉自己當前的視角----Alt+左鍵拖拽

Graphics API/渲染接口也就是底層跟顯卡打交道、驅動硬件加速的標準。

UnityUnrealGodot(結合對應平臺 API:DX12、Vulkan、Metal)

GPU 驅動只實現「API 規范」,并不區分高層語言

  • 顯卡廠商(NVIDIA/AMD/Intel/Apple 等)在驅動里只負責實現底層的 Graphics API(如 DirectX、Vulkan、OpenGL、Metal)的二進制接口——這些接口在本質上是 C/C++ 的 ABI(應用二進制接口)。

  • 驅動并不會同時編譯出一堆 “C++ 版”、“C# 版”、“Java 版” 的驅動庫。它導出的是一套底層的函數和數據結構,供任何能調用 C 接口的語言來用。

各種編程語言通過「綁定」來調用這些 C 接口

  • C/C++:可以 直接 #include <d3d12.h> 或者 #include <vulkan/vulkan.h>,在代碼里無縫調用驅動導出的函數。

  • C#:通常使用 P/Invoke([DllImport])或者像 SharpDX、VulkanSharp 這樣的第三方封裝庫,把底層 DLL 導出的 C 接口“翻譯”成 C# 的類和方法。

  • Java/Python/Go:同樣可以通過 JNI、ctypes、cgo 等方式,把驅動的 C 接口映射到各自語言里。比如 LWJGL(Java),PyOpenGL(Python)都是用這種思路。

游戲引擎和框架通常做更高一層封裝

  • Unity、Unreal、Godot 等引擎,底層已經把對 DirectX/Vulkan/Metal 的調用都寫好 C++ 代碼了,然后再在引擎層給腳本語言(C#, Blueprint, GDScript)提供更易用的接口。

  • 比如在 Unity 里你調用 Graphics.DrawMesh(),它背后跑的是 C++、再到 DirectX/Vulkan 驅動,整個過程對 C# 腳本透明。

  • Unity 引擎核心 是用 C++ 寫的,它直接通過諸如 DirectX、Vulkan、Metal 這些“C 語言風格”的 Graphics API 去驅動 GPU。

  • 你在 Unity 里寫的 C# 腳本(例如 Graphics.DrawMesh() 或者修改材質屬性)并不是直接 P/Invoke 調用這些 Graphics API,而是調用了 Unity C++ 引擎提供的“腳本綁定”(bindings)。這些綁定通常是通過 Unity 自己的宿主進程(UnityPlayer.dll)把 C# 的調用轉成內部的 C++ 函數,一次跨語言切換后,后續都在 C++ → 驅動 API 里完成。

這樣設計的好處有兩個:

  1. 性能: 把所有高頻的、與硬件交互密集的部分都留在 C++ 層;C# ? C++ 的調用只在腳本邏輯層面(每幀僅僅幾百次)發生,而不是每繪制一個三角形、每次設置一個 GPU 狀態就 P/Invoke。

  2. 穩定性與可維護性: 驅動和 Graphics API 的改動都在 C++ 層處理,對 C# 腳本層透明,不用讓每個 C# 項目都去適配不同平臺的 P/Invoke 簽名。

為什么 Unity 不讓 C# 直接 P/Invoke?

  • 減少跨語言調用次數:Unity 把常見的渲染操作都集合成了一套“C++ 原生接口”,C# 只調用這些接口一次進入本地層,之后所有渲染都在 C++ 到驅動的環節。

  • API 統一與封裝:無論你是用 C#、ShaderLab 還是通過 Visual Effect Graph/Shader Graph,最終都走同一個 C++ 實現,不用重復寫綁定。

  • 安全與穩定:讓腳本層不直接接觸底層 DLL,也防止用戶誤用不安全的 P/Invoke 導致崩潰或安全漏洞。

其實在 Unity 里,C# → C++ 的“中轉”調用并不是在每個三角形、每次狀態切換、每個像素著色時都發生的——那樣的開銷肯定會大得不可接受。它真正的調用頻率,大致是:

  1. 每幀幾十到幾百次 的 “腳本層面”渲染命令(DrawMesh、SetGlobalFloat、EnableKeyword……)

  2. Unity 內部把這些命令 累積到一套命令緩沖(Command Buffer)

  3. 在 C++ 層一次性向 GPU 提交整個緩沖區(提交 DrawCall 批次,而不是單個三角形)

你在 C# 里寫

Graphics.DrawMesh(mesh, matrix, material, layer);

每次這句腳本執行時,會做一次 C#→C++ 的入口調用。但它并不立刻跑到底層的 GPU 提交,而是 把參數存到 C++ 的渲染隊列里

  • 當一幀結束、所有繪制邏輯跑完后,Unity C++ 層會把這些“渲染命令列表”批量通過一次或幾次 vkQueueSubmit / ID3D12CommandQueue::ExecuteCommandLists / MTLCommandBuffer commit 提交給顯卡。

也就是說,你在 C# 里可能調用了 50 次 DrawMesh,但這 50 次調用只會在本地層合并成幾次底層 GPU 提交。P/Invoke 的開銷只體現在那 50 次調用上,而不是每個三角片、每個狀態切換都 P/Invoke 一次。

如果你直接在 C# 里一個 DrawCall 對應一個 P/Invoke,再對每個三角形循環,那肯定會慢;但 Unity 已經幫你把這些細節都封裝在 C++ 里了,你在 C# 里看到的只是高級接口。

C# 這邊的“驅動”其實就是 .NET 運行時/CLR(Common Language Runtime) 本身:

  1. .NET 運行時=語言的“驅動”

    • 當你安裝了 .NET Framework、.NET Core/5+ 或 Mono,里面就包含了 CLR、垃圾回收、JIT 編譯器、Base Class Library(BCL) 等,負責把你的 C# IL 轉成機器碼并執行。

    • 這就類似于顯卡廠商編寫的 GPU 驅動:它實現了 Graphics API 規范,把高層調用(DrawCall)翻譯給硬件;而 CLR 則實現了 ECMA-335 標準,把 C#、VB、F# 編譯出來的 IL 翻譯給 CPU。

跨語言調用=互操作(Interop)

  • C# 想調用 C++ 寫的庫,一般通過 P/Invoke[DllImport]) 或 C++/CLI、或 COM,本質上也是 CLR 調用本地 DLL 導出的 C 風格函數。

  • 這套互操作機制由 CLR 提供,調用時也會牽涉“托管 ? 非托管”上下文切換、參數封送(marshalling)等,就像 GPU API 驅動要封裝命令緩沖、驅動開銷一樣。

不需要給每種語言都寫一個“驅動”

  • CLR 是同一套運行時/規范,不管是 C#、VB 還是 F#,都跑在同一個 CLR 上。

  • 你只需要安裝一次對應平臺的 .NET 運行時,就能運行任意 .NET 語言編譯的程序,不用為每個語言再各寫一份“驅動”。

你寫的 Java 源碼(.java)首先被 javac 編譯成 Java 字節碼(.class 文件),這是一種平臺無關的中間格式,不是機器碼,也不是 C++。

Java JVM.NET CLR / Mono
輸入.class(Java 字節碼).dll/.exe(IL 中間語言)
解釋執行解釋器 + JIT解釋器 + JIT
AOT 支持GraalVM Native Image 等.NET Native / Mono AOT
調用本地庫(Interop)JNI(Java Native Interface)P/Invoke / C++/CLI
生態Spring、Android Runtime、GraalVM 等Unity、ASP.NET、Xamarin、Mono

可編程化與可定制化:Scriptable Render Pipeline(SRP)

  • 傳統引擎(如 Unity 5 之前的內置管線,Unreal 4.XX 的默認前向/延遲管線)對渲染流程是“黑盒”式的,只有少量參數可調。

  • 次世代管線(Unity 的 URP/HDRP、Unreal Engine 5 的自定義管線、Godot 4 的 Vulkan 渲染)都采用了可腳本化渲染管線(Scriptable Render Pipeline)理念

  • 次世代管線幾乎都把基于物理的渲染(PBR, Physically Based Rendering)作為核心:

    • 統一材質模型:F0、粗糙度(Roughness)、金屬度(Metallic)、法線、環境光遮蔽等統一標準;

    • 能量守恒:確保光的反射和吸收滿足真實物理規律;

    • 一致性:無論場景光照如何變化,材質表現都保持物理自洽。

高效的光照計算:延遲+Clustered/Tiled/Nanite

  • 延遲渲染(Deferred Rendering):先把幾何信息寫入 G‐Buffer,在屏幕空間做光照,適合大批點光源;

  • Tiled/Clustered Shading:把屏幕或視錐體劃分成小塊或體素,把光源分桶管理,只對相關瓦片/簇做光照,提高效率;

  • GPU 驅動渲染(GPU Driven):把剔除、實例化、Draw Call 構建都放到 GPU Compute Shader 中,減輕 CPU 負擔;

  • 虛擬化幾何(Nanite):Unreal 5 的 Nanite 利用海量細分三角陣列在 GPU 上動態 LOD,實時渲染數十億三角。

新一代光照與全局光照:光線追蹤+Lumen

  • 硬件光線追蹤(RTX/DXR/Metal Ray Tracing):實時計算反射、折射、陰影;

  • 軟件全局光照(Lumen、SVOGI、Probe Grid):混合光柵與光線追蹤做間接照明,既快速又真實;

  • 混合渲染:在不同場景階段(GI 探針、后期 SSDO、實時 RT)中動態切換,兼顧性能與畫質。

渲染剖析與工具鏈

  • 渲染圖(Frame Graph):所有 Render Pass 都以節點化/依賴圖方式管理,可視化調試和自動合并;

  • GPU Profiler & RenderDoc:細粒度分析每個 Pass、每個 DrawCall 的性能,支持管線統計與著色器調試;

  • 資產打包與宏:自動提取 Shader Variant、分批預編譯常用 Shader,減少運行時編譯阻塞。

  • Unity HDRP(High Definition Render Pipeline)

    • 專為高端 PC/主機打造:支持物理光照、延遲+Tiled 光照、體積霧、光線追蹤特效。

    • 用戶可通過 C# 腳本定制 Frame Graph,增刪 Pass;材質系統與 Shader Graph 深度集成。

  • Unity URP(Universal Render Pipeline)

    • 面向移動端和跨平臺應用:輕量級延遲或前向+Tiled 渲染,支持 Shader Instancing、輕量級后期。

  • Unreal Engine 5

    • Nanite + Lumen 雙核技術,自動化虛擬化幾何與全局光照,無需手工烘焙,實時打造電影級場景。

  • Godot 4 Vulkan

    • 集成 Clustered Shading、GI 探針、屏幕空間環境光遮蔽,且引擎代碼開源可定制。

次世代渲染管線 = 可編程化+物理真實感+高效光照+混合光線追蹤 的一整套現代實時圖形架構。
它不僅要在“畫質”上接近電影工業級效果,更要在“性能”上充分利用多核 CPU、GPU Compute 和硬件光線追蹤等能力,為跨平臺的游戲/實時應用提供可擴展、可定制、高性能的渲染解決方案。

“Tiled 光照” 是一種在實時渲染中優化大量點光源/聚光燈的方法,核心思路是把屏幕空間分成一個一個的小“瓦片”(Tile),然后只對每個瓦片中實際影響到的光源做光照計算,而不用讓每個像素都跑遍所有光源。這樣能大幅減少光照計算量。

  • 屏幕拆分成瓦片

    • 比如把 1920×1080 的屏幕劃分為 16×16 像素的小塊,得到 120×68 共 8160 個瓦片。

  • 光源—瓦片關聯

    • 在一個專門的 Compute Shader(或 CPU 線程)里,遍歷場景里所有的點光/聚光,判斷它們的影響范圍(球體或錐體),再把每個光源加入到與之相交的那些瓦片的“光源列表”里。

    • 最終每個瓦片得到一個「僅包含真正會影響該區域的光源索引」的小列表。

  • 瓦片內像素光照

    • 在主渲染 Pass(通常是延遲光照或前向+Clustered)里,每個像素先定位到它屬于哪個瓦片,然后只從該瓦片的光源列表里取出那些光源,逐一做漫反射/鏡面反射計算。

    • 這樣即使場景有幾百、上千個光源,大多數像素最多只要計算幾十盞真正可見/有效的光源。

  • 可擴展:場景光源越多,瓦片大小/分辨率可調;也可以升級到“Clustered”三維分塊,連同深度一起分區。

  • 跨管線:既能用在延遲渲染(Deferred)里,也能在前向渲染(Forward)中做“Forward+”或“Clustered Forward”優化。

傳統做法是在幾何階段就給每個物體算好光照(把燈光的影響一起算進去),只需要一次 Pipeline 就完成。但如果場景有多盞燈,就要對每個物體分別跑幾遍頂點→片元,效率會急劇下降。

eferred 渲染(延遲渲染)怎么做的

延遲渲染把上面兩個階段分開,變成:

  1. 第一次:填 G-Buffer

    • 把場景里的所有像素信息(深度、法線、材質參數)寫到多個渲染目標上(稱為 G-Buffer)。

    • 實際上 GPU 會同時寫出幾張“貼圖”:

      • 一張存 深度

      • 一張存 法線

      • 一張存 漫反射顏色

      • 可能還有張存 金屬度/粗糙度,……

  2. 第二次:屏幕空間光照

    • 屏幕上每個像素已經有了上一步的所有必要數據,接下來只需在「屏幕四邊形」上做一次遍歷:

      • 讀取 G-Buffer 里的深度+法線+材質,

      • 針對每個像素列舉出少量相關的燈(用 Tiled/Clustered)

      • 計算漫反射+高光+陰影……

    • 這樣就不用再跑幾何階段,把所有光照都集中在屏幕上一次性完成。

為什么說“但 G-Buffer 的讀寫會帶來很高的帶寬消耗”

  • 寫入 G-Buffer:在幾何階段,GPU 要向顯存寫入多張大貼圖(深度、法線、顏色……),這就是“多通道寫入”。

  • 讀取 G-Buffer:在光照階段,GPU 又要從顯存里讀回這些貼圖數據(多通道讀取),才能拿到每個像素的深度、法線、材質參數。

  • 顯存帶寬:顯卡內存的讀寫速度相比它計算速度要慢得多,頻繁的大規模讀寫就會成為瓶頸。

假設你的游戲目標是 1080p(1920×1080),在一個典型的 Deferred 渲染中,你可能會用到如下的 G-Buffer:

G-Buffer 通道格式每像素字節數
深度(Depth)32-bit4 B
法線(Normal)RGBA16F8 B
漫反射顏色(Albedo)RGBA84 B
金屬度/粗糙度/AO(MRAO)RGBA84 B
合計20 B/px

  1. 寫入 G-Buffer(Geometry Pass)
    每幀要向顯存寫入:

    1920 × 1080 ≈ 2.07 × 10^6 像素 × 20 B/像素 ≈ 41.5 MB/幀

  2. 讀取 G-Buffer(Lighting Pass)
    同樣地,又要從顯存讀出這 41.5 MB/幀。

  3. 總帶寬消耗

    41.5 MB (寫入) + 41.5 MB (讀取) = 83 MB 每幀

  4. 不同幀率下的帶寬需求

    幀率帶寬需求
    60FPS83 MB × 60 ≈ 4.98 GB/s
    144FPS83 MB × 144 ≈ 11.9 GB/s
    240FPS83 MB × 240 ≈ 19.9 GB/s

對比一下市面上典型顯卡的理論顯存帶寬:

  • GTX 1080:≈320 GB/s

  • RTX 3060:≈360 GB/s

  • Radeon RX 6700 XT:≈384 GB/s

雖然看起來 60FPS 只用了 ~5 GB/s(“才”占了帶寬的 1–2%),但這只是寫讀 G-Buffer的部分開銷,還不包括:

  • 后續所有的材質貼圖采樣、環境貼圖讀寫;

  • Shadow Map 的寫入和讀取;

  • 后期特效(Bloom、TAA、DOF 等)的多輪讀寫;

  • Compute Shader、Stream-Out、Copy 等其它顯存操作。

把這些加起來,顯存帶寬就很快被攥緊了,尤其在更高分辨率(1440p/4K)或更多 G-Buffer 通道(HDR、法線空間貼圖、動量貼圖等)時,帶寬需求幾何倍上升,延遲渲染的“G-Buffer 二次流式讀寫”成為了最大的性能瓶頸之一。

GPU 核心時鐘(Core/Boost Clock)

  • Core Clock(基礎頻率):GPU 在正常負載下的運行頻率。

  • Boost Clock(加速頻率):當溫度、功耗和負載都允許時,GPU 會自動把核心時鐘「超」到更高的值,以提高每秒能執行的著色器指令渲染單元操作的吞吐量。

  • 這兩個時鐘域只管 GPU “算力” 的快慢——它不決定顯存的讀寫速度

顯存時鐘(Memory Clock)和總線寬度(Bus Width)

  • Memory Clock:顯存芯片(GDDR6/GDDR5/HBM 等)自身的工作頻率。通常廠商會給一個有效速率,比如 14 000 MHz(也叫 14 Gbps)。

  • Bus Width:GPU 與顯存之間的數據通道寬度,比如 128 bit、192 bit、256 bit。

  • 它們共同決定了顯存帶寬(Memory Bandwidth),即每秒能搬多少數據給 GPU 核心用。

針對顯存(Memory Clock)的工作頻率

  • 如果顯存標為 14 Gbps(Gigabits per second),可以理解為:

    • 它每秒鐘能“嘀嗒”14 × 10? 次,每次在那根數據線上傳輸 1 bit(比特)信息。

    • GDDR6 中通常有很多并行數據線(一根數據線按 Memory Interface Width,比如 128 bit,總共就是 128 條線同時在跑這個頻率)。

  • 為什么說 14 Gbps 而不是 14 GHz?

    • Gbps 是“千兆比特/秒”,是一種經常用在高速串行接口(把寬總線看作一條條并行線)的標法,和 GHz(10? 周期/秒)在含義上很接近,但針對的是“每條線每秒能跑多少比特”。

    • 14 Gbps ≈ 14 × 10? Hz,也就是說那根線每秒鐘能“嘀嗒”14 billion 次。

Unreal Engine 的 Lumen 和 Nanite 并不是像 HDRP、URP 那樣“腳本化管線”里的一組可插拔節點,而是深度內置在引擎渲染架構里的兩大核心子系統。它們在源碼層面就和 Deferred/Forward 渲染、材質系統、光線追蹤支持等緊密耦合,所以從“普通項目”層面,確實沒法像 Unity 那樣在 C# 或 Shader Graph 里隨意“拆掉”或“重組”它們。

為什么看起來是“定下來了”

  1. 引擎級集成

    • Lumen 和 Nanite 從 5.0+ 開始就是 UE5 的默認渲染子系統,你在項目設置里只能打開或關閉它們,全流程(從 G-Buffer、光線追蹤、體素緩存到最終合成)都在引擎核心代碼里。

  2. 無 SRP 式腳本化接口

    • Unity 的 HDRP/URP 是建立在 Scriptable Render Pipeline 之上,整個渲染流程的每一步(剔除、Shadow Pass、G-Buffer、Lighting Pass、Post)都暴露給 C#,方便你按需插拔。

    • UE5 則是基于 Render GraphPipeline State Object (PSO) 的 C++ 實現,對項目開放的擴展點主要在“添加”而非“替換”已有步驟。

雖然不能“拆掉整個 Lumen/Nanite”,但如果你有足夠 C++ 資源和愿意編譯引擎,也能做一些深度定制:

  1. 修改 Renderer 源碼

    • 在引擎源碼的 Source/Runtime/Renderer/Private 目錄下,Lumen、Nanite 相關的模塊都是 .cpp/.h 文件,你可以 fork UE5 源碼,刪改這些實現,重新編譯你的定制化渲染管線。

  2. 自定義 Render Graph 節點

    • UE5 的渲染流程是基于 Render Graph 構建的。你可以在 FDeferredShadingSceneRenderer::Render() 等入口,插入自定義的 Render Graph Pass,比如在 Lumen GI 前后做一次額外合成。

  3. 自定義 Shading Model

    • 如果你只想改材質層面的光照模型,可以在 Engine/Shaders/Private/MaterialShared.usf 里新增一個 EBlendMode::Custom 的 Shading Model,改寫 GetBaseLightingGetLightingModel 之類函數,仍然保留 Lumen 的 GI。

  4. 插件 + 模塊化源碼

    • 將你的定制放到一個引擎插件里,并在 .uproject.uplugin 里覆蓋 Renderer 模塊,便于在不同項目間復用。

對于“風格化效果”——并不推薦改源碼

  • 很多定制效果(卡通、像素化、怪誕色調、線框渲染、特定后期合成)都可以用:

    1. 自定義材質 + 后處理(Post Process)

    2. Custom Shading Model / Custom Depth + Stencil

    3. 插件級 Render Graph Pass(在現有渲染流程里插入一個額外 Pass)

  • 這些方式都在引擎開放的高層 API(藍圖/C++ 渲染接口)范圍內,不用重新編譯整個引擎,升級版本也更方便。

只有在這些情況下才該動源碼

  • 性能:你確定自己的游戲在目標平臺上已經用盡了所有可調 API,只有改內核才能再提升 10% 幀率。

  • 功能缺失:引擎高層接口確實做不到你想要的底層操作(非常罕見)。

  • 團隊人手:有專門的渲染工程師維護一個私有 UE 源碼分支,并能承擔后續合并和升級的成本。

否則,只為一個風格化 Shader 效果去改動這么龐大的管線,不但風險極高(升級、Bug、兼容性),也大大降低了迭代效率和可維護性。建議優先在現有可擴展接口里做自定義渲染,再視情況決定是不是真的需要“動刀”到引擎級別。

(P2)OBS參數設置_嗶哩嗶哩_bilibili

音頻比特率同理

錄制視頻到底是哪一軌會被寫進去?

這取決于你在“輸出設置”中的“錄制格式和音軌配置”:

  • 如果你在設置中選擇 只啟用音軌1 進行錄制,那么最終導出的視頻就只包含音軌1中的內容。

  • 如果你啟用了 多音軌錄制(比如 mp4 + 軌道1~3),那么導出的視頻將會攜帶多個音軌,你可以在后期剪輯軟件中單獨調出每條軌道。

你錄了一個教學視頻:

  • 軌道1:合成音軌(用于預覽聽感)

  • 軌道2:桌面音頻(PPT 聲音 + 視頻素材)

  • 軌道3:麥克風(你講解的聲音)

后期你發現某一段麥克風雜音太重、或咳嗽了。
如果你只錄了一個合成軌道(桌面 + 麥克風),你沒法分離出來,只能忍著或者剪掉整段。

但有了獨立軌道:

  • 你可以只剪掉麥克風這段,

  • 或者加上降噪插件處理,

  • 桌面聲音完全不受影響。

無論是 .mp4.mkv 還是 .mov,一旦音軌寫入進去,它們都是標準化的數據結構

  • 可以被讀取 ?

  • 可以單獨靜音、剪切、提取、替換 ?

  • 可以重新封裝(不重新編碼) ?

.mkv 是編輯友好的首選格式

(P3)OBS直播(基礎篇)_嗶哩嗶哩_bilibili

轉場特效是場景轉換的時候產生的過渡

點擊開始直播(也就是推流,推流可能更加形象一些),想停止,就停止推流,然后去bzhan上設置停止直播的開關

直播時長,錄制時長

總之,需要直播的時候,就使用obs,拿b站或者其他平臺給的推流碼,填入之后就可以直播自己的電腦屏幕,可以用已經了解的obs的規則去管控自己的直播

視頻錄制如果要錄

obs的文件部分可以轉換文件格式,不用擔心mkv保存了最好的音軌調整性,然后轉別的格式不方便

聽到“糊聲”,不是酷狗變了,而是 OBS 改變了“你整個系統的音頻處理路徑”。
想要聽到原來的音質,需要從驅動層、音頻通道、采樣率上做出限制或隔離。

這樣就改了

禁用不需要的音頻通道

OBS 設置 → 音頻:

  • 麥克風/輔助音頻1 → 只啟用你實際用的

  • 桌面音頻 → 啟用你系統默認的那一個

  • 其他通道 → 統統設為“禁用”

這樣 OBS 就不會偷偷“激活”多個音頻輸入或輸出接口。

OBS 打開后會觸發自動采樣轉換,造成插值失真

改用獨立聲卡或虛擬音頻設備隔離 OBS

如果你有:

  • 外置 USB 聲卡

  • 虛擬音頻路由(如 VB-Cable、VoiceMeeter)

可以設置:

  • 酷狗 → 播放到真實聲卡(耳機)

  • OBS → 捕獲虛擬聲卡 / 第二設備,互不干擾

這樣你聽到的不會是 OBS “截獲后的信號”。

藍牙耳機的“聽”和“說”功能之間存在模式沖突,只有一個能高質量運行。

模式名稱用途特征
🎵 A2DP高質量立體聲傳輸模式聽音樂、看視頻音質好,但不能用麥克風
🎙 HFP/HSP通話模式(耳機+麥克風)打語音、開麥克風可以說話,但音質極差,像電話音

所以結論正確:

🟢 如果你外接一個獨立麥克風(USB 或 3.5mm 插口),
🔁 就可以讓藍牙耳機 只用于播放(A2DP),系統不會切換到 HFP 模式,
🎧 你就能持續享受高質量的音頻輸出。

的藍牙音質問題不是 OBS 特有的

這個問題會在所有場景下觸發,比如:

  • 微信語音 → 藍牙瞬間變糊

  • QQ語音 → 音樂變差

  • Discord 開啟麥克 → YouTube 音質崩壞

它是 藍牙協議層面的問題,不是 OBS 的 bug。

聲卡就是外接麥克風設備嗎?

不是。

  • 有些外接麥克風設備(比如 USB 麥)內置聲卡 → 是二合一設備。

  • 但真正意義上的“外置聲卡”,是可以連接多個音源、調節電平、具備專業音頻處理功能的設備,不一定自帶麥克風。

階段技能模塊目標
① 基礎圖形理解Unity 渲染流程、URP/HDRP管線結構、ShaderGraph基本邏輯能夠看懂節點、了解 SRP 是干什么的
② 真實光照原理漫反射、高光、陰影類型(硬/軟/SSAO)、光照探針、光照貼圖、SH光照能合理解釋光照表現背后的機制
③ 性能分析Profiler、Frame Debugger 使用,DrawCall 分析、Batches、RenderTexture 代價能識別“這個場景為什么卡、卡在哪”
④ ShaderGraph 實戰節點功能實際應用:邊緣光、漸變、遮罩、透明、噪聲、流動、特效寫法能實現效果,能解釋原理(如基于法線/UV/世界空間)
⑤ 渲染管線控制自定義 SRP、RenderFeature、CommandBuffer、Blit 操作、后處理流程對渲染順序、通道、混合有清晰認知,能做高級控制
⑥ 跨模塊優化思維與美術/程序協作,場景組織優化(LOD、烘焙、陰影距離)、動態光源管理能在團隊中定位渲染瓶頸,提出合理建議

xxxxxxxxxxxxxxx

一片 1K×4 芯片,一共可以存儲 1024 × 4 = 4096 bit = 512 byte

8 片 1K×4 存儲芯片,組成一個 4K×8 的存儲器

利用了 地址譯碼器 + 芯片分組 + 數據線并聯 的方法來實現容量與字位的同時擴展。

譯碼器,它根據地址的高位來決定哪一組芯片工作

防止多個芯片同時干活沖突

總線是共享的資源,所有芯片的數據線通常都是接在 同一條數據總線上。同一時刻,只能有一個芯片處于“工作”狀態,其他芯片都要“閉嘴”(高阻狀態)。不加片選控制,多個芯片都接在數據總線上,一起輸出東西?? 數據總線上誰說了算?電壓會亂跳,變成垃圾數據甚至損壞芯片。

元件訪問延遲(大概數量級)說明
寄存器1 個 CPU 時鐘周期CPU 內部,最快
L1 Cache~3-4 個時鐘周期非常快,但容量小
L2 Cache~10 個周期稍慢一些,容量大些
內存(RAM)~100 個周期或更多太慢了,CPU等得焦躁
硬盤(HDD)幾百萬周期簡直是“烏龜”

Memory Hierarchy(存儲層次結構),就是為了在速度、容量、成本之間做平衡。?

CPU 內核內部,電子信號的傳輸幾乎不需要走線;

沒有中介,不需要“找地址”、“走總線”、“排隊”;

是專為執行指令準備的高速電路(SRAM結構);

L1/L2 Cache:也在芯片里,但要做“內容匹配”,L1 Cache 也在 CPU 芯片上,但要根據地址查找數據是否命中

現代 CPU(以及 GPU)有專門的模塊叫:

FPU(Floating Point Unit)浮點運算單元

它在硬件層面執行 IEEE-754 定義的操作。

大多數2D虛擬主播不需要穿戴動捕設備,只使用攝像頭 +面部追蹤軟件即可實現面部表情和頭部動作的捕捉。

但如果追求全身動作/復雜動態,才可能用到動捕服或外部設備。

游戲主程序通常是 C++,Lua 只是邏輯腳本,改 Lua 不影響主程序運行

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

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

相關文章

日本生活:日語語言學校-日語作文-溝通無國界(4)-題目:喜歡讀書

日本生活&#xff1a;日語語言學校-日語作文-溝通無國界&#xff08;4&#xff09;-題目&#xff1a;喜歡讀書 1-前言2-作文原稿3-作文日語和譯本&#xff08;1&#xff09;日文原文&#xff08;2&#xff09;對應中文&#xff08;3&#xff09;對應英文 4-老師評語5-自我感想&…

C++優化程序的Tips

轉自個人博客 1. 避免創建過多中間變量 過多的中間變量不利于代碼的可讀性&#xff0c;還會增加內存的使用&#xff0c;而且可能導致額外的計算開銷。 將用于同一種情況的變量統一管理&#xff0c;可以使用一種通用的變量來代替多個變量。 2. 函數中習慣使用引用傳參而不是返…

C#Blazor應用-跨平臺WEB開發VB.NET

在 C# 中實現 Blazor 應用需要結合 Razor 語法和 C# 代碼&#xff0c;Blazor 允許使用 C# 同時開發前端和后端邏輯。以下是一個完整的 C# Blazor 實現示例&#xff0c;包含項目創建、基礎組件和數據交互等內容&#xff1a; 一、創建 Blazor 項目 使用 Visual Studio 新建項目 …

前端的安全隱患之API惡意調用

永遠不要相信前端傳來的數據&#xff0c;對于資深開發者而言&#xff0c;這幾乎是一種本能&#xff0c;無需過多解釋。然而&#xff0c;初入職場的開發新手可能會感到困惑&#xff1a;為何要對前端傳來的數據持有如此不信任的態度&#xff1f;難道人與人之間連基本的信任都不存…

基于 Spark 實現 COS 海量數據處理

上周在組內分享了一下這個主題&#xff0c; 我覺得還是摘出一部分當文章輸出出來 分享主要包括三個方面&#xff1a; 1. 項目背景 2.Spark 原理 3. Spark 實戰 項目背景 主要是將海量日志進行多維度處理&#xff1b; 項目難點 1、數據量大&#xff08;壓縮包數量 6TB,60 億條數…

Unity3D 屏幕點擊特效

實現點擊屏幕任意位置播放點擊特效。 屏幕點擊特效 需求 現有一個需求&#xff0c;點擊屏幕任意位置&#xff0c;播放一個點擊特效。 美術已經做好了特效&#xff0c;效果如圖&#xff1a; 特效容器 首先&#xff0c;畫布是 Camera 模式&#xff0c;畫布底下有一個 UIClic…

MCU編程

MCU 編程基礎&#xff1a;概念、架構與實踐 一、什么是 MCU 編程&#xff1f; MCU&#xff08;Microcontroller Unit&#xff0c;微控制器&#xff09; 是將 CPU、內存、外設&#xff08;如 GPIO、UART、ADC&#xff09;集成在單一芯片上的小型計算機系統。MCU 編程即針對這些…

Go語言--語法基礎6--基本數據類型--數組類型(1)

Go 語言提供了數組類型的數據結構。 數組是具有相同唯一類型的一組已編號且長度固定的數據項序列&#xff0c;這種類型可以是任意的 原始類型例如整型、字符串或者自定義類型。相對于去聲明number0,number1, ..., and number99 的變量&#xff0c;使用數組形式 numbers[0], …

左神算法之給定一個數組arr,返回其中的數值的差值等于k的子數組有多少個

目錄 1. 題目2. 解釋3. 思路4. 代碼5. 總結 1. 題目 給定一個數組arr&#xff0c;返回其中的數值的差值等于k的子數組有多少個 2. 解釋 略 3. 思路 直接用hashSet進行存儲&#xff0c;查這個值加上k后的值是否在數組中 4. 代碼 public class Problem01_SubvalueEqualk {…

自回歸(AR)與掩碼(MLM)的核心區別:續寫還是補全?

自回歸(AR)與掩碼(MLM)的核心區別:用例子秒懂 一、核心機制對比:像“續寫”還是“完形填空”? 維度自回歸(Autoregressive)掩碼語言模型(Masked LM)核心目標根據已生成的token,預測下一個token(順序生成)預測句子中被“掩碼”的token(補全缺失信息)輸入輸出輸入…

后端開發兩個月實習總結

前言 本人目前在一家小公司后端開發實習差不多兩個月了&#xff0c;現在準備離職了&#xff0c;就這兩個月的實習經歷寫下這篇文章&#xff0c;既是對自己實習的一個總結&#xff0c;也是給正在找實習的小伙伴以及未來即將進入到后端開發這個行業的同學的分享一下經驗。 一、個…

Python基礎(??FAISS?和??Chroma?)

??1. 索引與查詢性能? ??指標????FAISS????Chroma????分析????索引構建速度??72.4秒&#xff08;5551個文本塊&#xff09;91.59秒&#xff08;相同數據集&#xff09;FAISS的底層優化&#xff08;如PQ量化&#xff09;加速索引構建&#xff0c;適合批…

Windows下memcpy_s如何在Linux下使用

Windows下代碼如下 memcpy_s(pLine->ppBuf[i], m_ColorLineByte, pIn nOffset, m_ColorLineByte); 方案 1&#xff1a;使用標準 memcpy 手動檢查&#xff08;最通用&#xff09; // 檢查參數有效性 if (pLine->ppBuf[i] nullptr || pIn nullptr || m_ColorLi…

2025年數學算法與自動化控制國際會議(ICMAAC 2025)

2025年數學算法與自動化控制國際會議&#xff08;ICMAAC 2025&#xff09; 2025 International Conference on Mathematical Algorithms and Automation Control 一、大會信息 會議簡稱&#xff1a;ICMAAC 2025 大會地點&#xff1a;中國長沙 審稿通知&#xff1a;投稿后2-3日…

C語言數組介紹 -- 一維數組和二維數組的創建、初始化、下標、遍歷、存儲,C99 變長數組

目錄 1. 一維數組 1.1 數組的概念 1.2 一維數組的創建 1.3 一維數組的初始化 1.4 數組的類型 1.5 數組下標 1.5.1 數組元素的遍歷 1.5.2 數組的輸入 1.6 一維數組在內存中的存儲 1.7 sizeof 計算數組元素個數 2. 二維數組 2.1 二維數組的創建 2.2 二維數組的初始…

SpringAI + DeepSeek大模型應用開發 - 進階篇(上)

三、SpringAI 2. 哄哄模擬器 2.1 提示詞工程 提示詞工程&#xff08;Prompt Engineering&#xff09;&#xff1a;通過優化提示詞&#xff0c;使大模型生成盡可能理想的內容&#xff0c;這一過程就叫提示詞工程。 &#xff08;1&#xff09;清晰明確的指令 談談人工智能 …

Spring Boot實現異常處理

Spring Boot 提供了多種靈活的方式實現異常處理&#xff0c;以下是核心方案和最佳實踐&#xff1a; 一、基礎異常處理方案 1. ControllerAdvice ExceptionHandler&#xff08;全局處理&#xff09; ControllerAdvice public class GlobalExceptionHandler {// 處理特定異常&…

【目標檢測】IOU的概念與Python實例解析

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

Vue2中如何使用vue-print-nb打印功能

插件官網地址&#xff1a;vue-print-nb - npm 1.安裝 npm install vue-print-nb --save 2.導入打印插件 //main.js import Print from vue-print-nb Vue.use(Print); 3.配置參數 4.頁面使用 <div id"printDiv">打印內容</div><el-button v-print&…

Matplotlib快速入門

目錄 基本使用 解決中文亂碼 一個坐標系繪制多個圖像 多個坐標系繪制 基本使用 什么是Matplotlib 是專門用于開發2D圖表(包括3D圖表)以漸進&#xff0c;交互式方式實現數據可視化 為什么要學習matplotlib 可視化是在整個數據挖掘的關鍵輔助工具&#xff0c;可以清晰的理解…