Unity中實現ShaderToy卡通火(一)

文章目錄

  • 前言
  • 一、準備好我們的后處理基礎腳本
    • 1、C#:
    • 2、Shader:
  • 二、開始逐語句對ShaderToy進行轉化
    • 1、首先,找到我們的主函數 mainImage
    • 2、其余的方法全部都是在 mainImage 函數中調用的方法
    • 3、替換后的代碼(已經沒報錯了,都是效果不對)
  • 三、我們來調試一下Shader,看看問題出在了哪?
    • 1、return float4(col, 1.0);
    • 2、black or fire
    • 3、getDepth函數
  • 四、修改 STEPS 的數值出錯問題
    • 法1:在屬性面板增加 STEPS 參數,賦予初始值4
    • 法2:使用#define 預定義一個常量
  • 五、最終代碼


前言

在上一篇文章中,我們講解了基礎的ShaderToy怎么轉化為Unity中的Shader。我們在這篇文章中,復刻一個復雜的ShaderToy效果卡通火。

  • Unity中的ShaderToy

  • 卡通火

請添加圖片描述


一、準備好我們的后處理基礎腳本

1、C#:

using UnityEngine;//后處理腳本
[ExecuteInEditMode]
public class P2_9 : MonoBehaviour
{public Shader PostProcessingShader;private Material mat;public Material Mat{get{if (PostProcessingShader == null){Debug.LogError("沒有賦予Shader");return null;}if (!PostProcessingShader.isSupported){Debug.LogError("當前Shader不支持");return null;}//如果材質沒有創建,則根據Shader創建材質,并給成員變量賦值存儲if (mat == null){Material _newMaterial = new Material(PostProcessingShader);_newMaterial.hideFlags = HideFlags.HideAndDontSave;mat = _newMaterial;return _newMaterial;}return mat;}}private void OnRenderImage(RenderTexture source, RenderTexture destination){Graphics.Blit(source,destination,Mat);}
}

2、Shader:

Shader "MyShader/P2_9"
{SubShader{// No culling or depthCull Off ZWrite Off ZTest AlwaysPass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#include "UnityCG.cginc"fixed4 frag (v2f_img i) : SV_Target{return 1;}ENDCG}}
}

二、開始逐語句對ShaderToy進行轉化

1、首先,找到我們的主函數 mainImage

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 uv = fragCoord.xy / iResolution.xy;uv.x *= 4.0;float t = iTime * 3.0;    vec3 col = vec3(0);float noise = getNoise(uv, t);//shape cutoff to get higher further up the screenCUTOFF = uv.y;    //and at horiz edgesCUTOFF += pow(abs(uv.x*0.5 - 1.),1.0);   //debugview cutoff field//fragColor = vec4(vec3(CUTOFF),1.0);   if (noise < CUTOFF){       //blackcol = vec3(0.);}else{//firefloat d = pow(getDepth(noise),0.7);        vec3 hsv = vec3(d *0.17,0.8 - d/4., d + 0.8);col = hsv2rgb(hsv);}fragColor = vec4(col,1.0);   
}

2、其余的方法全部都是在 mainImage 函數中調用的方法

因此,我們可以直接使用把這些方法復制到 我們片元著色器的上方,把參數類型轉化為CG中的參數類型,即可直接使用

  • vec2 :float2
  • vec3 :float3
  • vec4 :float4
  • float4(0,0) : 0
  • fract(x) : frac(x) (取 x 的小數部分)
  • mix(a,b,x) :lerp(a,b,x) (線性插值)

選中需要轉化的變量名,使用快捷鍵 Ctrl + F,進行全部替換

在這里插入圖片描述

3、替換后的代碼(已經沒報錯了,都是效果不對)

//https://www.shadertoy.com/view/lsscWrShader "MyShader/P2_9"
{SubShader{// No culling or depthCull Off ZWrite Off ZTest AlwaysPass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#include "UnityCG.cginc"float3 mod289(float3 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}float4 mod289(float4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}float4 permute(float4 x){return mod289(((x * 34.0) + 1.0) * x);}float4 taylorInvSqrt(float4 r){return 1.79284291400159 - 0.85373472095314 * r;}float snoise(float3 v){const float2 C = float2(1.0 / 6.0, 1.0 / 3.0);const float4 D = float4(0.0, 0.5, 1.0, 2.0);// First cornerfloat3 i = floor(v + dot(v, C.yyy));float3 x0 = v - i + dot(i, C.xxx);// Other cornersfloat3 g = step(x0.yzx, x0.xyz);float3 l = 1.0 - g;float3 i1 = min(g.xyz, l.zxy);float3 i2 = max(g.xyz, l.zxy);//   x0 = x0 - 0.0 + 0.0 * C.xxx;//   x1 = x0 - i1  + 1.0 * C.xxx;//   x2 = x0 - i2  + 2.0 * C.xxx;//   x3 = x0 - 1.0 + 3.0 * C.xxx;float3 x1 = x0 - i1 + C.xxx;float3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.yfloat3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y// Permutationsi = mod289(i);float4 p = permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0))+ i.y + float4(0.0, i1.y, i2.y, 1.0))+ i.x + float4(0.0, i1.x, i2.x, 1.0));// Gradients: 7x7 points over a square, mapped onto an octahedron.// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)float n_ = 0.142857142857; // 1.0/7.0float3 ns = n_ * D.wyz - D.xzx;float4 j = p - 49.0 * floor(p * ns.z * ns.z); //  mod(p,7*7)float4 x_ = floor(j * ns.z);float4 y_ = floor(j - 7.0 * x_); // mod(j,N)float4 x = x_ * ns.x + ns.yyyy;float4 y = y_ * ns.x + ns.yyyy;float4 h = 1.0 - abs(x) - abs(y);float4 b0 = float4(x.xy, y.xy);float4 b1 = float4(x.zw, y.zw);//float4 s0 = float4(lessThan(b0,0.0))*2.0 - 1.0;//float4 s1 = float4(lessThan(b1,0.0))*2.0 - 1.0;float4 s0 = floor(b0) * 2.0 + 1.0;float4 s1 = floor(b1) * 2.0 + 1.0;float4 sh = -step(h, 0);float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;float3 p0 = float3(a0.xy, h.x);float3 p1 = float3(a0.zw, h.y);float3 p2 = float3(a1.xy, h.z);float3 p3 = float3(a1.zw, h.w);//Normalise gradientsfloat4 norm = taylorInvSqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));p0 *= norm.x;p1 *= norm.y;p2 *= norm.z;p3 *= norm.w;// Mix final noise valuefloat4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);m = m * m;return 42.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1),dot(p2, x2), dot(p3, x3)));}//END ASHIMA /const float STEPS = 4.;float CUTOFF = 0.15; //depth less than this, show blackfloat3 hsv2rgb(float3 c){float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);}float getNoise(float2 uv, float t){//given a uv coord and time - return a noise val in range 0 - 1//using ashima noise//add time to y position to make noise field move upwardsfloat TRAVEL_SPEED = 1.5;//octave 1float SCALE = 2.0;float noise = snoise(float3(uv.x * SCALE, uv.y * SCALE - t * TRAVEL_SPEED, 0));//octave 2 - more detailSCALE = 6.0;noise += snoise(float3(uv.x * SCALE + t, uv.y * SCALE, 0)) * 0.2;//move noise into 0 - 1 range    noise = (noise / 2. + 0.5);return noise;}float getDepth(float n){//given a 0-1 value return a depth,//remap remaining non-cutoff region to 0 - 1float d = (n - CUTOFF) / (1. - CUTOFF);//step itd = floor(d * STEPS) / STEPS;return d;}fixed4 frag(v2f_img i) : SV_Target{float2 uv = i.uv;uv.x *= 4.0;float t = _Time.y * 3.0;float3 col = 0;float noise = getNoise(uv, t);//shape cutoff to get higher further up the screenCUTOFF = uv.y;//and at horiz edgesCUTOFF += pow(abs(uv.x * 0.5 - 1.), 1.0);//debugview cutoff field//fragColor = float4(float3(CUTOFF),1.0);   if (noise < CUTOFF){//blackcol = 0;}else{//firefloat d = pow(getDepth(noise), 0.7);float3 hsv = float3(d * 0.17, 0.8 - d / 4., d + 0.8);col = hsv2rgb(hsv);}return float4(col, 1.0);}ENDCG}}
}

在這里插入圖片描述


三、我們來調試一下Shader,看看問題出在了哪?

我們在調試Shader時,因為主要效果是在 片元著色器 中實現的。
所以,我們調試Shader一般 從 輸出 倒著 來調試

1、return float4(col, 1.0);

在 ShaderToy中,已經規定了透明值為 1 。所以,最終效果為黑色,不是透明值導致的。我們應該順著 col 去找bug。

2、black or fire

if (noise < CUTOFF)
{//blackcol = 0;
}
else
{//firefloat d = pow(getDepth(noise), 0.7);float3 hsv = float3(d * 0.17, 0.8 - d / 4., d + 0.8);col = hsv2rgb(hsv);
}
  • 我們修改black中的col。發現黑色的背景變白了,說明這不是使col最終全為 0 的原因
    col = 1;
    請添加圖片描述

  • 我們修改 fire 中的 col 分別為 hsv 、d 和 getDepth(noise); (沒有變化,說明這也不是原因所在)
    col = hsv; / col = d; / col = getDepth(noise);
    在這里插入圖片描述

  • 我們修改 fire 中的 col 為 noise 后,我們的火出現了變化(可以鎖定getDepth函數出現了問題)
    col = noise;
    請添加圖片描述

3、getDepth函數

float getDepth(float n)
{//given a 0-1 value return a depth,//remap remaining non-cutoff region to 0 - 1float d = (n - CUTOFF) / (1. - CUTOFF);//step itd = floor(d * STEPS) / STEPS;return d;
}
  • 在歸一化(remap remaining non-cutoff region to 0 - 1)之后,返回一個d。(我們可以看出火有了大致的顏色,說明問題處在了d = floor(d * STEPS) / STEPS;這句話)
    請添加圖片描述
  • 而 d 我們已經返回過了。所以,最終問題在 STEPS 參數上
    在這里插入圖片描述

四、修改 STEPS 的數值出錯問題

在Unity的Shader中,如果我們的常量直接定義在Pass中
不管初始值為多少,Unity都會默認為0。
如果我們想這樣使用參數,必須在屬性塊定義一個變量給定初始值

法1:在屬性面板增加 STEPS 參數,賦予初始值4

  • 在這樣定義后,修改對應的變量名后即可使用
	Properties{_Steps("STEPS",float) = 4}

法2:使用#define 預定義一個常量

#define STEPS 4

  • 可以看出,我們效果正確了
    請添加圖片描述

五、最終代碼

//https://www.shadertoy.com/view/lsscWrShader "MyShader/P2_9"
{Properties{_Steps("STEPS",float) = 4_CUTOFF("CUTOFF",float) = 0.15}SubShader{// No culling or depthCull Off ZWrite Off ZTest AlwaysPass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#include "UnityCG.cginc"float3 mod289(float3 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}float4 mod289(float4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}float4 permute(float4 x){return mod289(((x * 34.0) + 1.0) * x);}float4 taylorInvSqrt(float4 r){return 1.79284291400159 - 0.85373472095314 * r;}float snoise(float3 v){const float2 C = float2(1.0 / 6.0, 1.0 / 3.0);const float4 D = float4(0.0, 0.5, 1.0, 2.0);// First cornerfloat3 i = floor(v + dot(v, C.yyy));float3 x0 = v - i + dot(i, C.xxx);// Other cornersfloat3 g = step(x0.yzx, x0.xyz);float3 l = 1.0 - g;float3 i1 = min(g.xyz, l.zxy);float3 i2 = max(g.xyz, l.zxy);//   x0 = x0 - 0.0 + 0.0 * C.xxx;//   x1 = x0 - i1  + 1.0 * C.xxx;//   x2 = x0 - i2  + 2.0 * C.xxx;//   x3 = x0 - 1.0 + 3.0 * C.xxx;float3 x1 = x0 - i1 + C.xxx;float3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.yfloat3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y// Permutationsi = mod289(i);float4 p = permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0))+ i.y + float4(0.0, i1.y, i2.y, 1.0))+ i.x + float4(0.0, i1.x, i2.x, 1.0));// Gradients: 7x7 points over a square, mapped onto an octahedron.// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)float n_ = 0.142857142857; // 1.0/7.0float3 ns = n_ * D.wyz - D.xzx;float4 j = p - 49.0 * floor(p * ns.z * ns.z); //  mod(p,7*7)float4 x_ = floor(j * ns.z);float4 y_ = floor(j - 7.0 * x_); // mod(j,N)float4 x = x_ * ns.x + ns.yyyy;float4 y = y_ * ns.x + ns.yyyy;float4 h = 1.0 - abs(x) - abs(y);float4 b0 = float4(x.xy, y.xy);float4 b1 = float4(x.zw, y.zw);//float4 s0 = float4(lessThan(b0,0.0))*2.0 - 1.0;//float4 s1 = float4(lessThan(b1,0.0))*2.0 - 1.0;float4 s0 = floor(b0) * 2.0 + 1.0;float4 s1 = floor(b1) * 2.0 + 1.0;float4 sh = -step(h, 0);float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;float3 p0 = float3(a0.xy, h.x);float3 p1 = float3(a0.zw, h.y);float3 p2 = float3(a1.xy, h.z);float3 p3 = float3(a1.zw, h.w);//Normalise gradientsfloat4 norm = taylorInvSqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));p0 *= norm.x;p1 *= norm.y;p2 *= norm.z;p3 *= norm.w;// Mix final noise valuefloat4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);m = m * m;return 42.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1),dot(p2, x2), dot(p3, x3)));}//END ASHIMA /float _Steps;float _CUTOFF; //depth less than this, show blackfloat3 hsv2rgb(float3 c){float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);}float getNoise(float2 uv, float t){//given a uv coord and time - return a noise val in range 0 - 1//using ashima noise//add time to y position to make noise field move upwardsfloat TRAVEL_SPEED = 1.5;//octave 1float SCALE = 2.0;float noise = snoise(float3(uv.x * SCALE, uv.y * SCALE - t * TRAVEL_SPEED, 0));//octave 2 - more detailSCALE = 6.0;noise += snoise(float3(uv.x * SCALE + t, uv.y * SCALE, 0)) * 0.2;//move noise into 0 - 1 range    noise = (noise / 2. + 0.5);return noise;}float getDepth(float n){//given a 0-1 value return a depth,//remap remaining non-_CUTOFF region to 0 - 1float d = (n - _CUTOFF) / (1. - _CUTOFF);//step itd = floor(d * _Steps) / _Steps;return d;}fixed4 frag(v2f_img i) : SV_Target{float2 uv = i.uv;uv.x *= 4.0;float t = _Time.y * 3.0;float3 col = 0;float noise = getNoise(uv, t);//shape _CUTOFF to get higher further up the screen_CUTOFF = uv.y;//and at horiz edges_CUTOFF += pow(abs(uv.x * 0.5 - 1.), 1.0);//debugview _CUTOFF field//fragColor = float4(float3(_CUTOFF),1.0);   if (noise < _CUTOFF){//blackcol = 0;}else{//firefloat d = pow(getDepth(noise), 0.7);float3 hsv = float3(d * 0.17, 0.8 - d / 4., d + 0.8);col = hsv2rgb(hsv);}return float4(col, 1.0);}ENDCG}}
}

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

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

相關文章

智能優化算法應用:基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用&#xff1a;基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用&#xff1a;基于正余弦算法3D無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.正余弦算法4.實驗參數設定5.算法結果6.參考文…

基于單個參數線性回歸的機器學習代碼

本文為學習吳恩達版本機器學習教程的代碼整理&#xff0c;使用的數據集為https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt 將數據集和py代碼放到同一目錄中&#xff0c;使…

2023最新八股文前端面試題

第一章 Css 1.說一下CSS的盒模型。 在HTML頁面中的所有元素都可以看成是一個盒子盒子的組成:內容content、內邊距padding、邊框border、外邊距margin盒模型的類型: 標準盒模型 margin border padding content IE盒模型 margin content(border padding) 控制盒模型的模式…

淘寶api接口測試方式(item_get-獲得淘寶商品詳情)

注冊淘寶開放平臺賬號&#xff1a;首先&#xff0c;你需要在淘寶開放平臺上注冊一個賬號&#xff0c;并創建一個應用。獲取App Key和Secret Key&#xff1a;在創建應用后&#xff0c;你會獲得App Key和Secret Key&#xff0c;這些憑證將用于調用API。了解淘寶商品詳情接口&…

【開源】基于Vue+SpringBoot的免稅店商城管理系統

文末獲取源碼&#xff0c;項目編號&#xff1a; S 069 。 \color{red}{文末獲取源碼&#xff0c;項目編號&#xff1a;S069。} 文末獲取源碼&#xff0c;項目編號&#xff1a;S069。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、系統設計2.1 功能模塊設計2.2 研究方法 三、系統…

什么是圖片懶加載(image lazy loading)?它的作用是什么?

聚沙成塔每天進步一點點 ? 專欄簡介 前端入門之旅&#xff1a;探索Web開發的奇妙世界 歡迎來到前端入門之旅&#xff01;感興趣的可以訂閱本專欄哦&#xff01;這個專欄是為那些對Web開發感興趣、剛剛踏入前端領域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發…

如何使用vue開發vscode插件

以下是一個簡單的示例&#xff0c;演示如何使用Vue和VSCode的Webview API來開發一個簡單的VSCode插件&#xff1a; 創建一個VSCode插件項目 首先&#xff0c;你需要創建一個VSCode插件項目。你可以使用VSCode的插件生成器來快速創建一個基本的項目結構。從VSCode的命令面板中運…

【Flutter】graphic圖表實現tooltip一段時間后自動隱藏

概述 graphic圖表中提供了自定義tooltip的事件&#xff0c;可通過selections中on和clear配置手勢選項和可識別設備&#xff0c;默認情況下tooltip需要雙擊隱藏&#xff0c;但這并不符合我們的需求。通過調研發現&#xff0c;若想實現tooltip隔幾秒后隱藏&#xff0c;可通過Str…

3DMax物理畫筆物體填充放置繪制畫筆插件安裝使用方法

3DMax物理畫筆物體填充放置繪制畫筆插件&#xff0c;允許您使用筆刷以非常自然的方式用物品快速填充場景&#xff0c;并使用剛體模擬自動放置它們。 無論你是從事建筑、游戲電影還是商業。。。等等&#xff0c;你經常需要用一些物品為你的場景添加細節。手工放置它們是乏味的&…

Threejs發光閃爍提示特效

一、導語 發光閃爍特效應該在我們的項目中是經常需要去封裝的一個特效吧&#xff0c;一般用于點擊選擇&#xff0c;選中物體&#xff0c;或者一些特效加持于中心物體&#xff0c;物體碰撞檢測后的發光特效等等 二、分析 我們可以合理的使用后處理特效&#xff0c;上步驟&am…

hive查看數據庫出現org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

FAILED: HiveException java,lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient 在啟動hive后&#xff0c;使用show databses查看數據庫時發現&#xff0c;出現了這個錯誤 情況一&#xff1a; 根據搜索查找以及…

Docker一 | Docker的基本使用

目錄 Docker的基本使用 常用命令 啟動Docker 查看Docker的運行狀態 重啟Docker 停止Docker服務 查看命令相關信息 鏡像命令 列出本地主機上的鏡像 搜索某個鏡像的名稱 拉取指定的鏡像到本地 查看鏡像/容器/數據卷所占的空間 刪除某個鏡像 容器命令 啟動容器 列出…

數字電路基礎知識系列(六)之LC濾波器的基礎知識

LC濾波器&#xff0c;是指將電感(L)與電容器 ©進行組合設計構成的濾波電路&#xff0c;可去除或通過特定頻率的無源器件。電容器具有隔直流通交流&#xff0c;且交流頻率越高越容易通過的特性。而電感則具有隔交流通直流&#xff0c;且交流頻率越高越不易通過的特性。因此…

linux如何使用Xshell遠程連接

簡介&#xff1a;本文的一切條件基于redhat的linux操作系統。 目錄 1、創建虛擬機&#xff1a; 2、使用命令查看網段信息 拓展1&#xff1a;&#xff08;若網卡上沒有網段信息&#xff0c;可以使用任意兩種方法&#xff09;&#xff1a; 準備工作&#xff1a; 1、點擊左…

git入門教程+常用命令

Git入門教程 本文章主要參照視頻教程&#xff1a;https://www.bilibili.com/video/BV1FE411P7B3/?spm_id_from333.337.search-card.all.click&vd_source06caf161b187fb3f4c039bc15e238fea 為什么要使用GIT 版本控制是項目、文檔迭代的必然要求&#xff0c;所以需要使用…

Springboot自定義start首發預告

Springboot自定義start首發預告 基于Springboot的自定義start , 減少項目建設重復工作, 如 依賴 , 出入參包裝 , 日志打印 , mybatis基本配置等等等. 優點 模塊化 可插拔 易于維護和升級 定制化 社區支持(后期支持) 發布時間 預告: 2023-12-10 預計發布: 2024-1-1 , 元旦首…

Android 設置音量默認值

在車機 Audio 開發中&#xff0c;有很多場景需要設置音量的最大值和最小值問題&#xff0c;例如通話模式通常是禁止靜音的&#xff0c;耳機模式調整到較大音量時開機后會恢復一個最大默認值等問題。而且通常情況下不通車型的默認值可能會不同&#xff0c;這篇文章就來看一下如何…

Java多線程是什么?

Java多線程是什么&#xff1f; Java多線程是指在程序中同時運行多個線程&#xff0c;每個線程都是獨立運行的&#xff0c;即有自己的執行路徑、棧、寄存器等資源&#xff0c;并且可以同步地訪問共享數據。 Java多線程的主要優勢在于能夠充分利用多核處理器&#xff0c;同時提…

移動端原生實現列表列固定橫向滾動功能

功能介紹&#xff1a; 在移動端開發中&#xff0c;會用到列表作為信息展示方式&#xff0c;一般希望上下滾動時&#xff0c;可以固定表頭&#xff0c;左右滾動時&#xff0c;可以固定最左列。 需求&#xff1a; 1、列表可以使用數組循環遍歷&#xff1b; 2、上下滾動時&…

離線環境下使用百度地圖(vue版)(展示自己的地圖瓦片)3.0版本api

1.下載自己想要的地圖網片 (1)瓦片圖下載 提取百度網盤中文件&#xff0c;然后運行exe文件&#xff0c;選擇要下載的層級及地區即可 百度網盤鏈接&#xff1a;https://pan.baidu.com/s/16sOJ9ws7HCgNH3EMf7Ejyg?pwd0q0e 提取碼&#xff1a;0q0e (2)將瓦片圖映射到網上 推薦使…