RenderState.FaceCullMode.Front Issue

Hi,

I added a shape.Box to my scene and set the additional render state face cull mode to front.

This is what it looks like…

I realise that I must be doing something wrong as the front faces can clearly be seen.

I have tried all the other modes and they work as expected.

Please Help.

Regards
Penny

Show us the other modes so we can verify that it’s not a double sided mesh.

Hi pspeed,

This is face culling off…

This is face culling back…

This is face culling front…

The spatial mesh is generated from com.jme3.scene.shape.box

Here is the instantiation code…

public class sBox extends Node
 {
 public enum Face {OUTSIDE,INSIDE};
 public sBox(Vector3f _center,float _w,float _h,float _d,ColorRGBA _c,Face _f)
  {
  Geometry g=new Geometry("Box");
  Material m=new Material(Eo.getAssetManager(),"Asset/test/Lighting2.j3md");
  m.setBoolean("UseMaterialColors",true);
  m.setColor("Diffuse",_c);
  if(_c.getAlpha()<1f)
   {
   m.setTransparent(true);
   m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
   g.setQueueBucket(Bucket.Transparent);
   }
  if(_f==Face.OUTSIDE)
   {
   m.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Back);
   }else{
   m.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front);
   }
  Mesh mesh=new Box(_w,_h,_d);
  g.setMesh(mesh);
  g.setMaterial(m);
  attachChild(g);
  TangentBinormalGenerator.generate(g);
  setLocalTranslation(_center);
  }

I added TangentBinormalGenerator.generate(g); to see if that made a difference.

I made of copy of the lighting shader and added the following line…

wvNormal=-faceforward(wvNormal, viewDir, wvNormal);

at the appropriate location to enable back face lighting to render correctly.

This is everything. The issue is the front face culled spatial is showing the front faces.

Regards
Penny

And you have tried the original Ligthing shader too?
And you have tried to use _c with Alpha == 1f too?

Hiya Ogli,

This is with original Lighting shader…

This is with alpha set to 1…

As you can see, the back face lighting is now reversed and incorrect.
Both with alpha at 0.5f and 1f the front faces are showing.

Thanks
Penny

original shader -and- alpha == 1f -and- front face culling needs to be tested.

did you test this combination? (original shader, alpha = 1f, cull front faces)

also, try this with the original jME Box in the original SimpleApplication (the one that is auto-generated when you start a new jME project).

also, you did not say if you use jME 3.0 or jME 3.1 alpha1 or jME 3.1 master.

I wouldn’t know how to create the original simple application because I do not use the SDI. I type everything in notepad and use javac.exe to compile.

Here is the startup output… (looks like I am using version 3.0.10)

Dec 12, 2015 9:28:07 PM com.jme3.system.JmeDesktopSystem initialize
INFO: Running on jMonkeyEngine 3.0.10

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Lwjgl 2.9.0 context running on thread LWJGL Renderer Thread

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Adapter: aticfx64

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Driver Version: 8.17.10.1429

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Vendor: ATI Technologies Inc.

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: OpenGL Version: 4.5.13416 Compatibility Profile Context 15.300.1025.0

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: Renderer: AMD Radeon HD 7800 Series

Dec 12, 2015 9:28:08 PM com.jme3.system.lwjgl.LwjglContext printContextInitInfo
INFO: GLSL Ver: 4.40

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Device: OpenAL Soft

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Vendor: OpenAL Community

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Renderer: OpenAL Soft

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio Version: 1.1 ALSOFT 1.15.1

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: AudioRenderer supports 64 channels

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio effect extension version: 1.0

Dec 12, 2015 9:28:08 PM com.jme3.audio.lwjgl.LwjglAudioRenderer initInThread
INFO: Audio max auxilary sends: 4

Hm …
I just created a little test project with a “Quad” (instead of Box).
I had hoped that this would only have one face (i.e. 2 triangles and normals pointing all in one direction).
But this is not true - it seems that if you create a Quad and then a Geometry from that Quad, then all faces are actually doubled (i.e. four triangles, with 2 triangles having upwards normals and 2 triangles having down normals).
If this is the same with a Geometry created from a Box, then this would explain the strange behavior.
It’s strange though … because the code of Quad looks like only two triangles are made (in the index buffer).
The Box code is similar - it indicates that the Box is made of 12 triangles, not 24 triangles.
Very strange…
@pspeed - do you know anything about this? Or maybe other people from @Coredev team??

This makes sense. I will manually create a mesh to see if it solves the issue and I will let you know.

Hm… but it should not be that way.
I mean what is the error?
ideas:
a) the Geometry generates two triangles for each triangle that we want to create
b) there is an error in the shader

very strange…

Quad is only two triangles. Whatever you are using to surmise that it is 4 triangles is faulty.

No success… Here are my results…

2 cubes, one back face culled the other front face culled, with normal lines…

code…

public class sBox2 extends Node
 {

 private static final float[] GEOMETRY_NORMALS_DATA = {

// front
  0,  0, -1,  0,  0, -1,  0,  0, -1,
  0,  0, -1,  0,  0, -1,  0,  0, -1,
// back
  0,  0,  1,  0,  0,  1,  0,  0,  1,
  0,  0,  1,  0,  0,  1,  0,  0,  1,
// top
  0,  1,  0,  0,  1,  0,  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,  0, -1,  0,  0, -1,  0,
// right
 -1,  0,  0, -1,  0,  0, -1,  0,  0,
 -1,  0,  0, -1,  0,  0, -1,  0,  0,
// left
  1,  0,  0,  1,  0,  0,  1,  0,  0,
  1,  0,  0,  1,  0,  0,  1,  0,  0

  };

 public enum Face {OUTSIDE,INSIDE};
 public sBox2(Vector3f _center,float _w,float _h,float _d,MyColor _c,Face _f)
  {
  Geometry g=new Geometry("Box");
  Material m=new Material(Eo.getAssetManager(),"Common/MatDefs/Light/Lighting.j3md");
  m.setBoolean("UseMaterialColors",true);
  m.setColor("Diffuse",_c.asJmeColor());
  if(_c.getAlpha()<1f)
   {
   m.setTransparent(true);
   m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
   g.setQueueBucket(Bucket.Transparent);
   }
  if(_f==Face.OUTSIDE)
   {
   m.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Back);
   }else{
   m.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front);
   }
  Mesh mesh=createMesh(_w,_h,_d);
  g.setMesh(mesh);
  g.setMaterial(m);
  attachChild(g);
  TangentBinormalGenerator.generate(g);
  setLocalTranslation(_center);


  Geometry g2=new Geometry("Normals");
  g2.setMesh(TangentBinormalGenerator.genNormalLines(mesh,1f));
  Material m2=new Material(Eo.getAssetManager(),"Asset/material/Basic.j3md");
  m2.setColor("Color",MyColor.BLUE.asJmeColor());
  g2.setMaterial(m2);
  attachChild(g2);


  }
 private Mesh createMesh(float _w,float _h,float _d)
  {
  float hw=_w/2;
  float hh=_h/2;
  float hd=_d/2;

  Mesh m=new Mesh();
  m.setMode(Mesh.Mode.Triangles);
  m.setBuffer(VertexBuffer.Type.Normal,3,GEOMETRY_NORMALS_DATA);


  m.setBuffer(VertexBuffer.Type.Position,3,new float[]{

-hw,-hh,-hd,
+hw,+hh,-hd,
+hw,-hh,-hd,
-hw,-hh,-hd,
-hw,+hh,-hd,
+hw,+hh,-hd,

-hw,-hh,+hd,
+hw,-hh,+hd,
+hw,+hh,+hd,
-hw,-hh,+hd,
+hw,+hh,+hd,
-hw,+hh,+hd,


-hw,+hh,-hd,
+hw,+hh,+hd,
+hw,+hh,-hd,
-hw,+hh,-hd,
-hw,+hh,+hd,
+hw,+hh,+hd,

-hw,-hh,-hd,
+hw,-hh,-hd,
+hw,-hh,+hd,
-hw,-hh,-hd,
+hw,-hh,+hd,
-hw,-hh,+hd,


-hw,+hh,-hd,
-hw,-hh,-hd,
-hw,-hh,+hd,
-hw,+hh,-hd,
-hw,-hh,+hd,
-hw,+hh,+hd,

+hw,+hh,-hd,
+hw,-hh,+hd,
+hw,-hh,-hd,
+hw,+hh,-hd,
+hw,+hh,+hd,
+hw,-hh,+hd});

  return m;
  }
    //################################################################################
// end
//################################################################################
 }

Can you provide a complete single class test case with just the cube and scene setup?

ok, I tried that and the issue doesnt seem to occur in the simple application test.

My question is now, what is the difference and what could cause this.

All the nodes in my project scene are created without any additional settings as per SimpleApplication.

The scene is being rendered to an offscreen buffer. I can’t imagine the renderManger or anything else would have settings that cause this.

Is there something that I am unaware of?
Maybe a camera setting?

code…

package jme3test.penny;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

import com.jme3.light.PointLight;
import com.jme3.material.RenderState;


public class Test1 extends SimpleApplication {

    public static void main(String[] args){
        Test1 app = new Test1();
        app.start(); // start the game
        }

@Override
    public void simpleInitApp() {

    PointLight pl=new PointLight();
    pl.setPosition(new Vector3f(2f,3f,4f));
    pl.setRadius(30);
    rootNode.addLight(pl);



    Box b = new Box(1, 1, 1); // create cube shape
    Geometry geom = new Geometry("Box", b);  // create cube geometry from the shape
    Material mat = new Material(assetManager,
      "Common/MatDefs/Light/Lighting.j3md");  // create a simple material
    mat.setColor("Diffuse", ColorRGBA.Blue);   // set color of material to blue
  mat.setBoolean("UseMaterialColors",true);

   mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front);
    geom.setMaterial(mat);                   // set the cube's material
    rootNode.attachChild(geom);              // make the cube appear in the scene
    }
}

I have found the cause, what to do about it is the question…

With 3 lights, ambient and direction on root node, and a point light on a node attached to the root node which is the parent of the boxes.

This image is with the point light removed…

Could this be a bug in the Lighting shader not processing the lights correctly?
or is there a renderstate type setting that I need to get the shader to merge the lights correctly?

Your help is greatly appreciate.
Thanks
Penny

Ehm … stupid me. All works as it should - except for what Penny seems to have discovered.

As a side note… now that I have removed the 3 light I am able to show you some pictures…

Is that what you try to achieve? Translucent hulls?
I called this “the jellyfish shader” in my sketches.
Problem is that it only works with convex objects.
But for many cases (e.g. bubbles) that’s enough.
It just won’t render convoluted / concave objects.

I think I understand what you mean.

You are right that concave objects, an object where it is possible to see a surface of itself through a surface of itself, will fail to render correctly. This is because the render engine renders geometries as complete objects.

Transparency support is practically none existant yet I see a lot of programs/games with quite comprehensive transparency handling.

If I find that I need to give a concave shape transparency I will break it into multiple geometries. I didnt want to dig too deep into the render mechanism so I created somthing similar to a scene processor for the transparency bucket.

I didnt want to alter the way geometries are rendered from the normal way, ie they are rendered using the default material defs. I wonder if it is possible to alter the renderer so it wraps geometries with a transparency pixel depth handler so concave geometries could be rendered. The issue then would be how to handle intersecting geometries. I do have an idea for that tho.

All the work my transparency handler does is on the GPU.

I have heard of a concept called “A buffer”. (A is for “Alpha”, I guess…)
This is a very old concept trying to deal with that.

Some deferred renderers have their custom tricks to deal with transparent objects too.
You must know, that deferred rendering usually has a big problem with transparency.

Also … (what I often see) is that people confuse Transparency and Translucency.
Transparency comes from small holes in objects (i.e. a fence or tree).
Translucency comes from “colored glass” (i.e. sunglasses or green wine bottles).
Some objects can have both (i.e. a tree that is made of glass - combines both ideas).