Files
netease-modsdk-wiki/docs/wiki/concepts/shaders.md
2025-03-20 00:13:44 +08:00

162 lines
8.5 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: Shaders
mentions:
- SirLich
- Dreamedc2015
- yanasakana
- MedicalJewel
- SIsilicon
---
:::warning
The shaders on this page are incompatible with [Render Dragon](https://help.minecraft.net/hc/en-us/articles/360052771272-About-the-1-16-200-Update-for-Windows-10-). That means that they will not work on Windows and Console devices past 1.16.200, nor other devices past 1.18.30!
:::
## Overview
Shaders are divided into 2 folders: `glsl` and `hlsl`. For shaders to work on every device,
you need to code shaders in both languages. For testing on Windows, `hlsl` is enough.
When rewriting shaders from one language to another, there are few things to change,
like HLSL `float3` is `vec3` in GLSL. Mapping between those languages can be found [here](https://anteru.net/blog/2016/mapping-between-HLSL-and-GLSL/)
## Materials
Vertex, fragments, and sometimes geometry shaders are combined with some options
as materials and are required for custom shaders. To create new material,
you need to create a file, which matches the name of the .material file in the vanilla resource pack.
For example: `materials/particles.material`. Materials support inheritance by adding parent
material after a colon. For example: `entity_alpha:entity_base`
### Common material definition fields
| **Field name** | **Description** | **Example value** | **Notes** |
| ---------------- | --------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vertexShader` | Path to the shader relative to hlsl/glsl folder | | For HLSL shader, `.hlsl` suffix is added. |
| `fragmentShader` | Path to the shader relative to hlsl/glsl folder | | For HLSL shader, `.hlsl` suffix is added. |
| `vertexFields` | An array of fields passed to vertex shader | | It's better to copy this field from vanilla material. |
| `variants` | An array of objects, which define variants of the material | | It's better to copy this field from vanilla material. |
| `+defines` | An array of `#define` directives to add to the shader source | | Useful for reusing shader, but changing some minor setting. |
| `+states` | An array of states to enable | `["Blending", "DisableAlphaWrite", "DisableDepthWrite"]` | For OpenGL implementation, this is equivalent to [glEnable](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEnable.xml) call. |
| `-defines` | An array of `#defines` directives to remove from inherited `+defines` | | |
| `+samplerStates` | An array of objects, defining how texture at certain index is treated | `{ "samplerIndex": 0, "textureFilter": "Point" }` | `textureFilter` specifies how to sample the texture and `textureWrap` specifies the behavior, when accessing outside of the texture dimensions. |
| `msaaSupport` | Multisample anti-aliasing support | `Both` | |
| `blendSrc` | Specifies how the color source blending factors are computed | `One` | For OpenGL implementation, this is equivalent to [glBlendFunc](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml) call. |
| `blendDst` | Specifies how the color destination blending factors are computed | `One` | For OpenGL implementation, this is equivalent to [glBlendFunc](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml) call. |
Example:
<CodeHeader></CodeHeader>
```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"
}
}
}
```
For all the details about material files and possible field values, check [material file JSON schema](https://github.com/stirante/bedrock-shader-schema/blob/master/materials.schema.json).
## Troubleshooting
### Shader doesnt change
Every time there is a change in the shader, you need to restart Minecraft to recompile the shader completely.
### Compilation error
When there is a shader compilation error, a line number is usually specified where the error occurred. You need to check a few lines above the one set in error because Minecraft adds `#define` directives before compilation.
### Couldnt find constant buffer named: $Globals
I couldnt accurately find the actual cause of this error, but it seems to be somehow connected to global variables. Removing them (initializing them in the `main` function or changing them to `#define` directives) seems to fix the problem.
## Tips and tricks
### Passing variables to the shader
You can pass variables to the shader from a particle or an entity by changing entity color.
Input color is clamped to `<0.0, 1.0>`. To pass more significant values, you need to divide by max value (or at least some considerable number).
### Using time in shader
`TIME` variable is a number of seconds as `float` and is global for all shaders. For time-based on particle lifetime, you need to pass this:
<CodeHeader></CodeHeader>
```json
"minecraft:particle_appearance_tinting": {
"color": ["variable.particle_age/variable.particle_lifetime", 0, 0, 1]
}
```
Then in the shader, use `PSInput.color.r` as time, where `0.0` is particle birth and `1.0` is particle death.
### Camera direction towards the entity
For entity shaders, you can make the shader dependent on the camera direction towards the entity.
- Add to `PS_Input` in vertex and fragment shader new field
<CodeHeader></CodeHeader>
```
float3 viewDir: POSITION;
```
- After that, add to vertex shader this line
<CodeHeader></CodeHeader>
```
PSInput.viewDir = normalize((mul(WORLD, mul(BONES[VSInput.boneId], float4(VSInput.position, 1)))).xyz);
```
- In the fragment shader, use `PSInput.viewDir` to make changes depending on camera rotation
### Debugging values
The easiest way to debug a value is to turn it into color and render it like this.
<CodeHeader></CodeHeader>
```
PSOutput.color = float4(PSInput.uv, 0., 1.);
```
This should create a red-green gradient, showing that the values of `uv` are between `<0, 0>` and `<1, 1>`.
You can use the debug shader I wrote [based on this shader](http://mew.cx/drawtext/drawtext).
Right now, this shader will display values of the color passed to the shader. To display another value, change line 70 in hlsl shader to
<CodeHeader></CodeHeader>
```
int ascii = getFloatCharacter( cellIndex, <float4 vector here> );
```
GLSL version of debugging shader may crash Minecraft, use only for debugging.
[Download debug shader](http://files.stirante.com/debugShader.zip)
![](/assets/images/knowledge/shaders/debugShader.gif)