<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>M0e_N00b`s Nest</title><description>巧制代码，改变人生</description><link>https://powdered-delta.github.io</link><item><title>尝试 ESP32+Arduino 创建一个带屏幕的ws2812 灯带控制器</title><link>https://powdered-delta.github.io/posts/%E5%B0%9D%E8%AF%95-esp32arduino-%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%B8%A6%E5%B1%8F%E5%B9%95%E7%9A%84ws2812-%E7%81%AF%E5%B8%A6%E6%8E%A7%E5%88%B6%E5%99%A8</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E5%B0%9D%E8%AF%95-esp32arduino-%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%B8%A6%E5%B1%8F%E5%B9%95%E7%9A%84ws2812-%E7%81%AF%E5%B8%A6%E6%8E%A7%E5%88%B6%E5%99%A8</guid><pubDate>Wed, 30 Aug 2023 05:47:25 GMT</pubDate><content:encoded>&lt;p&gt;灯带物料表：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.geeksman.com/esp32/&quot;&gt;https://docs.geeksman.com/esp32/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ws 2812 灯带 一条。
Nano V3 Atmega328P 一块&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240328174354.png&quot; alt=&quot;Pasted image 20240328174354.png&quot; /&gt;
4按键板一块
供电模组：
18650
软包锂电池
usb 5V供电（暂定）&lt;/p&gt;
&lt;p&gt;一块 Oled 单色屏（用于显示UI）SSD1306 驱动&lt;/p&gt;
&lt;p&gt;代码：&lt;/p&gt;
&lt;p&gt;参考地址:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/qq_55493007/article/details/125374751&quot;&gt;https://blog.csdn.net/qq_55493007/article/details/125374751&lt;/a&gt;
`&lt;a href=&quot;https://doc.itprojects.cn/0006.zhishi.esp32/02.doc/index.html&quot;&gt;https://doc.itprojects.cn/0006.zhishi.esp32/02.doc/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import neopixel
from machine import Pin
import time
import urandom

GBIO_IN = Pin(15)  # 控制信号输入引脚
LED_NUM = 30  # LED灯的数量

# class NeoPixel(pin, n, bpp=3, timing=0)
#    pin :输出引脚,可使用引脚见下文
#    n :LED灯的个数
#    bpp:
#        3:默认为3元组RGB
#        4:对于具有3种以上颜色的LED，例如RGBW像素或RGBY像素,采用4元组RGBY或RGBY像素
#    timing:默认等于0,为400KHz速率；等于1，为800KHz速率
#

LED = neopixel.NeoPixel(pin=GBIO_IN, n=LED_NUM, timing=1)  # 创建控制对象

LED.fill((255, 0, 0))  # GRB填充数据(RGB顺序, 0为不亮，255为全亮)
LED.write()  # 写入数据
time.sleep(1)

while True:
    r = urandom.randint(0, 255)
    g = urandom.randint(0, 255)
    b = urandom.randint(0, 255)
    for i in range(30):
        LED[i] = (r, g, b)  # 依次设置LED灯珠的颜色
        LED.write()  # 写入数据
        time.sleep_ms(50)

    r = urandom.randint(0, 255)
    g = urandom.randint(0, 255)
    b = urandom.randint(0, 255)
    for i in range(29, -1, -1):
        LED[i] = (r, g, b)  # 依次设置LED灯珠的颜色
        LED.write()  # 写入数据
        time.sleep_ms(50)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;项目需求可变量：&lt;/p&gt;
&lt;p&gt;灯带长度（代码中配置）
循环长度（代码中配置）
速度 : float[] 可调节  // ms
亮度： float[] 可调节  // 0 ~ 1
模式：text[] 可轮流切换&lt;/p&gt;
&lt;p&gt;根据 current_mode 来进行队列生成方法的选择&lt;/p&gt;
&lt;p&gt;处理时考虑 灯带长度，循环长度，亮度 生成色表
通过色表来进行硬件渲染
速度决定更新时长间隔&lt;/p&gt;
&lt;p&gt;ui如何处理？&lt;/p&gt;
&lt;p&gt;按键功能如何分配？&lt;/p&gt;
&lt;p&gt;暂定4 按键？&lt;/p&gt;
&lt;p&gt;按键需要实现功能:&lt;/p&gt;
&lt;p&gt;有UI: 开机（确定）， +, -,  返回
// 改为三个按钮： 取消返回键，确定和返回共用按钮
开机
主界面：
模式
常亮（单色）
呼吸灯（单色 / 渐变）
跑马灯（没有颜色选项）
渐变（没有颜色选项）
闪烁（受到颜色影响，可随机，可渐变）
随机颜色（不受颜色影响）
缓亮（固定颜色）
亮度（灯光亮度）[0到255]
32,127,255
速度（灯光速度） 单位毫秒，更新一次的时间
uint speedList[] = { 20, 50, 100 };
切换随机
切换渐变&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 返回 HSV 颜色 （待定）
int rgb_to_hsv(int r,int g,int b){
  double min, max, delta;
  min = std::min(std::min(r, g), b);
  max = std::max(std::max(r, g), b);
  v = max / 255.0;
  delta = max - min;
    if (max != 0) {
        s = delta / max;
    } else {
        s = 0;
        h = -1;
        return;
    }
    // max 为红色
        if (r == max) {
        h = (g - b) / delta;
    } else if (g == max) {
        h = 2 + (b - r) / delta;
    } else {
        h = 4 + (r - g) / delta;
    }
    return h,s,v
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;屏幕操作参考：
&lt;a href=&quot;https://www.bilibili.com/video/BV1RM4y1a7J5?p=18&quot;&gt;https://www.bilibili.com/video/BV1RM4y1a7J5?p=18&lt;/a&gt;
&lt;img src=&quot;images/Pasted%20image%2020240327163930.png&quot; alt=&quot;Pasted image 20240327163930.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;按键板:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;K1&lt;/th&gt;
&lt;th&gt;A4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;K2&lt;/td&gt;
&lt;td&gt;A5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;K3&lt;/td&gt;
&lt;td&gt;A6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;K4&lt;/td&gt;
&lt;td&gt;A7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;新版按键：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;K1&lt;/th&gt;
&lt;th&gt;D5&lt;/th&gt;
&lt;th&gt;5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;K2&lt;/td&gt;
&lt;td&gt;D4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;K3&lt;/td&gt;
&lt;td&gt;D3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;K4&lt;/td&gt;
&lt;td&gt;D2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;GND&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;OLED 屏幕 # 0.91寸OLED模块12832液晶屏ssd1306显示屏 IIC模块 4针oled屏&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GND&lt;/th&gt;
&lt;th&gt;GND&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VCC&lt;/td&gt;
&lt;td&gt;VIN/3V3&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SCK&lt;/td&gt;
&lt;td&gt;D13&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;// 链接到 SCL（A5） 上 成功点亮&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDA&lt;/td&gt;
&lt;td&gt;A4&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;大号屏幕链接图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240328184358.png&quot; alt=&quot;Pasted image 20240328184358.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;测试项目： pong&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://wokwi.com/projects/348849468083274322&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;已知问题：屏幕字库不支持中文&lt;/p&gt;
&lt;p&gt;切换菜单的 代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;SPI.h&amp;gt;
&amp;lt;Wire.h&amp;gt;
&amp;lt;Adafruit_GFX.h&amp;gt;
&amp;lt;Adafruit_SSD1306.h&amp;gt;
  
UP_BUTTON 2
DOWN_BUTTON 3
String MENU_LIST[4] = { &quot;Color&quot;, &quot;Speed&quot;, &quot;Light&quot;, &quot;Power off&quot; };
int CURRENT_MENU = 0;
int MENU_ITEMS = 4;
  
  
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &amp;amp;Wire);
  
uint8_t count;
  
  
void setup()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  
  // Display the splash screen (we&apos;re legally required to do so)
  display.display();
  // unsigned long start = millis();
  
  pinMode(UP_BUTTON, INPUT_PULLUP);
  pinMode(DOWN_BUTTON, INPUT_PULLUP);
  
  display.clearDisplay();
  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10, 18);
  display.display();
  
}
  
void loop()
{
  static bool up_state = false;
  static bool down_state = false;
  up_state |= (digitalRead(UP_BUTTON) == LOW);
  down_state |= (digitalRead(DOWN_BUTTON) == LOW);
  
  
  if (up_state)
  {
    delay(300);
    CURRENT_MENU = (CURRENT_MENU+1)%MENU_ITEMS;
  }
  if (down_state)
  {
    delay(300);
    if (CURRENT_MENU &amp;gt; 0) {
      CURRENT_MENU -= 1;
    } else {
      CURRENT_MENU = 0;
    }
  }
  up_state = down_state = false;
  display.clearDisplay();
  display.setCursor(5, 18);
  display.print(CURRENT_MENU);
  display.setCursor(25, 18);
  display.print(MENU_LIST[CURRENT_MENU]);
  display.display();
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;// 调试问题：&lt;a href=&quot;https://www.jianshu.com/p/8e14f233d0e7&quot;&gt;https://www.jianshu.com/p/8e14f233d0e7&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;文字显示  在线取模：
&lt;a href=&quot;https://www.zhetao.com/fontarray.html&quot;&gt;https://www.zhetao.com/fontarray.html&lt;/a&gt;
&lt;a href=&quot;https://javl.github.io/image2cpp/&quot;&gt;https://javl.github.io/image2cpp/&lt;/a&gt;
默认配置即可&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240329171501.png&quot; alt=&quot;Pasted image 20240329171501.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;忍杀取模 64 * 32
&lt;img src=&quot;images/Pasted%20image%2020240329171435.png&quot; alt=&quot;Pasted image 20240329171435.png&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// &apos;sp20240329_170854_974&apos;, 58x32px
const unsigned char epd_bitmap_sp20240329_170854_974 [] PROGMEM = {
 0x00, 0x00, 0x01, 0xc0, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0x80, 0x1c, 0x00, 0x03, 0x00, 
 0x3c, 0x00, 0x7f, 0x80, 0x1e, 0x00, 0x0e, 0x00, 0x0f, 0xc3, 0xff, 0x80, 0x1f, 0x90, 0x7e, 0x00, 
 0x03, 0xff, 0xff, 0x80, 0x9f, 0x99, 0xf4, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x7f, 0x1f, 0xcc, 0x80, 
 0x01, 0xfc, 0x0f, 0x00, 0x3e, 0x0f, 0x18, 0x80, 0x03, 0xf8, 0x0f, 0x00, 0x3f, 0x0e, 0x19, 0x80, 
 0x03, 0xf0, 0x0f, 0x00, 0x3f, 0xce, 0x31, 0x80, 0x07, 0xe0, 0x0f, 0x00, 0x73, 0x8f, 0x33, 0xc0, 
 0x1f, 0xc0, 0x07, 0x00, 0x61, 0x1f, 0x73, 0xc0, 0x7f, 0x80, 0x87, 0x80, 0x80, 0x3f, 0x63, 0x80, 
 0x3f, 0x80, 0x67, 0x80, 0x38, 0x7e, 0x67, 0x80, 0x0f, 0x80, 0x3f, 0xc0, 0xf0, 0x1c, 0xff, 0x00, 
 0x03, 0xc8, 0x1f, 0xc0, 0x70, 0x08, 0xfe, 0x00, 0x00, 0x64, 0x07, 0x80, 0x31, 0xc1, 0xfc, 0x00, 
 0x23, 0x16, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x11, 0xc6, 0x00, 0x00, 0x78, 0x3f, 0x80, 0x00, 
 0x19, 0xe7, 0x40, 0x81, 0xf0, 0x07, 0xfe, 0x00, 0x39, 0xcf, 0x41, 0x00, 0x78, 0x40, 0xfc, 0x00, 
 0x79, 0x9f, 0x63, 0x00, 0x7e, 0x30, 0x78, 0x00, 0x79, 0x9e, 0x66, 0x00, 0xff, 0x98, 0xf0, 0x00, 
 0x33, 0x8c, 0xf6, 0x00, 0xbb, 0x8f, 0xe0, 0x00, 0x03, 0x81, 0xf7, 0x01, 0x33, 0x07, 0xc0, 0x00, 
 0x03, 0xc1, 0xf7, 0x80, 0x31, 0x0f, 0xf8, 0x00, 0x01, 0xe1, 0xe7, 0x80, 0x39, 0x1f, 0xf0, 0x00, 
 0x00, 0x70, 0xc7, 0x00, 0x78, 0x79, 0xe0, 0x00, 0x00, 0x38, 0x0f, 0x00, 0xfc, 0xe1, 0xc0, 0x00, 
 0x00, 0x1c, 0x1e, 0x00, 0x7d, 0x81, 0x00, 0x00, 0x00, 0x06, 0x38, 0x00, 0x1c, 0x00, 0x00, 0x00, 
 0x00, 0x03, 0xe0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 272)
const int epd_bitmap_allArray_LEN = 1;
const unsigned char* epd_bitmap_allArray[1] = {
 epd_bitmap_sp20240329_170854_974
};

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最简显示BMP代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;SPI.h&amp;gt;
&amp;lt;Wire.h&amp;gt;
&amp;lt;Adafruit_GFX.h&amp;gt;
&amp;lt;Adafruit_SSD1306.h&amp;gt;

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &amp;amp;Wire);

// &apos;sp20240329_170854_974&apos;, 58x32px
const unsigned char epd_bitmap_sp20240329_170854_974 [] PROGMEM = {
 0x00, 0x00, 0x01, 0xc0, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0x80, 0x1c, 0x00, 0x03, 0x00, 
 0x3c, 0x00, 0x7f, 0x80, 0x1e, 0x00, 0x0e, 0x00, 0x0f, 0xc3, 0xff, 0x80, 0x1f, 0x90, 0x7e, 0x00, 
 0x03, 0xff, 0xff, 0x80, 0x9f, 0x99, 0xf4, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x7f, 0x1f, 0xcc, 0x80, 
 0x01, 0xfc, 0x0f, 0x00, 0x3e, 0x0f, 0x18, 0x80, 0x03, 0xf8, 0x0f, 0x00, 0x3f, 0x0e, 0x19, 0x80, 
 0x03, 0xf0, 0x0f, 0x00, 0x3f, 0xce, 0x31, 0x80, 0x07, 0xe0, 0x0f, 0x00, 0x73, 0x8f, 0x33, 0xc0, 
 0x1f, 0xc0, 0x07, 0x00, 0x61, 0x1f, 0x73, 0xc0, 0x7f, 0x80, 0x87, 0x80, 0x80, 0x3f, 0x63, 0x80, 
 0x3f, 0x80, 0x67, 0x80, 0x38, 0x7e, 0x67, 0x80, 0x0f, 0x80, 0x3f, 0xc0, 0xf0, 0x1c, 0xff, 0x00, 
 0x03, 0xc8, 0x1f, 0xc0, 0x70, 0x08, 0xfe, 0x00, 0x00, 0x64, 0x07, 0x80, 0x31, 0xc1, 0xfc, 0x00, 
 0x23, 0x16, 0x03, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x11, 0xc6, 0x00, 0x00, 0x78, 0x3f, 0x80, 0x00, 
 0x19, 0xe7, 0x40, 0x81, 0xf0, 0x07, 0xfe, 0x00, 0x39, 0xcf, 0x41, 0x00, 0x78, 0x40, 0xfc, 0x00, 
 0x79, 0x9f, 0x63, 0x00, 0x7e, 0x30, 0x78, 0x00, 0x79, 0x9e, 0x66, 0x00, 0xff, 0x98, 0xf0, 0x00, 
 0x33, 0x8c, 0xf6, 0x00, 0xbb, 0x8f, 0xe0, 0x00, 0x03, 0x81, 0xf7, 0x01, 0x33, 0x07, 0xc0, 0x00, 
 0x03, 0xc1, 0xf7, 0x80, 0x31, 0x0f, 0xf8, 0x00, 0x01, 0xe1, 0xe7, 0x80, 0x39, 0x1f, 0xf0, 0x00, 
 0x00, 0x70, 0xc7, 0x00, 0x78, 0x79, 0xe0, 0x00, 0x00, 0x38, 0x0f, 0x00, 0xfc, 0xe1, 0xc0, 0x00, 
 0x00, 0x1c, 0x1e, 0x00, 0x7d, 0x81, 0x00, 0x00, 0x00, 0x06, 0x38, 0x00, 0x1c, 0x00, 0x00, 0x00, 
 0x00, 0x03, 0xe0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
};

// 动画用帧数控制
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 272)
const int epd_bitmap_allArray_LEN = 1;
const unsigned char* epd_bitmap_allArray[1] = {
 epd_bitmap_sp20240329_170854_974
};

void setup()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  display.drawBitmap(35, 0, epd_bitmap_sp20240329_170854_974, 58, 32, SSD1306_WHITE);

  display.display();
}

void loop()
{

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最终控制代码&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Arduino.h&amp;gt;
&amp;lt;String.h&amp;gt;
&amp;lt;Adafruit_NeoPixel.h&amp;gt;
&amp;lt;Adafruit_GFX.h&amp;gt;
&amp;lt;Adafruit_SSD1306.h&amp;gt;


// 按钮参数
UP_BTN 2       // D2 (可省略)
DOWN_BTN 3     // D3
CONFIRM_BTN 4  // D4
// 灯带参数
LED_PIN 6  //D6
LED_NUM 30
DelayTime 50

Adafruit_NeoPixel strip(LED_NUM, LED_PIN, NEO_GRB + NEO_KHZ800);



/*
    屏幕链接:
    SCK A5
    SDA A4
*/
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &amp;amp;Wire);

// 先测试通过上下按键切换不同的菜单选项

// 菜单
String menuList[] = {
  &quot;1:Mode&quot;,
  &quot;2:Bright&quot;,
  &quot;3:Color&quot;,
  &quot;4:Delay&quot;,
};

// 当前菜单项
uint8_t currentMenuIndex = 0;
// 菜单总长度（用于处理
uint8_t menuLength = 4;
// 标记是否在子菜单中，负责渲染菜单/选项 和 处理按键操作
bool isSubMenu = false;

// 模式相关
String modeList[] = {
  &quot;Rainbow Flow&quot;,    // 0 彩虹跑马灯
  &quot;Rainbow Pause&quot;,   // 1 彩虹暂停
  &quot;Rainbow Breath&quot;,  // 2 彩虹呼吸灯
  &quot;Breath&quot;,          // 3 单色呼吸灯
  &quot;Blink&quot;,           // 4 闪烁
  &quot;Pulse&quot;,           // 5 脉动
  &quot;Sigle Color&quot;,     // 6 单色常亮（从头开始依次点亮）
};
uint8_t currentModeIndex = 0;
uint8_t modeLength = 7;

// 亮度相关 默认中等亮度
float brightList[] = { 15, 31, 127, 255 };
uint8_t currentBrightIndex = 1;
uint8_t brightLength = 4;

// 速度配置项 // 单位毫秒，更新一次的时间
unsigned long delayList[] = { 20, 50, 100, 500 };
uint8_t currentDelayIndex = 2;
uint8_t delayLength = 4;
// 色彩 // 可能不需要，考虑通过Hue 实现渐变
uint32_t colorList[] = {
  strip.Color(255, 0, 0),     // 红色
  strip.Color(255, 165, 0),   // 橙色
  strip.Color(255, 255, 0),   // 黄色
  strip.Color(0, 128, 0),     // 绿色
  strip.Color(0, 255, 255),   // 青色
  strip.Color(0, 0, 255),     // 蓝色
  strip.Color(128, 0, 128),   // 紫色
  strip.Color(255, 255, 255)  // 白色
};

String colorNameList[] = {
  &quot;Red&quot;,
  &quot;Orange&quot;,
  &quot;Yellow&quot;,
  &quot;Green&quot;,
  &quot;Cyan&quot;,
  &quot;Blue&quot;,
  &quot;Purple&quot;,
  &quot;White&quot;,
};
uint8_t currentColorIndex = 1;
uint8_t colorLength = 8;

// 处理按钮截流和灯效延迟
bool btn_flag = false;
unsigned long previousMillisBtn = 0;
unsigned long previousMillis = 0;
// seed用于生成特效时记录当前的渲染指数
long rainbowSeed = 0;
int breathSeed = 0;
int pulseSeed = 0;

// 灯效相关代码

// 控制呼吸灯强度
void setBreathBrightness(int breathSteps) {
  int step = floor(brightList[currentBrightIndex] / breathSteps);
  /**
     * 当前的 seed 提供初始值
     * 共计循环 steps *2 次，每次单独计算亮度，
     * 随后计算本次亮度（如何处理默认亮度？通过判断 currentModeIndex 跳过、
     * seed小于steps： 直接设定亮度为 seed * step
     * seed大于steps: 设定为 currentBright - (seed-steps)*step
     * */
  int bright = 0;
  if (breathSeed &amp;lt;= breathSteps) {
    bright = breathSeed * step;
  } else {
    bright = brightList[currentBrightIndex] - ((breathSeed - breathSteps) * step);
  }
  breathSeed = (breathSeed + 1) % (2 * breathSteps);

  strip.setBrightness(bright);
}

// 彩虹跑马灯 参数控制是否静态
void rainbowFlow(bool isStatic) {
  // 向上取整
  uint16_t step = ceil(65535 / strip.numPixels());
  uint16_t firstHue = 65535 - rainbowSeed * step;  // 根据seed算出当前第一个led的Hue seed
  // 直接算出修正值，用于修正
  for (uint16_t i = 0; i &amp;lt; strip.numPixels(); i++)
  // 遍历灯条
  {
    /**
         * 计算颜色
         * seed 需要跟 灯珠数量对比
         * 第一个偏移为0, 每个灯珠的 Hue 步进为多少？(65535/30?)
         * 指定第i灯的颜色
         * 例如：长度10, 0灯初始Hue为0, 1灯初始Hue 为 6553
         * 第二帧时： 0灯Hue 为 65535-6553 1灯为0
         * 3帧： 0 = 65535-6553-6553(65535*(10-2)/10) 1 为 65535*（10-1)/10
         */
    uint16_t pixelHue = firstHue + step * i;
    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
  }
  if (!isStatic) {
    rainbowSeed = (rainbowSeed + 1) % strip.numPixels();
  }
  strip.show();
}

void rainbowBreath(int steps) {
  setBreathBrightness(steps);
  rainbowFlow(false);
}
void singleColor(int len = strip.numPixels()) {
  // 单色，直接点亮
  if (len &amp;gt; 0) {
    strip.fill(colorList[currentColorIndex], 0, len);
  } else {
    strip.clear();
  }
  strip.show();
}

// 此处 steps 不能小于最小亮度
void singleBreath(int breathSteps)
// 通过 breathSeed 来控制当前的呼吸灯状态。 breathSteps 控制段数
{
  setBreathBrightness(breathSteps);
  singleColor();
}

/**
 * 处理灯光闪烁
 */
void blink() {
  // 跟呼吸同理，但是只有亮灭,step 为1 即可实现
  singleBreath(1);
}
void pulse() {
  /**
     * 通过 pulseSeed 实现。上限为 length*2
     * 根据 pulse获得当前长度，然后用 fill 填充长度即可
     */
  int total = strip.numPixels();
  strip.clear();
  if (pulseSeed &amp;lt;= total) {
    singleColor(pulseSeed);
  } else {
    singleColor(total - (pulseSeed - total));
  }

  pulseSeed = (pulseSeed + 1) % (total * 2);
}

// 功能性方法，处理屏幕和按键

/**处理按钮按下的后续操作
 * 总共三个按钮需要处理
 * 按键类型用对应针脚代替
 * 上    D2  2
 * 下    D3  3
 * 确认  D4  4
 * （也可以简化掉 上键
 *
 * 判断处理顺序：
 * 先判断是否为 confirm、
 * 判断当前是否 sub
 */
void handlePressBtn(uint8_t type) {
  if (type == CONFIRM_BTN) {
    isSubMenu = !isSubMenu;
  } else if (!isSubMenu)
  // 主菜单
  {
    switch (type) {
      case DOWN_BTN:  // 下
        currentMenuIndex = (currentMenuIndex + 1) % menuLength;
        break;
      case UP_BTN:  // 上
        currentMenuIndex = (currentMenuIndex == 0 ? menuLength : currentMenuIndex) - 1;
        break;
    }
  } else
  // 子菜单
  {
    switch (type) {
      case DOWN_BTN:  // 下
        switch (currentMenuIndex) {
          case 0:  // MODE
            currentModeIndex = (currentModeIndex + 1) % modeLength;
            break;
          case 1:  // Bright
            currentBrightIndex = (currentBrightIndex + 1) % brightLength;
            break;
          case 2:  // Color
            currentColorIndex = (currentColorIndex + 1) % colorLength;
            break;
          case 3:  // Delay
            currentDelayIndex = (currentDelayIndex + 1) % delayLength;
            break;
        }
        break;
      case UP_BTN:  // 上

        switch (currentMenuIndex) {
          case 0:  // MODE
            currentModeIndex = (currentModeIndex == 0 ? modeLength : currentModeIndex) - 1;
            break;
          case 1:  // Bright
            currentBrightIndex = (currentBrightIndex == 0 ? brightLength : currentBrightIndex) - 1;
            break;
          case 2:  // Color
            currentColorIndex = (currentColorIndex == 0 ? colorLength : currentColorIndex) - 1;
            break;
          case 3:  // Delay
            currentDelayIndex = (currentDelayIndex == 0 ? delayLength : currentDelayIndex) - 1;
            break;
        }
        break;
    }
  }
}

/**
 * 该方法用于渲染当前屏幕内容
 */
void renderScreen() {
  display.clearDisplay();
  // 根据当前是否为子菜单判断
  if (!isSubMenu) {
    // 字号2
    display.setCursor(0, 6);
    display.setTextSize(2);
    // 渲染主菜单内容
    display.print(menuList[currentMenuIndex]);
  } else {
    // 字号1
    display.setTextSize(1);
    // 先渲染Menu项：
    display.setCursor(0, 0);
    display.print(menuList[currentMenuIndex] + &quot;:&quot;);
    // 再获取 subMenu 选项
    String text;
    // 当前为子菜单时，根据case 渲染对应的 item
    switch (currentMenuIndex) {
      case 0:  // MODE
        text = modeList[currentModeIndex];
        break;
      case 1:  // Bright
        text = String(currentBrightIndex + 1);
        break;
      case 2:  // Color
        text = colorNameList[currentColorIndex];
        break;
      case 3:  // Delay
        text = &quot;Delay: &quot; + String(delayList[currentDelayIndex]) + &quot; ms&quot;;
        break;
    }
    display.setCursor(12, 12);
    display.print(text);
  }
  display.display();
}

/**
 * 用于点亮灯条，根据当前的参数选择不同的灯条渲染方法
  String modeList[] = {
    &quot;Rainbow Flow&quot;,     // 彩虹跑马灯
    &quot;Rainbow Gradient&quot;, // 彩虹暂停
    &quot;Rainbow Breath&quot;,   // 彩虹呼吸灯
    &quot;Breath&quot;,           // 单色呼吸灯
    &quot;Blink&quot;,            // 闪烁
    &quot;Pulse&quot;,            // 脉动
    &quot;Sigle Color&quot;,      // 单色常亮（从头开始依次点亮）
  };
 * *灯效处理内部不加延时
 */
void renderStrip() {
  // 设置亮度
  // 如果 mode 不为呼吸灯，呼吸灯则跳过设置亮度
  if (currentModeIndex != 2 &amp;amp;&amp;amp; currentModeIndex != 3) {
    strip.setBrightness(brightList[currentBrightIndex]);
  }

  switch (currentModeIndex) {
    case 0:  // 彩虹跑马灯
      rainbowFlow(false);
      break;
    case 1:  // 彩虹暂停
      // rainbowStatic();
      rainbowFlow(true);
      break;
    case 2:  // 彩虹呼吸灯
      rainbowBreath(15);
      break;
    case 3:  // 单色呼吸灯
      singleBreath(15);
      break;
    case 4:  // 闪烁
      // 呼吸 step 为 1 即可实现
      singleBreath(1);
      break;
    case 5:  // 脉动
      pulse();
      break;
    case 6:  // 单色常亮
      singleColor();
      break;
    default:
      rainbowFlow(false);
  }

  // 测试用
}

// 最后执行阶段
void setup() {
  // 初始化灯条
  strip.begin();
  strip.setBrightness(brightList[currentBrightIndex]);
  strip.show();

  // 初始化按键

  pinMode(UP_BTN, INPUT_PULLUP);
  pinMode(DOWN_BTN, INPUT_PULLUP);
  pinMode(CONFIRM_BTN, INPUT_PULLUP);

  // 初始化屏幕
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
}

void loop() {
  /**
     * 此处结构为：
     * 初始化
     * 监听按键
     *  按下则按照情况处理
     * 渲染界面
     *  根据当前的 isSubmenu 和 currentMenu 以及 index 等处理显示内容
     * 点亮灯条
     *  根据当前的所有参数（Bright, Mode, Delay, Random) 进行渲染
     */

  unsigned long currentMillis = millis();  // 获取当前时间

  // 监听按键
  static bool up_state = false;
  static bool down_state = false;
  static bool confirm_state = false;
  // 读取按键
  up_state |= (digitalRead(UP_BTN) == LOW);
  down_state |= (digitalRead(DOWN_BTN) == LOW);
  confirm_state |= (digitalRead(CONFIRM_BTN) == LOW);

  if (currentMillis - previousMillisBtn &amp;gt;= 300) {
    // 按钮flag 复位
    btn_flag = false;
  }

  if (!btn_flag &amp;amp;&amp;amp; (up_state || down_state || confirm_state)) {
    delay(20);
    // 储存当前按钮时间戳并且设定 flag, 跳过200ms内的处理
    previousMillisBtn = currentMillis;
    btn_flag = true;
    if (up_state) {
      handlePressBtn(UP_BTN);
    } else if (down_state) {
      handlePressBtn(DOWN_BTN);
    } else if (confirm_state) {
      handlePressBtn(CONFIRM_BTN);
    }
  }
  up_state = down_state = confirm_state = false;
  // 比较按钮时间戳并且在200ms后复位 btn_flag

  // 展示屏幕内容
  renderScreen();
  // 根据指定的延迟渲染灯条
  if (currentMillis - previousMillis &amp;gt;= delayList[currentDelayIndex]) {
    renderStrip();
    previousMillis = currentMillis;
  }
}


&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>Win WSL环境下部署 FunAsr 踩坑笔记</title><link>https://powdered-delta.github.io/posts/win-wsl%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%83%A8%E7%BD%B2-funasr-%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/win-wsl%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%83%A8%E7%BD%B2-funasr-%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0</guid><pubDate>Fri, 08 Mar 2024 04:56:22 GMT</pubDate><content:encoded>&lt;p&gt;本文 WSL安装部分参考 &lt;a href=&quot;https://blog.lukeewin.top/archives/install-funasr-with-docker&quot;&gt;docker安装funasr - lukeewin的博客&lt;/a&gt; ，查询原文获取更多信息
FunASR 官方仓库： &lt;a href=&quot;https://github.com/modelscope/FunASR/&quot;&gt;https://github.com/modelscope/FunASR/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;方案1： 通过官方打包成品文件直接使用&lt;/h2&gt;
&lt;p&gt;WSL折腾完后才发现官方原来有win平台打包成品（
win版本发布地址：
&lt;a href=&quot;https://www.modelscope.cn/models/iic/funasr-runtime-win-cpu-x64&quot;&gt;https://www.modelscope.cn/models/iic/funasr-runtime-win-cpu-x64&lt;/a&gt;
安装模型等参考链接介绍或者下方 linux环境&lt;/p&gt;
&lt;h2&gt;方案2：通过 WSL 安装&lt;/h2&gt;
&lt;h3&gt;1. 安装 miniconda（可选）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1. 清理 现有 python 安装
2. 下载，安装 miniconda
3. 配置初始化
 1. `./conda init --all`
4. 解决命令行报错
 1. `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned`
5. 安装python 3.8 环境
 1. `conda create -n funasr python=3.8`
 2. `conda activate funasr`
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 安装 funasr&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1. `pip3 install -U funasr -i https://mirrors.aliyun.com/pypi/simple/`
2. 安装 hdbscan 失败
 1. Failed building wheel for hdbscan
 2. 解决方案
 3.  `conda install -c conda-forge hdbscan`  // 没用
 4. 安装 c++ build tools
     [独立安装VS的C++编译器build tools - 知乎 (zhihu.com)]
     (https://zhuanlan.zhihu.com/p/458579668)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 安装 modelScope&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1.  `pip install modelscope`
2. 下载模型文件：
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
 from modelscope.hub.snapshot_download import snapshot_download model_dir = snapshot_download(&apos;damo/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404-onnx&apos;, cache_dir=&apos;path/to/local/dir&apos;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;（ 剩余部分丢失，请参照原文 &lt;a href=&quot;https://blog.lukeewin.top/archives/install-funasr-with-docker&quot;&gt;docker安装funasr - lukeewin的博客&lt;/a&gt; )&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>PS 快捷操作</title><link>https://powdered-delta.github.io/posts/ps-%E5%BF%AB%E6%8D%B7%E6%93%8D%E4%BD%9C</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/ps-%E5%BF%AB%E6%8D%B7%E6%93%8D%E4%BD%9C</guid><pubDate>Mon, 02 Dec 2024 08:16:53 GMT</pubDate><content:encoded>&lt;p&gt;前段时间有群友打算试试漫画嵌字
此处整理一下我能想起来的嵌字常用PS快捷键&lt;/p&gt;
&lt;p&gt;b 铅笔
e 橡皮擦
w 选中工具 （shift+w 切换）
m 框选
如果框需要调整的话，shift+拖动就是加选，alt+拖动就是减选
g 是油漆桶和渐变（shift+g切换）
t 文本框 ctrl+enter 就是确认文本框内容（退出文本框编辑）
ctrl+c 复制选区之后，按ctrl+shift+v会在原本位置粘贴为新图层（直接ctrl+v 会在当前屏幕正中间粘贴）
b 或者 e 模式下，按住ctrl 左键点击画面部分，可以快速切换到那一块所在的图层&lt;/p&gt;
&lt;p&gt;ctrl+shift+e 合并图层
ctrl+shift+alt+e 新建合并图层
shift+t 变形&lt;/p&gt;
&lt;p&gt;图层操作：
Ctrl+j 复制图层（按住alt，鼠标左键拖动也可以复制图层）
ctrl+左键 多选图层
ctrl+e 将多选的图层合并（不保留原图层）
ctrl+alt+e 将多选的图层合并到新建图层（保留原图层）
ctrl+alt+shift+e 将当前的所有可见图层合并到新建图层&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>【转载】遊戲模型佈線對動作變形之影響（1）-手肘膝蓋篇</title><link>https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF1-%E6%89%8B%E8%82%98%E8%86%9D%E8%93%8B%E7%AF%87</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF1-%E6%89%8B%E8%82%98%E8%86%9D%E8%93%8B%E7%AF%87</guid><pubDate>Thu, 05 Dec 2024 05:58:18 GMT</pubDate><content:encoded>&lt;p&gt;转载自 &lt;a href=&quot;https://bida999.pixnet.net/blog/post/23951002&quot;&gt;https://bida999.pixnet.net/blog/post/23951002&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;對於文章標題如何訂，著實讓我想了很久，最後還是把他搞的&lt;br /&gt;
又臭又長，真不好意思，言歸正傳，相信很多人對於佈線影響變形&lt;br /&gt;
已經很有概念，所以在這裡就以我所了解的來跟大家分享交流，&lt;br /&gt;
內容以遊戲用的關節佈線為主，正所謂萬變不離其宗，只要能把&lt;br /&gt;
觀念建立起來，以後不論是做怪物還是動畫用的模型都不是問題，&lt;br /&gt;
預計會分三個章節來講，由淺入深。&lt;br /&gt;
內容大致如下：&lt;br /&gt;
   1.手肘膝蓋篇&lt;br /&gt;
   2.骨盆肩膀篇&lt;br /&gt;
   3.臉部表情篇因為這只是個人的經驗心得，所以有不足的地方，歡迎大家一起&lt;br /&gt;
研究討論。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;為什麼模型要有正確的關節佈線？&lt;/strong&gt;&lt;br /&gt;
   首先正確的關節佈線可以避免面數的浪費，讓權重變得容易調整&lt;br /&gt;
而且省時，更可以讓關節彎曲時看起來更漂亮。這就是為什麼正確的&lt;br /&gt;
佈線對關節變形這麼重要了，對於遊戲製作的分工來說，經常會發生&lt;br /&gt;
模型製作人員因為沒有Rigging的經驗，因此在製作模型時只求其形&lt;br /&gt;
而不思其行，在關節佈線上沒有考慮周詳，導致反覆修改的問題。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;怎麼樣佈線關節變形才會好看？&lt;/strong&gt;    就以手肘、膝蓋以及手指來說，他們都有個共通點，那就是他們&lt;br /&gt;
只能單軸單方向旋轉，這也是為什麼在格鬥中會有關節技，也正因為&lt;br /&gt;
如此，這類型的佈線是可以被定義成一個規則來依循的，基本以關節&lt;br /&gt;
內外彎曲來分，只要掌握住**『外3內2』&lt;strong&gt;的佈線規則，就可以正確的&lt;br /&gt;
完成這類型的關節，如果在面數許可的情況下，可以增加外彎部分的&lt;br /&gt;
線段，以強化彎曲時的剪影線條。    可能會有人問：為什麼關節內側只需要2條線段，大家可以看下面&lt;br /&gt;
的3張圖示來理解，就&lt;/strong&gt;（圖1）**來看，關節內側只有2條線段，在設定&lt;br /&gt;
權重時上面的線段給大腿骨骼控制，下面的給小腿控制，最後當關節&lt;br /&gt;
彎曲時，我們可以看到內側變形的結果是合理及漂亮的。&lt;br /&gt;
&lt;img src=&quot;images/Pasted%20image%2020240406160547.png&quot; alt=&quot;Pasted image 20240406160547.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;以**（圖2）**來說，關節內側有3條線段，以致於中間的那條線段必須&lt;br /&gt;
要給2根骨骼各一半的權重，於是在彎曲時產生出不自然的凹陷，雖然&lt;br /&gt;
不太明顯，不過卻浪費了面數又沒有達到效果。&lt;br /&gt;
&lt;img src=&quot;images/Pasted%20image%2020240406160604.png&quot; alt=&quot;Pasted image 20240406160604.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;以**（圖3）&lt;strong&gt;來說，關節內側只給1條線段，在彎曲時我們可以看到&lt;br /&gt;
這樣的佈線是變形最嚴重的，雖然面數省下來了，可是卻也犧牲了關節&lt;br /&gt;
的剪影，基本上只有在做&lt;/strong&gt;LOD**的時候才有可能出現這樣的佈線。&lt;/p&gt;
&lt;p&gt;相信只要掌握住這個大原則，以後既便是做怪物也不用擔心佈線的問題。&lt;br /&gt;
   在這裡有個小技巧跟大家分享，一般我們在彎曲關節時，會發現&lt;br /&gt;
有奇怪的黑影，有時候我們只要把四邊面裡的線段轉個方向，其實&lt;br /&gt;
就可以解決這個問題，讓他看起來更完美。&lt;strong&gt;（如圖下所示）&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;images/Pasted%20image%2020240406160440.png&quot; alt=&quot;Pasted image 20240406160440.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;好久沒有寫這類的東西，寫起來才發現自己的贅詞很多，經過反覆檢驗&lt;br /&gt;
跟修改，希望大家可以了解我寫的內容。（達到&quot;筆隨心動&quot;境界，難～）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;＊LOD：&lt;strong&gt;全名叫&lt;/strong&gt;『Level of detail』&lt;/strong&gt;，從字面上可以解釋成有層級的&lt;br /&gt;
           細節，在3D即時遊戲中是經常使用的一種增加效能的方法，           簡單的說就是將模型在鏡頭前的出現的距離遠近，來決定顯示&lt;br /&gt;
           出多少面數的模型，所以在模型製作上，同一個模型會有不同&lt;br /&gt;
           面數的模型，原則上模型減面有個通用計算方式，假如原始模型&lt;br /&gt;
           是5000面，那LOD1就打五折變2500面，之後以此類推，1250&lt;br /&gt;
           、625.......。&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>【转载】遊戲模型佈線對動作變形之影響（2-1）-骨盆篇</title><link>https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF2-1-%E9%AA%A8%E7%9B%86%E7%AF%87</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF2-1-%E9%AA%A8%E7%9B%86%E7%AF%87</guid><pubDate>Thu, 05 Dec 2024 05:58:20 GMT</pubDate><content:encoded>&lt;p&gt;转载自 &lt;a href=&quot;https://bida999.pixnet.net/blog/post/24080170&quot;&gt;https://bida999.pixnet.net/blog/post/24080170&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;這次我把第二篇的內容分成兩次來講，先來說說骨盆部分吧，&lt;br /&gt;
骨盆這塊位置就我們人體來說是個比較特別的地方，為什麼要&lt;br /&gt;
這麼說呢？是因為小雞雞會長在這邊嗎？當然不是啦，是因為&lt;br /&gt;
他是個有&lt;strong&gt;分叉&lt;/strong&gt;的地方，也就是一個屁股長出兩條腿，在人體上&lt;br /&gt;
還包含手掌跟手指也是同樣的類型。&lt;/p&gt;
&lt;p&gt;這類型基本上也是會有內彎跟外彎的差別，只是在外彎曲&lt;br /&gt;
不像手肘膝蓋那樣的限制，大腿的旋轉範圍相對來說會自由&lt;br /&gt;
的多，再加上兩腿之間會打開的狀況，所以模型除了在佈線&lt;br /&gt;
的考慮外，還要搭配權重的分配才能算是完整。&lt;/p&gt;
&lt;p&gt;就骨盆的模型佈線來說，有幾個地方要注意：&lt;strong&gt;（圖1）&lt;/strong&gt;&lt;br /&gt;
1、因為大腿會內彎曲，所以正面部分的佈線也是以兩條為主，&lt;br /&gt;
    並把兩條線段的位置放在大腿關節點上。&lt;br /&gt;
2、因為骨盆相較手肘膝蓋來說，他的體積大了很多，所以當&lt;br /&gt;
    大腿彎曲時，屁股的弧線就會容易被注意到，所以基本款&lt;br /&gt;
    一定要有3條線，然後再依據角色在鏡頭前的遠近來增加&lt;br /&gt;
    屁股的線段。&lt;br /&gt;
3、因為會有劈腿的動作，所以跨下要有兩條佈線，手掌跟手指&lt;br /&gt;
    之間也是一樣。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161138.png&quot; alt=&quot;Pasted image 20240406161138.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之前手肘內彎曲的權重設定分別給兩根骨頭就可以，不過&lt;br /&gt;
骨盆在權重設定上要有所改變，基本上先抬腿到45度左右，&lt;br /&gt;
調整內彎曲線段的權重（圖2的權重數值為參考值並非絕對）&lt;br /&gt;
，讓他不要穿插，之後在抬到90度來做體積感的微調，屁股&lt;br /&gt;
也是同樣，要調整成像是扇子打開的樣子，最後再檢查模型&lt;br /&gt;
的三角線的方向。&lt;strong&gt;（圖2）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161147.png&quot; alt=&quot;Pasted image 20240406161147.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最後我們檢查劈腿以及後彎的樣子，再微調相關的權重點&lt;br /&gt;
，因為當初跨下給了他兩條線段，可以看到當劈腿時跨下的&lt;br /&gt;
體積感會比較飽滿（有一趴），後彎部分也調整到在後抬腿&lt;br /&gt;
大約30度時不要穿插。&lt;strong&gt;（圖3）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161157.png&quot; alt=&quot;Pasted image 20240406161157.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在手掌手指之間也同樣適用以上的佈線方式，只需注意&lt;br /&gt;
把手掌跟手指交接的關節一顆一顆凸出來的感覺做出來就&lt;br /&gt;
可以。&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>【转载】遊戲模型佈線對動作變形之影響（2-2）-肩膀篇</title><link>https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF2-2-%E8%82%A9%E8%86%80%E7%AF%87</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E8%BD%AC%E8%BD%BD%E9%81%8A%E6%88%B2%E6%A8%A1%E5%9E%8B%E4%BD%88%E7%B7%9A%E5%B0%8D%E5%8B%95%E4%BD%9C%E8%AE%8A%E5%BD%A2%E4%B9%8B%E5%BD%B1%E9%9F%BF2-2-%E8%82%A9%E8%86%80%E7%AF%87</guid><pubDate>Thu, 05 Dec 2024 05:58:22 GMT</pubDate><content:encoded>&lt;p&gt;转载自 &lt;a href=&quot;https://bida999.pixnet.net/blog/post/24174074&quot;&gt;https://bida999.pixnet.net/blog/post/24174074&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;這次來說說肩膀的部分，肩膀他在人體中是旋轉角度最多的一個地方，所以變形的範圍變化也會比較大，因此模型佈線的正確性就關係到變形的好壞，而連續邊(Edge Loop)將會是肩膀&lt;/p&gt;
&lt;p&gt;佈線的主要原則。&lt;/p&gt;
&lt;p&gt;首先我們要確認肩膀起始的位置上有連續邊(Edge Loop淺藍線)&lt;br /&gt;
，因為之後我們要用這個連續邊作Exturd的動作產生另一個&lt;br /&gt;
連續邊**（圖**&lt;strong&gt;1*&lt;/strong&gt;*）**。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161000.png&quot; alt=&quot;Pasted image 20240406161000.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;**就肩膀的模型佈線來說，需要注意的地方有：（圖**&lt;strong&gt;2）&lt;br /&gt;
1*&lt;/strong&gt;*、**就正面來說，保持兩條連續邊（藍色線段）可以讓手臂在做&lt;br /&gt;
     前後左右旋轉時，在內彎時都有相同的變形效果，這就跟前     幾篇說的內彎要有兩條線是一樣的道理。&lt;br /&gt;
&lt;strong&gt;2**&lt;/strong&gt;、**因為大部分時間手臂都是向下，為了能讓三角肌的剪影看起來&lt;br /&gt;
     更為順暢，在橫向的連續邊上（紅色線段）可以依據需求增加。&lt;br /&gt;
&lt;strong&gt;3*&lt;/strong&gt;*、**因為肩膀的旋轉範圍很大，所以在變形處的模型佈線上多利用&lt;br /&gt;
     三芒或是五芒星來完成四角面的佈線，儘量不要做成三角面，     以防止在動作時產生奇怪的黑影或變形。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161013.png&quot; alt=&quot;Pasted image 20240406161013.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再利用動作及權重分配來檢查變形上的問題，基本上只要佈線&lt;br /&gt;
正確，都可以做出平順及正確的變形（圖3）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161022.png&quot; alt=&quot;Pasted image 20240406161022.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有一點要注意的，大部分人在製作抬手臂這個動作時，都會忽略&lt;br /&gt;
鎖骨這塊位置的旋轉，因此抬手的時候，手臂是離頭部會有段距離&lt;br /&gt;
大家可以自己對著鏡子抬手臂試試看，基本上鎖骨是會自然被帶上&lt;br /&gt;
去的**（圖**&lt;strong&gt;4*&lt;/strong&gt;*）**。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020240406161031.png&quot; alt=&quot;Pasted image 20240406161031.png&quot; /&gt;&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>Tauri first touch 1</title><link>https://powdered-delta.github.io/posts/tauri-first-touch-1</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/tauri-first-touch-1</guid><pubDate>Mon, 10 Feb 2025 16:55:12 GMT</pubDate><content:encoded>&lt;p&gt;Tauri + Nuxt 踩坑全流程&lt;/p&gt;
&lt;p&gt;首先打开tauri 官网&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tauri.app/&quot;&gt;https://tauri.app/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;文档指出需要先安装前置&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tauri.app/start/prerequisites/&quot;&gt;https://tauri.app/start/prerequisites/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;还需要安装 RUST
&lt;a href=&quot;https://www.rust-lang.org/zh-CN/tools/install&quot;&gt;https://www.rust-lang.org/zh-CN/tools/install&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250415203307.png&quot; alt=&quot;Pasted image 20250415203307.png&quot; /&gt;
直接选1 进行默认安装&lt;/p&gt;
&lt;p&gt;注意设置RUST默认工具链
rustup default stable-msvc&lt;/p&gt;
&lt;p&gt;由于涉及到前端开发，还需要安装Node
推荐选中LTS版本，但是我没装NVM，所以先暂时不切换版本，目前使用版本为 v23.5.0&lt;/p&gt;
&lt;p&gt;&lt;code&gt;npm create tauri-app@latest&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;报错&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
? Project name (tauri-app) › error: IO error: 函数不正确。 (os error 1): 函数不正确。 (os error 1)
npm error code 1
npm error path E:\Projects\WEB_PROJECTS\Tauri
npm error command failed
npm error command C:\WINDOWS\system32\cmd.exe /d /s /c create-tauri-app
npm error A complete log of this run can be found in: C:\Users\user\AppData\Local\npm-cache\_logs\2025-04-15T16_11_04_521Z-debug-0.log

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git bash 会报错
换用 PowerShell 即可正常运行&lt;/p&gt;
&lt;p&gt;成功创建项目&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>混元系列模型本地部署测试</title><link>https://powdered-delta.github.io/posts/%E6%B7%B7%E5%85%83%E7%B3%BB%E5%88%97%E6%A8%A1%E5%9E%8B%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2%E6%B5%8B%E8%AF%95</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E6%B7%B7%E5%85%83%E7%B3%BB%E5%88%97%E6%A8%A1%E5%9E%8B%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2%E6%B5%8B%E8%AF%95</guid><pubDate>Fri, 21 Feb 2025 08:01:18 GMT</pubDate><content:encoded>&lt;p&gt;参考：
&lt;a href=&quot;https://blog.csdn.net/qunfang960871/article/details/144906063&quot;&gt;https://blog.csdn.net/qunfang960871/article/details/144906063&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;混元 video 本地部署&lt;/h2&gt;
&lt;p&gt;conda  切换到 hunyuan 环境 （conda安装: /posts/conda-新建切换-虚拟环境）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conda activate HunyuanVideo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装
pip3 install -r .\requirements.txt -i &lt;a href=&quot;https://pypi.tuna.tsinghua.edu.cn/simple&quot;&gt;https://pypi.tuna.tsinghua.edu.cn/simple&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在 custom_nodes 目录下分别安装依赖
git clone &lt;a href=&quot;https://github.com/kijai/ComfyUI-HunyuanVideoWrapper.git&quot;&gt;https://github.com/kijai/ComfyUI-HunyuanVideoWrapper.git&lt;/a&gt;
git clone &lt;a href=&quot;https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git&quot;&gt;https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载视频模型的fp8量化版本:
&lt;a href=&quot;https://www.modelscope.cn/models/Kijai/HunyuanVideo_comfy/files&quot;&gt;https://www.modelscope.cn/models/Kijai/HunyuanVideo_comfy/files&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;模型名称分别是：hunyuan_video_720_cfgdistill_fp8_e4m3fn.safetensors 和 hunyuan_video_vae_bf16.safetensors&lt;/p&gt;
&lt;p&gt;删除CPU版本 torch 重新下载对应 whl
&lt;a href=&quot;https://blog.csdn.net/m0_74890428/article/details/130184164&quot;&gt;https://blog.csdn.net/m0_74890428/article/details/130184164&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250220230453.png&quot; alt=&quot;Pasted image 20250220230453.png&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;混元 3D 本地部署&lt;/h2&gt;
&lt;p&gt;模型仓库
&lt;a href=&quot;https://huggingface.co/Kijai/Hunyuan3D-2_safetensors/tree/main&quot;&gt;https://huggingface.co/Kijai/Hunyuan3D-2_safetensors/tree/main&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载指定版本的 pytorch
&lt;a href=&quot;https://download.pytorch.org/whl/torch_stable.html&quot;&gt;https://download.pytorch.org/whl/torch_stable.html&lt;/a&gt;
cu 为cuda版本  cp为python 版本号&lt;/p&gt;
&lt;p&gt;cu102/torch-1.7.1-cp38-cp38-linux_x86_64.whl&lt;/p&gt;
&lt;p&gt;cu102:表示cuda版本为10.2，&lt;br /&gt;
torch-1.7.1:表示torch版本为1.7.1&lt;br /&gt;
cp38:表示适用python版本为3.8&lt;br /&gt;
linux:表示适用于linux系统&lt;br /&gt;
x86_64:表示同时兼容32和64位系统、&lt;/p&gt;
&lt;p&gt;选择了&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://download.pytorch.org/whl/cu121/torch-2.3.1%2Bcu121-cp310-cp310-win_amd64.whl&quot;&gt;cu121/torch-2.3.1%2Bcu121-cp310-cp310-win_amd64.whl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;该版本进行下载&lt;/p&gt;
&lt;p&gt;根据 目录下的
需要重建为 py 3.12 + cuda 126 环境
&lt;a href=&quot;https://developer.nvidia.com/cuda-12-6-3-download-archive?target_os=Windows&amp;amp;target_arch=x86_64&amp;amp;target_version=10&amp;amp;target_type=exe_local&quot;&gt;https://developer.nvidia.com/cuda-12-6-3-download-archive?target_os=Windows&amp;amp;target_arch=x86_64&amp;amp;target_version=10&amp;amp;target_type=exe_local&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;创建新的 conda 环境&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conda create -n Hunyuan3D python==3.12
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;D:\ComfyUI\ComfyUI\custom_nodes\ComfyUI-Hunyuan3DWrapper&amp;gt;&lt;/p&gt;
&lt;p&gt;pip3 install -r .\requirements.txt -i &lt;a href=&quot;https://pypi.tuna.tsinghua.edu.cn/simple&quot;&gt;https://pypi.tuna.tsinghua.edu.cn/simple&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;pip install .\wheels\custom_rasterizer-0.1.0+torch260.cuda126-cp312-cp312-win_amd64.whl&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>记录一个有趣的盾牌绑手方案</title><link>https://powdered-delta.github.io/posts/%E8%AE%B0%E5%BD%95%E4%B8%80%E4%B8%AA%E6%9C%89%E8%B6%A3%E7%9A%84%E7%9B%BE%E7%89%8C%E7%BB%91%E6%89%8B%E6%96%B9%E6%A1%88</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E8%AE%B0%E5%BD%95%E4%B8%80%E4%B8%AA%E6%9C%89%E8%B6%A3%E7%9A%84%E7%9B%BE%E7%89%8C%E7%BB%91%E6%89%8B%E6%96%B9%E6%A1%88</guid><pubDate>Fri, 04 Jul 2025 08:01:58 GMT</pubDate><content:encoded>&lt;p&gt;在帮朋友做鸢盾型道具时查到一个很有意思的绑手分布方案 &lt;a href=&quot;https://youtu.be/D-_xHDvdSLw&quot;&gt;https://youtu.be/D-_xHDvdSLw&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250714145035.png&quot; alt=&quot;Pasted image 20250714145035.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250714145530.png&quot; alt=&quot;Pasted image 20250714145530.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;在此基础上受到启发，进行了一些修改（示意图）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250901201414.png&quot; alt=&quot;Pasted image 20250901201414.png&quot; /&gt;&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item><item><title>一般图片转换至 Wplace 可用的小尺寸像素图的部分方案（仅自用思路，不保证最优）</title><link>https://powdered-delta.github.io/posts/%E4%B8%80%E8%88%AC%E5%9B%BE%E7%89%87%E8%BD%AC%E6%8D%A2%E8%87%B3-wplace-%E5%8F%AF%E7%94%A8%E7%9A%84%E5%B0%8F%E5%B0%BA%E5%AF%B8%E5%83%8F%E7%B4%A0%E5%9B%BE%E7%9A%84%E9%83%A8%E5%88%86%E6%96%B9%E6%A1%88%E4%BB%85%E8%87%AA%E7%94%A8%E6%80%9D%E8%B7%AF%E4%B8%8D%E4%BF%9D%E8%AF%81%E6%9C%80%E4%BC%98</link><guid isPermaLink="true">https://powdered-delta.github.io/posts/%E4%B8%80%E8%88%AC%E5%9B%BE%E7%89%87%E8%BD%AC%E6%8D%A2%E8%87%B3-wplace-%E5%8F%AF%E7%94%A8%E7%9A%84%E5%B0%8F%E5%B0%BA%E5%AF%B8%E5%83%8F%E7%B4%A0%E5%9B%BE%E7%9A%84%E9%83%A8%E5%88%86%E6%96%B9%E6%A1%88%E4%BB%85%E8%87%AA%E7%94%A8%E6%80%9D%E8%B7%AF%E4%B8%8D%E4%BF%9D%E8%AF%81%E6%9C%80%E4%BC%98</guid><pubDate>Tue, 26 Aug 2025 13:44:45 GMT</pubDate><content:encoded>&lt;h2&gt;方案1&lt;/h2&gt;
&lt;h3&gt;先用ps 将图片轮廓提取&lt;/h3&gt;
&lt;p&gt;原图
&lt;img src=&quot;images/Pasted%20image%2020250902141625.png&quot; alt=&quot;Pasted image 20250902141625.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;提取轮廓：
&lt;img src=&quot;images/Pasted%20image%2020250902142625.png&quot; alt=&quot;Pasted image 20250902142625.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;通过色阶滤镜等调整使轮廓变清晰，顺便清理掉缩小图片后影响轮廓的细节&lt;/h3&gt;
&lt;p&gt;处理后：
&lt;img src=&quot;images/Pasted%20image%2020250902143324.png&quot; alt=&quot;Pasted image 20250902143324.png&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;将处理好的线稿中的白色去除为透明色，线条部分加深&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;通过魔棒【非连续】 选择图片白色区域， delete 删除白色区域，右键反选选区，然后用轮廓色画笔多涂涂就能出效果
处理完后效果如下(此处尽量不要用太黑的颜色)：
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;images/%E7%BA%BF%E7%A8%BF.png&quot; alt=&quot;线稿.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后将原图部分颜色略微调色以贴近wplace的色号&lt;/p&gt;
&lt;p&gt;然后将图片尺寸修改至想要绘制的像素图尺寸长宽各 &lt;em&gt;2 的尺寸
此例中原图为 828&lt;/em&gt; 1200，缩为 276 * 400
注意这一步不需要使用 邻近/硬边缘 进行重采样。示例中使用的是 保留细节2.0（减少杂色40%）
隐藏线稿图层：
&lt;img src=&quot;images/Pasted%20image%2020250902150806.png&quot; alt=&quot;Pasted image 20250902150806.png&quot; /&gt;
显示线稿图层
&lt;img src=&quot;images/Pasted%20image%2020250902150836.png&quot; alt=&quot;Pasted image 20250902150836.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;此时可以对颜色进行进一步的修改以贴合 wplace 的色板&lt;/p&gt;
&lt;p&gt;当颜色处理完毕后，就可以保存一下文件（注意不要合并图层，&lt;/p&gt;
&lt;p&gt;接下来的步骤换到 &lt;a href=&quot;https://www.aseprite.org/&quot;&gt;aseprite&lt;/a&gt; 操作(此软件有售卖版和社区版（需自行打包或者用别人打包成品
注意不要下官网的试用版，无法保存文件的（虽然可以复制图层回ps操作&lt;/p&gt;
&lt;p&gt;然后将ps改好的图放到aseprite中，使用aseprite缩放成138 * 200 后
再在aseprite中 导入色板：
&lt;img src=&quot;images/Pasted%20image%2020250902153004.png&quot; alt=&quot;Pasted image 20250902153004.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;加载对应 &lt;code&gt;wplace 颜色&lt;/code&gt; 的调色板
随后将图片的颜色模式改为索引（注意只保留合并线稿后的图像
不要使用索引直接修改，在更多选项里面进行调整&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250902153229.png&quot; alt=&quot;Pasted image 20250902153229.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;更多选项中可以调整抖动类型和映射类型（映射算法可能不太适合wplace，所以可能需要返工到ps里面手动调一下色相，此处演示就不折腾了&lt;/p&gt;
&lt;h4&gt;参数组合展示（附原图对比&lt;/h4&gt;
&lt;p&gt;默认参数：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250902153638.png&quot; alt=&quot;Pasted image 20250902153638.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;无抖动+rgb
&lt;img src=&quot;images/Pasted%20image%2020250902153705.png&quot; alt=&quot;Pasted image 20250902153705.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;无抖动+线性化RGB：
&lt;img src=&quot;images/Pasted%20image%2020250902153554.png&quot; alt=&quot;Pasted image 20250902153554.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;无抖动+CIEXYZ
&lt;img src=&quot;images/Pasted%20image%2020250902153755.png&quot; alt=&quot;Pasted image 20250902153755.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有序抖动 2 * 2 + 线性化RGB
&lt;img src=&quot;images/Pasted%20image%2020250902153915.png&quot; alt=&quot;Pasted image 20250902153915.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;有序抖动 4 * 4 + 线性化RGB
&lt;img src=&quot;images/Pasted%20image%2020250902153823.png&quot; alt=&quot;Pasted image 20250902153823.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;旧式抖动4 * 4 + 线性化RGB&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;images/Pasted%20image%2020250902153940.png&quot; alt=&quot;Pasted image 20250902153940.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;其他组合就不一一展示了， 总之最好是用无抖动算法出面部，手动抖动一下&lt;/p&gt;
&lt;p&gt;然后背景/衣物选择合适的抖动算法，最后再把几张图合并并且统一颜色拼好图，就能得到一张差不多的模板，然后手动修图去一下明显的杂色，绘制的时候再看情况稍微修一下图即可&lt;/p&gt;
</content:encoded><author>M0e_N00b</author></item></channel></rss>