-
Notifications
You must be signed in to change notification settings - Fork 26
Shader Compatibility. (For Shader Dev)
This is a guide for shader dev who wants to make shader packs work compatible with shimmer
also, this will mention some principles about how shimmer works
Please note that all this is not the final docs, and please don't treat this as a formal version
All is still alpha
Block/Fluid Bloom and colored Light, but all this should be done by you, the shader dev
shimmer which includes this ability is still work in progress
we can find a jar for a test at GitHub action on brach iris-comp
like here https://github.com/Low-Drag-MC/Shimmer/actions/runs/5726699796
and alpha version release at modrinth and curseforge, Shimmer 1.20.1-0.1.19
this article will use glsl version at least 150 and will only show the basic way
I am just a modder dev, not a shader dev. I am not good at writing fantasy shader stuff
for shader dev to make code can work both under shimmer and without shimmer, shimmer will make iris
insert another macro shimmer_installed
, an example usage is like this
#ifdef shimmer_installed
//code when shimmer is installed
#else
//code when shimmer is not installed
#endif
as we all know, Minecraft introduces a type of shader called core shader
In that kind of vertex shader, we can receive all available vertex information
when render by vanilla, shimmer will patch the vertex data transformed to shader
Minecraft use in ivec2 UV2
to represent light information, the core point is at there
Minecraft only has both 16 different light levels for block light and daylight, only 8bit data is enough
so, shimmer uses some unused bit to indicate whether the vertex should be bloom or not
under sodium and iris, this works similarly
gbuffers_terrain.vsh
#version 150
//in vsh
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix = mat4(1.0);
uniform vec3 chunkOffset;
in ivec2 vaUV2;
in vec2 vaUV0;
in vec3 vaPosition;
in vec4 vaColor;
out vec2 lmcoord;
out vec2 texcoord;
out vec4 tint;
#ifdef shimmer_installed
out float isBloom; // look at there
#endif
void main() {
gl_Position = projectionMatrix * (modelViewMatrix * vec4(vaPosition + chunkOffset, 1.0));
texcoord = (textureMatrix * vec4(vaUV0, 0.0, 1.0)).xy;
lmcoord = vaUV2 * (1.0 / 256.0) + (1.0 / 32.0);
tint = vaColor;
#ifdef shimmer_installed
if((vaUV2.x & 0x100) != 0) {
isBloom = 100.0;
} else {
isBloom = 0.0;
}
#endif
}
just make vaUV2.x & 0x100 !=0
, and we can know if this vertex should be bloom or not
just make a simple test usage fsh
gbuffers_terrain.fsh
#version 150
#extension GL_ARB_explicit_attrib_location : enable
uniform float alphaTestRef;
uniform sampler2D gtexture;
uniform sampler2D lightmap;
in vec2 lmcoord;
in vec2 texcoord;
in vec4 tint;
#ifdef shimmer_installed
in float isBloom;
#endif
/* DRAWBUFFERS:0 */
layout(location = 0) out vec4 colortex0Out;
void main() {
vec4 color = texture(gtexture, texcoord) * tint;
if (color.a < alphaTestRef) discard;
color *= texture(lightmap, lmcoord);
colortex0Out = color;
#ifdef shimmer_installed
if (isBloom > 99.0) {
colortex0Out *= vec4(1.0,0.0,0.0,0.0);
}
#endif
}
under vanilla and sodium
under simple test shader pack
though the visual effect is not good, we can find that all vertex should be blom is tinted red, as the code writes
the code example code is not so perfect, just a principle show.
For example, we can try to use some built-in glsl functions to avoid the if statement for better performance.
And if you just write code my way. Please note that in vsh we set 100.0
but in fsh we check > 99.0
this is import, don't use == 100
this is more complex, first of all, we need to use ShaderStorageBufferObject
some shaderpacks may still use #version 120
for compatibility,if you don't want to change to #version 150
and above
you can use syntax like this #extension GL_ARB_shader_storage_buffer_object : require
, this will help you
in the shaders.properties
file, we need to write things like this
iris.features.required = ssbo
bufferObject.0 = 65536
bufferObject.1 = 32
shimmer.config.lights = 0
shimmer.config.env = 1
the first three lines is for iris, you can find their wiki for the detailed explanation, just note that
you must use SSBO from 0 to the maximum you want to use, don't skip one of them, you can find a detailed explanation here
Also, the size should be at least the number written above
Then, the last two lines will been read by shimmer, the content before =
is fixed, and the content after =
should correspond with the SSBO index set before
from the buffer above, we can find that shimmer will provide two SSBO, one is called lights and another is env, code can explain them more precisely
#ifdef shimmer_installed
struct Light {
//formatted in r g b a
vec4 color;
//the color's source's position, based on Minecraft's world size
//which means if the position is easy to BlockPos, the same value you can see in f3 debug screen
vec3 position;
float radius;
};
//shimmer support at most 2048 light source
//note: don't read them arbitrarily, they are not initiated, we may read garbage data
layout (std140, binding = 0) buffer LightBuffer {
Light lights[2048]; //64MB total
};
//indicates how many lights to use, use this as an index to read lights safely
layout (std140, binding = 1) buffer EnvBuffer {
//uv light is a concept in shimmer, we can not take care of them just use uvLightCout+nouvLightCout as an index
//this kind of light should take Minecraft's original light level into consideration
int uvLightCout; //32 bytes total
//this kind of light shouldn't take Minecraft's original light level into consideration
int nouvLightCout;
//the camera's BlockPos, same in f3 debug screen, just for shimmer to work under vanilla and sodium
//you can ignore this and use uniform provided by iris
vec3 camPos;
};
#endif
SSBO bind
SSBO env info
SSBO lights info