Files
netease-modsdk-wiki/docs/wiki/concepts/shaders.md
2025-03-20 11:52:46 +08:00

148 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 着色器(光影)
mentions:
- SirLich
- Dreamedc2015
- yanasakana
- MedicalJewel
- SIsilicon
---
# 着色器光影Shader
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
:::warning
本页所述的着色器与[Render Dragon](https://help.minecraft.net/hc/en-us/articles/360052771272-About-the-1-16-200-Update-for-Windows-10-)渲染引擎不兼容。这意味着在1.16.200版本后的Windows和主机设备以及1.18.30版本后的其他设备上无法使用!
:::
## 概述
着色器分为`glsl``hlsl`两个文件夹。要使着色器在所有设备上生效需要同时用两种语言编写代码。在Windows平台测试时使用`hlsl`即可。在两种语言间转换时需要注意语法差异例如HLSL中的`float3`对应GLSL中的`vec3`。[此处](https://anteru.net/blog/2016/mapping-between-HLSL-and-GLSL/)可查看两种语言的对照表。
## 材质
顶点着色器、片段着色器和几何着色器(可选)通过材质配置文件组合使用。创建新材质时,需要参照原版资源包中的`.material`文件命名。例如:`materials/particles.material`。材质支持继承机制,使用冒号语法:`entity_alpha:entity_base`
### 通用材质定义字段
| **字段名称** | **描述** | **示例值** | **注意事项** |
| ------------------ | ----------------------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `vertexShader` | 顶点着色器路径相对于hlsl/glsl文件夹 | | HLSL着色器会自动添加`.hlsl`后缀 |
| `fragmentShader` | 片段着色器路径相对于hlsl/glsl文件夹 | | HLSL着色器会自动添加`.hlsl`后缀 |
| `vertexFields` | 传递给顶点着色器的字段数组 | | 建议从原版材质中复制此字段 |
| `variants` | 定义材质变体的对象数组 | | 建议从原版材质中复制此字段 |
| `+defines` | 添加到着色器源码的`#define`指令数组 | | 适用于复用着色器时调整细节参数 |
| `+states` | 启用的渲染状态数组 | `["Blending", "DisableAlphaWrite", "DisableDepthWrite"]` | OpenGL实现中对应[glEnable](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEnable.xml)调用 |
| `-defines` | 从继承的`+defines`中移除的指令数组 | | |
| `+samplerStates` | 定义纹理采样方式的对象数组 | `{ "samplerIndex": 0, "textureFilter": "Point" }` | `textureFilter`指定采样方式,`textureWrap`定义纹理边界外访问行为 |
| `msaaSupport` | 多重采样抗锯齿支持 | `Both` | |
| `blendSrc` | 颜色源混合因子计算方式 | `One` | OpenGL实现中对应[glBlendFunc](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml)调用 |
| `blendDst` | 颜色目标混合因子计算方式 | `One` | OpenGL实现中对应[glBlendFunc](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml)调用 |
示例:
::: code-group
```json [材质示例]
{
"materials": {
"version": "1.0.0",
"particle_debug": {
"vertexShader": "shaders/particle_generic.vertex",
"fragmentShader": "shaders/particle_debug.fragment",
"vertexFields": [
{ "field": "Position" },
{ "field": "Color" },
{ "field": "UV0" }
],
"+samplerStates": [
{
"samplerIndex": 0,
"textureFilter": "Point"
}
],
"msaaSupport": "Both"
}
}
}
```
:::
完整材质文件规范请参考[材质文件JSON模式](https://github.com/stirante/bedrock-shader-schema/blob/master/materials.schema.json)。
## 疑难解答
### 着色器未生效
每次修改着色器后必须重启Minecraft才能完全重新编译着色器。
### 编译错误
出现编译错误时错误信息中的行号可能需要检查前几行的代码因为Minecraft会在编译前自动添加`#define`指令。
### 找不到名为$Globals的常量缓冲区
此错误可能与全局变量相关。尝试通过以下方式解决:
- 在`main`函数中初始化变量
- 改用`#define`指令定义常量
## 实用技巧
### 向着色器传递变量
通过修改实体颜色可将数据传入着色器。输入值会被限制在`<0.0, 1.0>`范围内。传递较大数值时建议先进行归一化处理。
### 使用时间变量
全局`TIME`变量存储以秒为单位的浮点时间值。要获取基于粒子生命周期的计时器:
::: code-group
```json [粒子计时器配置]
"minecraft:particle_appearance_tinting": {
"color": ["variable.particle_age/variable.particle_lifetime", 0, 0, 1]
}
```
:::
在着色器中使用`PSInput.color.r`获取时间值,其中`0.0`表示粒子生成,`1.0`表示粒子消亡。
### 相机朝向控制
在实体着色器中实现相机方向相关效果:
1. 在顶点/片段着色器的`PS_Input`结构体添加:
```
float3 viewDir: POSITION;
```
2. 在顶点着色器中添加:
```
PSInput.viewDir = normalize((mul(WORLD, mul(BONES[VSInput.boneId], float4(VSInput.position, 1)))).xyz);
```
3. 在片段着色器中使用`PSInput.viewDir`控制渲染逻辑
### 调试技巧
将调试值转换为颜色输出是最直观的方式:
::: code-group
```hlsl [颜色调试]
PSOutput.color = float4(PSInput.uv, 0., 1.);
```
:::
这会生成红绿渐变显示UV坐标范围。推荐使用[调试着色器](http://files.stirante.com/debugShader.zip)修改HLSL第70行代码可显示不同变量
::: code-group
```hlsl [调试代码]
int ascii = getFloatCharacter( cellIndex, <需要显示的向量> );
```
:::
注意GLSL版调试着色器可能导致崩溃建议仅用于调试。
![调试着色器演示](/assets/images/knowledge/shaders/debugShader.gif)