Skip to content

着色器(光影)Shader

本页面镜像自
BedrockWiki

根据原始项目协议授权。本文经过AI翻译处理,如有内容遗漏,可以提交PR进行补充。

WARNING

本页所述的着色器与Render Dragon渲染引擎不兼容。这意味着在1.16.200版本后的Windows和主机设备,以及1.18.30版本后的其他设备上无法使用!

概述

着色器分为glslhlsl两个文件夹。要使着色器在所有设备上生效,需要同时用两种语言编写代码。在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颜色源混合因子计算方式OneOpenGL实现中对应glBlendFunc调用
blendDst颜色目标混合因子计算方式OneOpenGL实现中对应glBlendFunc调用

示例:

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模式

疑难解答

着色器未生效

每次修改着色器后,必须重启Minecraft才能完全重新编译着色器。

编译错误

出现编译错误时,错误信息中的行号可能需要检查前几行的代码,因为Minecraft会在编译前自动添加#define指令。

找不到名为$Globals的常量缓冲区

此错误可能与全局变量相关。尝试通过以下方式解决:

  • main函数中初始化变量
  • 改用#define指令定义常量

实用技巧

向着色器传递变量

通过修改实体颜色可将数据传入着色器。输入值会被限制在<0.0, 1.0>范围内。传递较大数值时建议先进行归一化处理。

使用时间变量

全局TIME变量存储以秒为单位的浮点时间值。要获取基于粒子生命周期的计时器:

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;
  1. 在顶点着色器中添加:
PSInput.viewDir = normalize((mul(WORLD, mul(BONES[VSInput.boneId], float4(VSInput.position, 1)))).xyz);
  1. 在片段着色器中使用PSInput.viewDir控制渲染逻辑

调试技巧

将调试值转换为颜色输出是最直观的方式:

hlsl
PSOutput.color = float4(PSInput.uv, 0., 1.);

这会生成红绿渐变,显示UV坐标范围。推荐使用调试着色器,修改HLSL第70行代码可显示不同变量:

hlsl
int ascii = getFloatCharacter( cellIndex, <需要显示的向量> );

注意:GLSL版调试着色器可能导致崩溃,建议仅用于调试。

调试着色器演示