Lightning a simple custom mesh

Hello Jmonkeys,
I’m creating a 3D editor for a voxel game and I’ve created a custom mesh for my spatials which is a box with different texture UVs than the usual default JME box.
Everything works fine, but I’ve got a problem with the faces of my box when I use the lights. I’m using Lighting.j3md, a directional light and an ambient light.
This is the situation:

as you can see the directional light comes from the opposite direction and these box sides look pretty ugly (there’s no distinction among the sides which are dark). I’m using a gray ambient color and a white diffuse color for the box.

so my question is: how can I make those dark sides more different (each darker than the others), so I can distinguish them easily?

Thanks in advance,
Axel

ps. this is the code for creating the box:
[java]
Mesh box = CustomBox.createCustomBox();
Geometry geom = new Geometry(“Box”, box);
Material mat = new Material(McAnimator.app.getAssetManager(), // Create new material and…
“Common/MatDefs/Light/Lighting.j3md”); // … specify .j3md file to use (illuminated).
mat.setBoolean(“UseMaterialColors”, true);
mat.setColor(“Ambient”, ColorRGBA.Gray); // … color of this object
mat.setColor(“Diffuse”, ColorRGBA.White); // … color of light being reflected
mat.setBoolean(“SeparateTexCoord”,true);
geom.setMaterial(mat);
node.attachChild(geom);
[/java]

and these are the normals of the vertices:
[java]
float[] normals = new float[]{
-1,-1,1, 1,-1,1, -1,1,1, 1,1,1, //FRONT
-1,-1,-1, -1,-1,1, -1,1,-1, -1,1,1, //LEFT
1,-1,-1, -1,-1,-1, 1,1,-1, -1,1,-1, //BACK
1,-1,1, 1,-1,-1, 1,1,1, 1,1,-1, //RIGHT
-1,-1,-1, 1,-1,-1, -1,-1,1, 1,-1,1, //BOTTOM
-1,1,1, 1,1,1, -1,1,-1, 1,1,-1, //TOP
};
[/java]

Seems that the forum didn’t load my image… so here’s again:

and in case, this is the link to the image:

I can look at your normals and instantly tell they are not normals. Unless they are used to somehow construct the normals in a non-obvious way.

Sometimes looking at code that already exists will get you 99% to your solution. For example, it would only take two or three clicks to open up JME’s Quad mesh to see how it makes a quad.

Edit: since that material configuration would work fine with a JME box, it’s obviously the mesh that is wrong… but we can’t see how you make that.

Thanks pspeed for your reply,
my normals are “shared normals”, but even with the “correct” normals, it has the same problem. Changing the normals, this is the code that I use for creating the custom mesh:

[java]
Mesh customBox = new Mesh();

    Vector3f[] vertices = new Vector3f[24];
    //FRONT
    vertices[0] = new Vector3f(0, -sizeY, 0);
    vertices[1] = new Vector3f(sizeX, -sizeY, 0);
    vertices[2] = new Vector3f(0, 0, 0);
    vertices[3] = new Vector3f(sizeX, 0, 0);
    //LEFT
    vertices[4] = new Vector3f(0, -sizeY, -sizeZ);
    vertices[5] = new Vector3f(0, -sizeY, 0);
    vertices[6] = new Vector3f(0, 0, -sizeZ);
    vertices[7] = new Vector3f(0, 0, 0);
    //BACK
    vertices[8] = new Vector3f(sizeX, -sizeY, -sizeZ);
    vertices[9] = new Vector3f(0, -sizeY, -sizeZ);
    vertices[10] = new Vector3f(sizeX, 0, -sizeZ);
    vertices[11] = new Vector3f(0, 0, -sizeZ);
    //RIGHT
    vertices[12] = new Vector3f(sizeX, -sizeY, 0);
    vertices[13] = new Vector3f(sizeX, -sizeY, -sizeZ);
    vertices[14] = new Vector3f(sizeX, 0, 0);
    vertices[15] = new Vector3f(sizeX, 0, -sizeZ);
    //BOTTOM
    vertices[16] = new Vector3f(0, -sizeY, -sizeZ);
    vertices[17] = new Vector3f(sizeX, -sizeY, -sizeZ);
    vertices[18] = new Vector3f(0, -sizeY, 0);
    vertices[19] = new Vector3f(sizeX, -sizeY, 0);
    //TOP
    vertices[20] = new Vector3f(0, 0, 0);
    vertices[21] = new Vector3f(sizeX, 0, 0);
    vertices[22] = new Vector3f(0, 0, -sizeZ);
    vertices[23] = new Vector3f(sizeX, 0, -sizeZ);

    // Texture coordinates
    Vector2f[] texCoord = new Vector2f[24];
    //FRONT
    texCoord[0] = new Vector2f(localOriginX+localSizeZ, localOriginY);
    texCoord[1] = new Vector2f(localOriginX+localSizeZ+localSizeX, localOriginY);
    texCoord[2] = new Vector2f(localOriginX+localSizeZ, localOriginY+localSizeY);
    texCoord[3] = new Vector2f(localOriginX+localSizeZ+localSizeX, localOriginY+localSizeY);
    //LEFT
    texCoord[4] = new Vector2f(localOriginX, localOriginY);
    texCoord[5] = new Vector2f(localOriginX + localSizeZ, localOriginY);
    texCoord[6] = new Vector2f(localOriginX, localOriginY+localSizeY);
    texCoord[7] = new Vector2f(localOriginX + localSizeZ, localOriginY+localSizeY);
    //BACK
    texCoord[8] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ, localOriginY);
    texCoord[9] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ + localSizeX, localOriginY);
    texCoord[10] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ, localOriginY+localSizeY);
    texCoord[11] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ + localSizeX, localOriginY+localSizeY);
    //RIGHT
    texCoord[12] = new Vector2f(localOriginX+localSizeZ+localSizeX, localOriginY);
    texCoord[13] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ, localOriginY);
    texCoord[14] = new Vector2f(localOriginX+localSizeZ+localSizeX, localOriginY+localSizeY);
    texCoord[15] = new Vector2f(localOriginX+localSizeZ+localSizeX+localSizeZ, localOriginY+localSizeY);
    //BOTTOM
    texCoord[16] = new Vector2f(localSizeZ, localOriginY+localSizeY);
    texCoord[17] = new Vector2f(localSizeZ + localSizeX, localOriginY+localSizeY);
    texCoord[18] = new Vector2f(localSizeZ, localOriginY+localSizeY+localSizeZ);
    texCoord[19] = new Vector2f(localSizeZ + localSizeX, localOriginY+localSizeY+localSizeZ);
    //TOP
    texCoord[20] = new Vector2f(localSizeZ + localSizeX, localOriginY+localSizeY);
    texCoord[21] = new Vector2f(localSizeZ + localSizeX + localSizeX, localOriginY+localSizeY);
    texCoord[22] = new Vector2f(localSizeZ + localSizeX, localOriginY+localSizeY+localSizeZ);
    texCoord[23] = new Vector2f(localSizeZ + localSizeX + localSizeX, localOriginY+localSizeY+localSizeZ);

    //Indexes. We define the order in which mesh should be constructed (each 3->1 triangle, 2 triangles->1 quad, 6 quads->1 cube)
    int[] indexes = {0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10, 12, 13, 14, 13, 15, 14, 16, 17, 18, 17, 19, 18, 20, 21, 22, 21, 23, 22};

    float[] normals = new float[]{
        0,0,1, 0,0,1, 0,0,1, 0,0,1, //FRONT
        -1,0,0, -1,0,0, -1,0,0, -1,0,0, //LEFT
        0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, //BACK
        1,0,0, 1,0,0, 1,0,0, 1,0,0, //RIGHT
        0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, //BOTTOM
        0,1,0, 0,1,0, 0,1,0, 0,1,0, //TOP
    };
    
    // Setting buffers
    customBox.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
    customBox.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
    customBox.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));
    customBox.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
    customBox.updateBound();

    customBox.setDynamic();

[/java]

the problem is still there: 3 faces of the box have the exactly same color and you cannot distinguish them.

Again thanks and sorry for the newbie question,
Axel

Try a regular quad with your material. If that doesn’t work then you know your material and/or lighting setup are messed up. If it works then you can figure out why your mesh is bugged.

DISCLAIMER : I’m a newbie too.

The 3 faces aren’t illuminated by directionnal light => black + ambient color
I suggest you to add an second lighter directionnal light in opposite or mirror direction (eg (-X, Y, -Z)) and to reduce intencity of ambient light.

You don’t need two lights. You can make a nice looking scene with one directional light and one ambient if they are setup right… and then you don’t take the performance hit of having two lights.

Edit: it’s true that the sides facing away from the light will have the same shading… because that’s lighting. Not sure it’s worth rendering the scene twice to make it less realistic.

I just tried with JME quads (I built a box made of JME quads) and the problem is still the same: Some faces look exactly the same and you cannot distinguish them. These images show you the result:
Dropbox - Error

and

As you can see from the images, we cannot distinguish the sides of the box.

I’d like to have something like this (taken from an already existing software):

This is my JME setup with the lights:

[java]
this.settings.setFrameRate(60);
//Activate windowed input behaviour
this.flyCam.setDragToRotate(true);
this.flyCam.setMoveSpeed(25);
//Set near/far FOV
float aspect = (float) cam.getWidth() / (float) cam.getHeight();
this.cam.setFrustumPerspective(45f, aspect, 0.1f, 200000F);
this.cam.update();

    this.viewPort.setBackgroundColor(ColorRGBA.DarkGray);
    
    AmbientLight am = new AmbientLight(); 
    am.setColor(ColorRGBA.White.mult(1F));
    
    DirectionalLight sun = new DirectionalLight();
    sun.setColor(ColorRGBA.White.mult(0.45F));
    sun.setDirection(new Vector3f(1F,-0.5F,0.5F).normalizeLocal());
          
    this.rootNode.addLight(am);
    this.rootNode.addLight(sun);

[/java]

Seriously don’t know what I should add/change/fix, I’d just like to have a slightly different gradient of gray on each side of my box caused by the light in the scene, so you can distinguish them easily.

Thanks again for the critical help!
Axel

Dont set your light diagonal, as the lighting is based on the normal dir to the lightdir dot product.

Try for example
sun.setDirection(new Vector3f(1,-0.6f,-0.3f).normalizeLocal());

@Empire Phoenix said: Dont set your light diagonal, as the lighting is based on the normal dir to the lightdir dot product.

Try for example
sun.setDirection(new Vector3f(1,-0.6f,-0.3f).normalizeLocal());

Just tried. Still 3 of 6 sides (the darker ones) have got the same gradient of grey, like this:

The other 3 sides are good tho :slight_smile:
Am I missing some basic concepts about lightning? I suppose the 3 darker sides should have slightly different gradients because of the light.

Again thanks,
Axel

Yep you miss some concept,

it is working s inteded,
as a light will only light surfaces actually in the direction of the light.
So those 3 surfaces are simply in the wrond direction.

Also visible in the examples there.

What you can do in this case if you really want (a kinda unrealistic) lighting, is to add a few more lights.
Alternativly you could also use a box model that is differently colord in the texture.

Thanks Empire Phoenix for the great tips,
this software will be an editor and the box must be rotated by the user, so I cannot use a different colored texture for this purpose (and I’m currently using a Color).

I also tried with 2 directional lights, but the results were very ugly.

In real life, even if the sides are both dark, you can see at least the edge between them. Here (as you can see in the images) you cannot.

Could you suggest what type of lights I should add into the scene, please? :smiley:
Thank you!

Do you actually care about realistic lighting or more about usability?

Possible 1
Create a second box in translucent bucket with wireframe on,then the edges are perfectly visible
Possible 2
Use a CellShading postprocessor or similar, so there is an actual contour.
possible 3
Use up to lights onto each axis, each with a slight color variation, so the edges have different colors.

IMHO, you should create your own shader/materials.
An other workaround for your editor is to attach the light source to the camera (like in the SDK viewer), or try to use shaderblow/matcap

To use matcap, you don’t need light (it basicly use normal, eye, and a texture).

  1. install netbeans plugin : shaderblowlib
  2. add library shaderblow

[java]
//Material mat = assetManager.loadMaterial(“Materials/matcap_0.j3m”); //same a the 2 following line.
Material mat = new Material(assetManager, “ShaderBlow/MatDefs/MatCap/MatCap.j3md”);
mat.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/mapcap_0.png”));
mat.setColor(“Multiply_Color”, ColorRGBA.Blue); // the diffuse color because mapcap_0 is grayscale
[/java]

I share project at GitHub - davidB/jme3_sandbox: jme3 sandbox project, experiment, ...

Matcap is used by modeling editor like zbrush.

Hope it help you

Thanks so much for your replies guys!

Use up to lights onto each axis, each with a slight color variation, so the edges have different colors.
This would mean having 3 different lights which would be a bit heavy for performance :)
An other workaround for your editor is to attach the light source to the camera (like in the SDK viewer)
This idea is pretty good, I'm considering this option!
To use matcap...
Also matcap seems really good (I'm a newbie and I didn't know about it), one question though: does this material work with transparency?

Thanks to all guys, incredible support!
Axel

I don’t know if matcap work with transparency, but I don’t think the code from shaderblow support transparency.

If you’re interested by matcap you can play with this online demo/tools : http://www.clicktorelease.com/code/spherical-normal-mapping/

Seems that the idea of having the light attached to the camera works perfectly. I’m checking if it works with no problems :slight_smile: Thanks guys for all the suggestions!