着色器(光影)Shader
本页面镜像自 BedrockWiki
根据原始项目协议授权。本文经过AI翻译处理,如有内容遗漏,可以提交PR进行补充。
WARNING
本页所述的着色器与Render Dragon渲染引擎不兼容。这意味着在1.16.200版本后的Windows和主机设备,以及1.18.30版本后的其他设备上无法使用!
概述
着色器分为glsl
和hlsl
两个文件夹。要使着色器在所有设备上生效,需要同时用两种语言编写代码。在Windows平台测试时,使用hlsl
即可。在两种语言间转换时需要注意语法差异,例如HLSL中的float3
对应GLSL中的vec3
。此处可查看两种语言的对照表。
材质
顶点着色器、片段着色器和几何着色器(可选)通过材质配置文件组合使用。创建新材质时,需要参照原版资源包中的.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调用 |
-defines | 从继承的+defines 中移除的指令数组 | ||
+samplerStates | 定义纹理采样方式的对象数组 | { "samplerIndex": 0, "textureFilter": "Point" } | textureFilter 指定采样方式,textureWrap 定义纹理边界外访问行为 |
msaaSupport | 多重采样抗锯齿支持 | Both | |
blendSrc | 颜色源混合因子计算方式 | One | OpenGL实现中对应glBlendFunc调用 |
blendDst | 颜色目标混合因子计算方式 | One | OpenGL实现中对应glBlendFunc调用 |
示例:
{
"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模式。
疑难解答
着色器未生效
每次修改着色器后,必须重启Minecraft才能完全重新编译着色器。
编译错误
出现编译错误时,错误信息中的行号可能需要检查前几行的代码,因为Minecraft会在编译前自动添加#define
指令。
找不到名为$Globals的常量缓冲区
此错误可能与全局变量相关。尝试通过以下方式解决:
- 在
main
函数中初始化变量 - 改用
#define
指令定义常量
实用技巧
向着色器传递变量
通过修改实体颜色可将数据传入着色器。输入值会被限制在<0.0, 1.0>
范围内。传递较大数值时建议先进行归一化处理。
使用时间变量
全局TIME
变量存储以秒为单位的浮点时间值。要获取基于粒子生命周期的计时器:
"minecraft:particle_appearance_tinting": {
"color": ["variable.particle_age/variable.particle_lifetime", 0, 0, 1]
}
在着色器中使用PSInput.color.r
获取时间值,其中0.0
表示粒子生成,1.0
表示粒子消亡。
相机朝向控制
在实体着色器中实现相机方向相关效果:
- 在顶点/片段着色器的
PS_Input
结构体添加:
float3 viewDir: POSITION;
- 在顶点着色器中添加:
PSInput.viewDir = normalize((mul(WORLD, mul(BONES[VSInput.boneId], float4(VSInput.position, 1)))).xyz);
- 在片段着色器中使用
PSInput.viewDir
控制渲染逻辑
调试技巧
将调试值转换为颜色输出是最直观的方式:
PSOutput.color = float4(PSInput.uv, 0., 1.);
这会生成红绿渐变,显示UV坐标范围。推荐使用调试着色器,修改HLSL第70行代码可显示不同变量:
int ascii = getFloatCharacter( cellIndex, <需要显示的向量> );
注意:GLSL版调试着色器可能导致崩溃,建议仅用于调试。