[SOLVED] Creating my own custom buffers (for night and day prebaked light)

I’ve run through this and it all works very nicely. I’ll put the code for the java and shaders at the bottom of this post in case anyone else is trying to do this. I’ve also put in in a respository for the full working example Bitbucket. And I’ve done a more in the context of my game write up here https://richardonsoftware.wordpress.com/night-and-day-done-not-stupidly/

    package mygame;

    import com.jme3.app.SimpleApplication;
    import com.jme3.material.Material;
    import com.jme3.math.Vector2f;
    import com.jme3.math.Vector3f;
    import com.jme3.math.Vector4f;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.Mesh;
    import com.jme3.scene.VertexBuffer;
    import com.jme3.shader.VarType;
    import com.jme3.util.BufferUtils;

    public class Main extends SimpleApplication {

        private Material mat;
        private float dayNightPeriod = 4;
        private float time;
        
        public static void main(String[] args) {
            Main app = new Main();
            app.start();
        }

        @Override
        public void simpleInitApp() {
            
            //the points in 3d space where the geometry will be
            Vector3f [] vertices = new Vector3f[8];
            //one square
            vertices[0] = new Vector3f(0,0,0);
            vertices[1] = new Vector3f(3,0,0);
            vertices[2] = new Vector3f(0,3,0);
            vertices[3] = new Vector3f(3,3,0);
            //a second square
            vertices[4] = new Vector3f(3,0,0);
            vertices[5] = new Vector3f(6,0,0);
            vertices[6] = new Vector3f(3,3,0);
            vertices[7] = new Vector3f(6,3,0);
            
            //combine those vetexes into triangles 
            int [] indexes = { 
                //first square
                2,0,1,1,3,2, 
                //second square    
                6,4,5,5,7,6     
            };
            
            //we're not using a texture but if we were this would define whtich parts of the image are where    
            Vector2f[] texCoord = new Vector2f[8];
            texCoord[0] = new Vector2f(0,0);
            texCoord[1] = new Vector2f(1,0);
            texCoord[2] = new Vector2f(0,1);
            texCoord[3] = new Vector2f(1,1);
            texCoord[4] = new Vector2f(0,0);
            texCoord[5] = new Vector2f(1,0);
            texCoord[6] = new Vector2f(0,1);
            texCoord[7] = new Vector2f(1,1);
            
            
            //Set the first colour buffer, this will be the sunlight color
            Vector4f[] sunlightColour = new Vector4f[8]; //these are Vector4f because we have a red, green, blue and transparency per vertex
            //both the squares at full brightness in sunlight
            sunlightColour[0] = new Vector4f(1,1,1,1);
            sunlightColour[1] = new Vector4f(1,1,1,1);
            sunlightColour[2] = new Vector4f(1,1,1,1);
            sunlightColour[3] = new Vector4f(1,1,1,1);
            
            sunlightColour[4] = new Vector4f(1,1,1,1);
            sunlightColour[5] = new Vector4f(1,1,1,1);
            sunlightColour[6] = new Vector4f(1,1,1,1);
            sunlightColour[7] = new Vector4f(1,1,1,1);
            
            Vector4f[] sourceLightColour = new Vector4f[8];
            sourceLightColour[0] = new Vector4f(0.9f,0.9f,0.9f,1); //first square at 90% brightness in sourcelight
            sourceLightColour[1] = new Vector4f(0.9f,0.9f,0.9f,1);
            sourceLightColour[2] = new Vector4f(0.9f,0.9f,0.9f,1);
            sourceLightColour[3] = new Vector4f(0.9f,0.9f,0.9f,1);
            
            sourceLightColour[4] = new Vector4f(0.3f,0.3f,0.3f,1);//second square at 30% brightness in sourcelight
            sourceLightColour[5] = new Vector4f(0.3f,0.3f,0.3f,1);
            sourceLightColour[6] = new Vector4f(0.3f,0.3f,0.3f,1);
            sourceLightColour[7] = new Vector4f(0.3f,0.3f,0.3f,1);
            
            //now we have all the data we create the mesh
            //for more details https://jmonkeyengine.github.io/wiki/jme3/advanced/custom_meshes.html
            Mesh mesh = new Mesh();
            mesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
            mesh.setBuffer(VertexBuffer.Type.Index,    3, BufferUtils.createIntBuffer(indexes));
            mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
            mesh.setBuffer(VertexBuffer.Type.Color, 4, BufferUtils.createFloatBuffer(sunlightColour));
            //we're using the conventional Color buffer for sunlight and using one of the (usually) unused TexCoord5 to hold the source light
            mesh.setBuffer(VertexBuffer.Type.TexCoord5, 4, BufferUtils.createFloatBuffer(sourceLightColour));
            mesh.updateBound();
            
            Geometry geom = new Geometry("mesh", mesh);

            mat = new Material(assetManager, "MatDefs/RepeatingUnshaded.j3md");
            //mat = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md"); 
            mat.setBoolean("VertexColor", true);
            geom.setMaterial(mat);

            rootNode.attachChild(geom);
        }

        @Override
        public void simpleUpdate(float tpf) {
           time += tpf;
           if (time>dayNightPeriod){
              time = 0; 
           }
           mat.setParam("SunlightIntensity", VarType.Float,time/dayNightPeriod); 
        }
    }

Vertex shader

    #import "Common/ShaderLib/GLSLCompat.glsllib"
    #import "Common/ShaderLib/Skinning.glsllib"
    #import "Common/ShaderLib/Instancing.glsllib"

    attribute vec3 inPosition;

#if defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
    #define NEED_TEXCOORD1
#endif

attribute vec2 inTexCoord;
attribute vec2 inTexCoord2;
attribute vec4 inColor;

varying vec2 texCoord1;
varying vec2 texCoord2;
attribute vec4 inTexCoord5; //!changed! this is the source light that is passed to us
varying vec4 texCoord5; //!changed! and this is how we'll pass it through to the fragment shader

varying vec4 vertColor;

void main(){
    #ifdef NEED_TEXCOORD1
        texCoord1 = inTexCoord;
    #endif

    #ifdef SEPARATE_TEXCOORD
        texCoord2 = inTexCoord2;
    #endif

    #ifdef HAS_VERTEXCOLOR
        vertColor = inColor;
    #endif

    vec4 modelSpacePos = vec4(inPosition, 1.0);
    #ifdef NUM_BONES
        Skinning_Compute(modelSpacePos);
    #endif

    texCoord5 = inTexCoord5; //!changed! its the fragment shader that wants this so we just pass it on


    gl_Position = TransformWorldViewProjection(modelSpacePos);
}

Fragment shader
    #import "Common/ShaderLib/GLSLCompat.glsllib"

    #if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))
        #define NEED_TEXCOORD1
    #endif

    #if defined(DISCARD_ALPHA)
        uniform float m_AlphaDiscardThreshold;
    #endif

    uniform float m_SunlightIntensity; //!changed!
    uniform vec4 m_Color;
    uniform sampler2D m_ColorMap;
    uniform sampler2D m_LightMap;

    varying vec2 texCoord1;
    varying vec2 texCoord2;

    varying vec4 vertColor;

    varying vec4 texCoord5; //!changed!this is the source color passed through to us

    void main(){
        vec4 color = vec4(1.0);

        #ifdef HAS_COLORMAP
            color *= texture2D(m_ColorMap, texCoord1);     
        #endif

        #ifdef HAS_VERTEXCOLOR
            //!changed! This is the actual combining of the two colours
            color.x *= max(vertColor.x * m_SunlightIntensity,texCoord5.x);
            color.y *= max(vertColor.y * m_SunlightIntensity,texCoord5.y);
            color.z *= max(vertColor.z * m_SunlightIntensity,texCoord5.z);
            color.a *= vertColor.a;
        #endif

        #ifdef HAS_COLOR
            color *= m_Color;
        #endif

        #ifdef HAS_LIGHTMAP
            #ifdef SEPARATE_TEXCOORD
                color.rgb *= texture2D(m_LightMap, texCoord2).rgb;
            #else
                color.rgb *= texture2D(m_LightMap, texCoord1).rgb;
            #endif
        #endif

        #if defined(DISCARD_ALPHA)
            if(color.a < m_AlphaDiscardThreshold){
               discard;
            }
        #endif

        gl_FragColor = color;
    }
5 Likes