Skip to content

ExtendedShader

Since 2.0.0

Before reading this page, make sure you understand Minecraft Core Shader.

Photon2 and LDLib2 extend vanilla shaders with ExtendedShader, adding:

  • Geometry shader (attach) support
  • Extra samplers and uniforms

📦 How to Use

ExtendedShader JSON is almost the same as Vanilla.
Here’s an example using Texture Material.

json
{
    "vertex": "photon:particle",
    /*
        "geometry": "<namespace>:<name>.gsh" // (1)
    */
    "fragment": "photon:hdr_particle",
    "samplers": [
        { "name": "Sampler2" },
        // custom samplers
        { "name": "Texture" }
    ],
    "uniforms": [
        { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] },
        { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] },
        { "name": "ColorModulator", "type": "float", "count": 4, "values": [1,1,1,1] },
        { "name": "FogStart", "type": "float", "count": 1, "values": [0.0] },
        { "name": "FogEnd", "type": "float", "count": 1, "values": [1.0] },
        { "name": "FogColor", "type": "float", "count": 4, "values": [0,0,0,0] },
        { "name": "FogShape", "type": "int", "count": 1, "values": [0] },
        // custom uniforms
        { "name": "DiscardThreshold", "type": "float", "count": 1, "values": [0.01] },
        { "name": "HDR", "type": "float", "count": 4, "values": [0,0,0,1] },
        { "name": "HDRMode", "type": "int", "count": 1, "values": [0] }
    ]
}
  1. Attach geometry shader if needed.

Difference from vanilla particle shader:

  • In the particle.vsh tab, use #moj_import &lt;photon:particle.glsl&gt; and getParticleData() to fetch vertex data.
  • In the hdr_particle.fsh tab, added HDR color output.

🎯 Handle Vertex Data

Different FX objects and renderer settings (e.g., GPU Instance, Additional GPU Data) can change vertex type and layout.

Photon2 provides a helper library that, through macros, automatically parses and converts input vertex data into an accessible format.

More info: Vertex Format

glsl
// Requires GLSL version 330+
#version 330 core

/*
struct ParticleData {
    vec3 Position;
    vec4 Color;
    vec2 UV;
    ivec2 LightUV;
    vec3 Normal;
};

ParticleData getParticleData() {
    // (1)
}
*/

void main() {
    ParticleData data = getParticleData();
    vec3 position = data.Position;
    vec4 color = data.Color;
    vec2 uv = data.UV;
    ivec2 lightUV = data.LightUV;
    vec3 normal = data.Normal;
}
  1. Internal Implementation, check Vertex Format for details.

Implementation Details

In vertex shader:

  1. Ensure #version is 330 or higher.
  2. Import Photon2 vertex library: #moj_import &lt;photon:particle.glsl&gt;
  3. Access data via getParticleData() — no need to handle internal layouts manually.
  4. Photon2 supports passing extra GPU vertex data (e.g., particle lifetime, velocity). See: Additional GPU Data

🎨 Extended Samplers

Photon2 provides extra built-in samplers beyond vanilla. When declared in JSON, these samplers won’t appear in the Inspector.

Sampler NameDescriptionPreview
Sampler2Light MapLight Map
SamplerSceneColorWorld ColorWorld Color
SamplerSceneDepthWorld DepthWorld Depth
SamplerCurveCurve Sampler-
SamplerGradientGradient Sampler-

📈 SamplerCurve / SamplerGradient

Curve & Gradient

Special samplers, active only if a Curve or Gradient is assigned. Photon2 encodes them into a 128×128 texture for sampling in shader.

glsl
#moj_import <photon:particle_utils.glsl>
/* internal implementation
const float INV_TEX_SIZE = 1.0 / 128.0;
const float MAX_U = 1.0 - 0.5 * INV_TEX_SIZE;

float getCurveValue(sampler2D curveTexture, int curveIndex, float x) {
    return texture(curveTexture, vec2(clamp(x, 0.0, MAX_U), (float(curveIndex) + 0.5) * INV_TEX_SIZE)).r;
}

vec4 getGradientValue(sampler2D gradientTexture, int gradientIndex, float x) {
    return texture(gradientTexture, vec2(clamp(x, 0.0, MAX_U), (float(gradientIndex) + 0.5) * INV_TEX_SIZE));
}
*/

uniform sampler2D SamplerCurve;
uniform sampler2D SamplerGradient;

void main() {
    float value = getCurveValue(SamplerCurve, 0, x);
    vec4 color = getGradientValue(SamplerGradient, 0, x);
}

Use:

  • Import helpers:

    glsl
    #moj_import <photon:particle_utils.glsl>
  • Call getCurveValue() and getGradientValue() to retrieve values.


🛠 Extended Uniforms

Photon2 adds more built-in uniforms on top of vanilla core shaders.


📋 Vanilla Built-in Uniforms

NameTypeDescription
ModelViewMatmat4Model-view matrix
ProjMatmat4Orthographic projection matrix (width=window, height=window, near=0.1, far=1000)
ScreenSizevec2Framebuffer width & height (pixels)
ColorModulatorvec4Final color multiplier
FogColorvec4Fog color & density (alpha = density)
FogStartfloatFog start distance
FogEndfloatFog end distance
FogShapeintFog mode
GameTimefloatNormalized day time (0–1, loops every 20min)
GlintAlphafloatGlint strength (0–1)

📋 Photon2 Built-in Uniforms

NameTypeDescription
U_CameraPositionvec3Camera world position
U_InverseProjectionMatrixmat4Precomputed inverse ProjMat
U_InverseViewMatrixmat4Precomputed inverse ModelViewMat
U_ViewPortvec4ViewPort(x, y, w, h) since 2.1.3.a

Released under the MIT License.