Custom Mesh baked in lighting

I’m trying to implement lighting in my Minecraft clone game. Everything I have read about lighting in this type of game suggests “baked in lighting”. I’m not sure how to do that. I know there is a Color buffer that can be set on the mesh but I have not had any luck in setting that and I don’t know how that interacts with the material’s texture. I’m also unsure if I need to use Lighting.j3md or Unshaded.j3md for the material.

I’m not looking for a lighting algorithm, I’ll figure that out once I know how to pass lighting values to JME.

Here are my code snippets of what I have now that I think are relevant. Please let me know if I should include something else:

public class BlockChunk_Material extends Material{

public BlockChunk_Material(AssetManager assetManager, String blockTextureFilePath){
    super(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    Texture texture = assetManager.loadTexture(blockTextureFilePath);
    texture.setMagFilter(Texture.MagFilter.Nearest);
    texture.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
    setTexture("ColorMap", texture);
    getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}

}

    private static Mesh generateMesh(){
    Mesh mesh = new Mesh();
    mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(positions));
    mesh.setBuffer(Type.Index, 1, BufferUtils.createShortBuffer(indices));
    mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
    mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoordinates));
    mesh.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(lighting));
    mesh.updateBound();
    return mesh;
}

I just need a nudge in the right direction here. I have searched and searched and haven’t had much luck.

All help is very appreciated.

Probably you will need your own material if you still want directional (ie: sunlight) style lighting.

Else if you just want purely static lighting then use Unshaded, set a color buffer, and turn vertex colors on for the material. See docs for Unshaded’s material parameters.

1 Like

Thanks @pspeed I got it working. I went with the second option for now since I’ve never created a custom material.

Now the hard part of figuring out a lighting algorithm. :worried:

Why that?
Jme already cares for that?

Take the lighting. J3md and then simply add some lights to your rootNode.

It would be more performant though, if you’d simply use unshaded lights (like have them on all DAY, without daytime and such.)

He wants to propagate lighting like in Minecraft (as stated in the first post) and would like to bake that lighting in (as stated in the first post). This is the more performance option as it can handle an infinite number of lights where as Lighting.j3md will not give you such lighting propagation and will render the scene once per light, limiting the number of lights that one can support.

1 Like

@pspeed if you don’t mind me asking, for Mythruna are you rebuilding the chunk meshes every time lighting changes? Or are you somehow just updating the color buffer?

Also, are there any resources you could suggest for lighting algorithms of this type?

I recalculate it every time since removing/adding a light is also changing the blocks anyway.

The algorithm isn’t hard… it’s like cellular automata or a flood fill. Plop a light value down, plop light value - 1 into all of its neighboring cells, repeat for unvisited cells.

But are you rebuilding the Mesh every time? In other words using new Mesh() or just updating the buffer? Seems like new Mesh() would be expensive considering how much light changes.

Light almost never changes. If you add a torch or remove a torch light changes. Otherwise, the fun is in the shader.

Ok. So day and night, or in general time of day would be best handled in shader?

I guess that’s what you were talking about in your first post. I would have to use a custom material if I wanted directional lighting.

Yep. In that case, your colors would represent ‘local’ lighting (rgb if you want colored lights) and use the alpha value for “sun/moon” brightness. The shader would calculate directional lighting just like Lighting.j3md but then scale it based on the color alpha. You could treat the rgb portion as ambient but I found that to be a bit lame and did something more complicated personally… but that’s the easiest way.

1 Like

Thanks. I think I’ll start simple and ignore night/day to get my feet wet.

I kinda got the same issue, and i’m not understanding how you guys manage to get the light baked :confused:
To be precise i’m looking for a static lightning, If you can help me i would be thanksfull.

From what i’ve understand I need :

  • A custom unshaded Material with the vertex color set to “On”.
  • A color buffer on the generated mesh.

Where i struggle if i got the way to go above right is :

  • How do i generate the color buffer ?

About the baking himself :

  • Does object on the scene not being part of the mesh will be baked to it ? (i mean the custom mesh is the floor, i got a house on it, does the house shadow will be baked to the floor ?)
  • If the point above does not work, how can i manage to get another object be baked to the floor ?

As last hint to what i’m looking for : baking lightmap unity 3D

Thanks for any help.

I’m also considering using static lighting for a custom mesh.
Looking around I found people suggesting (1, 2) using Sunflow to bake the lightmap.

Is it feasible?

We are talking about minecraft style light baking. You both are talking about lightmaps… which is something entirely different and something you will generate in your 3D modeler and use as a second texture.

For anyone interested in lights being manually baked into the mesh here is a good resource I found for a light propagation algorithm.

I’ve been able to get some of it going. Still having issues with sunlight but at least now I understand somewhat how this stuff works. I think the value in learning how to write a voxel game like a minecraft clone is having to struggle through the low level details so that later when using tools like blender or maybe sunflow, you have an idea of what’s going on behind the scenes. At least that’s one of my goals in writing this game. Plus it’s just fun :smile:

I hope to open source the project in the form of a framework for kids to get involved in programming, including my own.

So far the community has been tremendously helpful, especially @pspeed and I’m really grateful.

1 Like

@roroah if you are truly wanting to bake lights into a custom mesh then I will share how I am doing it.

My material:

public class BlockChunk_Material extends Material{

public BlockChunk_Material(AssetManager assetManager, String blockTextureFilePath){
    super(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    Texture texture = assetManager.loadTexture(blockTextureFilePath);
    texture.setMagFilter(Texture.MagFilter.Nearest);
    texture.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
    setTexture("ColorMap", texture);
    setBoolean("VertexColor",true); 
    getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}

}
The key thing there is setBoolean(“VertexColor”, true). This tells the material to look at the color buffer of the mesh. This is how you set the color buffer:

    private static Mesh generateMesh(){
    Mesh mesh = new Mesh();
    mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(positions));
    mesh.setBuffer(Type.Index, 1, BufferUtils.createShortBuffer(indices));
    mesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
    mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(textureCoordinates));
    mesh.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(color));
    mesh.updateBound();
    return mesh;
}

The color buffer is made up of 4 float values(RGBA). I have a lighting algorithm that generates a value between 0 and 15 for each of my block locations then I set that value in my color array as follows:

    private void addLighting(BlockChunkControl chunk, Vector3Int location, Block.Face face)
{
	LightMap lights = chunk.getLights();

	float light = lights.getNormalizedLight(location);
    colors.add(light);
    colors.add(light);
    colors.add(light);
    colors.add(1.0f);

    colors.add(light);
    colors.add(light);
    colors.add(light);
    colors.add(1.0f);

    colors.add(light);
    colors.add(light);
    colors.add(light);
    colors.add(1.0f);

    colors.add(light);
    colors.add(light);
    colors.add(light);
    colors.add(1.0f);
}

I don’t care about color so I just set the light value the same for RGB. Also I’m adding RGBA values for each vertex in the block shape.

Hope this helps.

@xuan I got no idea on how to use SunFlow…

@jchappelle Thx, time to read :blush:

Oh, my bad. I forgot minecraft style was to have the whole face with the same light.