Baked lighting and color question

Currently I have a game that has baked lighting(think minecraft voxel game). I have a shader that handles scaling the light based on the time of day. That all works fine.

I’m working on incorporating color in my shader. Currently for each vertex I’m sending the following data in the color buffer:
r = blockLight
g = blockLight
b = blockLight
a = sunLight

I thought that I could limit the colors and pack them into one of the spots I’m using for blockLight and use bitwise operators for unpacking it in my shader.

Is this a common way to solve this or is there a better way?

Thanks!

Why do you want to do that?

There’s no free lunch, really. What format is that buffer? If it’s 4 bytes then you don’t really have a lot of masking room to play with in one 8 bit value. It can be done… I’ve done it as my colored lighting only has 0-15 per channel and so does my sunlight… so I’ve packed it all into one 16 bit value.

I don’t. I’m hoping for a cleaner way.

As I was driving this morning I realized there are other buffers that I can use like TexCoord2, TexCoord3 and so on. Not sure if that’s the best way. I threw this out here this morning to see what others like yourself are doing.

Mythruna is memory limited mostly… so I pack whatever I can into as small of buffers as possible. My position buffers are even bytes instead of floats.

I still have a couple of questions surrounding what I’m allowed to do when creating the Mesh. I have a MeshData class that gets passed to all my mesh generating code. I’ve posted the code below.

I’m guessing that the Position, Index, Normal and TextCoord buffers shouldn’t be touched but since I’m setting the VertexColor then I’m free to stuff what I want to in Color? Also, what about TexCoord2, TexCoord3…etc? Can I use those buffers to stuff additional data?

Also, when you say you use bytes for positions, does that mean I can change Color to a byte buffer or is there a restriction on what data type is allowed for different VertexBuffer.Type(s)?

I know that’s a lot of questions but I’m just trying to figure out what I’m allowed to do in respect to passing data to the shader.

public class MeshData
{
    public TFloatList positionsList = new TFloatArrayList();
    public TShortList indicesList = new TShortArrayList();
    public TFloatList normalsList = new TFloatArrayList();
    public TFloatList textureCoordinatesList = new TFloatArrayList();
    public TFloatList colorList = new TFloatArrayList();
    public Vector3fPool vec3Pool = new Vector3fPool();
    
	public Mesh toMesh()
	{
		float[] positions = positionsList.toArray();
		short[] indices = indicesList.toArray();
		float[] textureCoordinates = textureCoordinatesList.toArray();
		float[] normals = normalsList.toArray();
                float[] color = colorList.toArray();

		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;
	}
}

No restrictions at all, really. Your positions can be bytes, your texture coordinates can be integers… completely up to your shader.

Good deal! Thanks!

For a quick test I changed my color buffer to be an int buffer and removed my int(inColor.a) cast inside my shader and got an “explicit cast from float to int” error.

One thing that I’m frustrated with all of this is that since JME3 does so much behind the scenes for me, I find it really hard to understand the fundamentals. Where does inColor come from? Who declares it’s type to be float? If I want to send custom flags via mesh.setBuffer(Type.TexCoord5, 2, BufferUtils.createIntBuffer(flags)); then how do I access it in my shader? Is there a magical inTextCoord5?

I’ve read https://docs.jmonkeyengine.org/advanced/jme3_shaders.html so I get that there are jme3 equivalents to the GLSL attributes that are being set somewhere, so that answers part of my question above. But apparently they have data types that are set in stone according to the shader.

Shaders really piss me off. I don’t get how anyone gets good at writing shaders. It takes me 20 seconds to load my game and I get nowhere because of some “knitpicky” error.

Sorry I had to vent. My frustrations are mostly with GLSL and myself not with JME3. I hope you understand. :wink:

Here’s what I want to do. I want to make my sunlight and blocklight components stuffed into an integer field, and have another integer field have my block color multipliers. Each color channel for that will be 4 bits. Then another integer field reserved for custom flags that are attributes of a block that may alter the shader’s behavior. My revised code is below. Thanks for all your help thus far.

public class MeshData
{
    public TFloatList positionsList = new TFloatArrayList();
    public TShortList indicesList = new TShortArrayList();
    public TFloatList normalsList = new TFloatArrayList();
    public TFloatList textureCoordinatesList = new TFloatArrayList();
    public TFloatList colorList = new TFloatArrayList();
    public Vector3fPool vec3Pool = new Vector3fPool();
    
	public Mesh toMesh()
	{
		float[] positions = positionsList.toArray();
		short[] indices = indicesList.toArray();
		float[] textureCoordinates = textureCoordinatesList.toArray();
		float[] normals = normalsList.toArray();
        float[] color = colorList.toArray();
        int[] colorInts = new int[color.length];
        for(int i = 0; i < color.length; i++)
        {
        	colorInts[i] = (int)color[i];
        }

		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.createIntBuffer(colorInts));
		mesh.updateBound();
		return mesh;
	}
}

I can’t see the shader source so it’s tough to comment.

Im not at my computer at the moment but basically I’m using inColor.a as the index to an array like so lightTable [inColor.a]. Previously I did this lightTable [int (inColor.a)]. Looks like in inColor is a float vector no matter what I put in the mesh.

Is there a way to send custom attributes or am I limited to the ones in VertexBuffer.Type enum?

None of that is the part I need to see. You’ve somewhere at the top of your shader declared with inColor is. I have no idea what you’ve declared it as.

I think it’s

attribute vec4 inColor

I’ll check in the morning and post. Thanks!

Well… a vec4 is 4 floats. The drivers will convert your ints to floats then.

…my guess is that you really want:
attribute ivec4 inColor;

Thanks that did the trick!

That’s the first I’ve heard of that data type and I have read several GLSL tutorials. I feel like I’m in my first semester of Computer Science when I do this stuff.