[Solved] Problems with TestVertexProgramState

Good day,



I am hoping to apply the same effect illustrated in the TestVertexProgramState example.  Below is a screenshot of the problem:







This screenshot is derived from only drawing the shaded torus.  I can fix this by calling the following piece of code:


// Remove all of the lights...
lightState.detatchAll();

// This works just the same...
lightState.setEnable(false);



However, when I do that and then reenable the outline torus the following happens:



Notice that there are only two shaded color values on the torus.  I have not modified the 1x16 shader.png nor modified the celshaderARB.vp shader example included in the latest jME release.

It would seem that with the lights on I am getting the correct number of shaded colors on my torus, but the torus has some sort of artifact problem.  Also, with the light on my outline becomes a sort of gradient which is not the effect I am trying to emulate.

Below is my source code which is almost identical to jmetest.renderer.state.TestVertexProgramState by Eric Woroshow.


import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.input.NodeHandler;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Torus;
import com.jme.scene.state.CullState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.VertexProgramState;
import com.jme.scene.state.WireframeState;
import com.jme.util.TextureManager;

public class Test extends SimpleGame {

   private final float[] lightPosition = { -0.8f, 0.8f, 0.8f, 0.0f };

   public static void main(String[] args) {
      Test app = new Test();
      // app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
      app.start();
   }

   protected void simpleInitGame() {
      display.setTitle("Vertex Programs");
      display.getRenderer().setBackgroundColor(
            new ColorRGBA(0.25f, 0.25f, 0.25f, 1.0f));

      cam.setLocation(new Vector3f(0, 0, 45));
      cam.update();
      input = new NodeHandler(rootNode, 10, 2);

      lightState.detachAll();

      Torus outline = createOutlineTorus();
      Torus shaded = createShadedTorus();
      rootNode.attachChild(outline);
      rootNode.attachChild(shaded);

      rootNode.updateRenderState();
   }

   private Torus createShadedTorus() {
      VertexProgramState vp = display.getRenderer()
            .createVertexProgramState();
      vp.setParameter(lightPosition, 8);
      vp.load(Test.class.getClassLoader().getResource(
            "jmetest/data/images/celshaderARB.vp"));
      vp.setEnabled(true);

      TextureState ts = display.getRenderer().createTextureState();
      ts.setTexture(TextureManager.loadTexture(Test.class.getClassLoader()
            .getResource("jmetest/data/images/shader.png"),
            Texture.MM_NEAREST, Texture.MM_NEAREST));
      ts.setEnabled(true);

      CullState cs = display.getRenderer().createCullState();
      cs.setCullMode(CullState.CS_BACK);
      cs.setEnabled(true);

      Torus torus = new Torus("shadedTorus", 128, 32, 3.0f, 5.0f);
      torus.setDefaultColor(ColorRGBA.orange.clone());
      torus.setRenderState(vp);
      torus.setRenderState(ts);
      torus.setRenderState(cs);

      return torus;
   }

   private Torus createOutlineTorus() {
      CullState cs = display.getRenderer().createCullState();
      cs.setCullMode(CullState.CS_FRONT);
      cs.setEnabled(true);

      WireframeState ws = display.getRenderer().createWireframeState();
      ws.setLineWidth(6.0f);
      ws.setFace(WireframeState.WS_FRONT);
      ws.setEnabled(true);

      Torus torus = new Torus("outlineTorus", 128, 32, 3.0f, 5.0f);
      torus.setDefaultColor(ColorRGBA.black.clone());
      torus.setRenderState(cs);
      torus.setRenderState(ws);

      return torus;
   }
}



I appreciate the help!

While I’m still wondering why the above code isn’t working effectively, I wrote the same idea using GLSL instead.  I kinda like this second approach more because its application seems to scale more effectively.



Here is an image using the a GLSL approach:





Below is the my source code:


import com.jme.app.SimpleGame;
import com.jme.input.NodeHandler;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Torus;
import com.jme.scene.state.CullState;
import com.jme.scene.state.GLSLShaderObjectsState;
import com.jme.scene.state.WireframeState;

public class Test2 extends SimpleGame {

   public static void main(String[] args) {
      Test2 app = new Test2();
      app.start();
   }

   private Torus shadedGLSLTorus;

   private Torus outlineTorus;

   private float[] phongColor = new float[3];

   private float[] diffuseColor = new float[3];

   private float[] edgeColor = new float[3];

   private float edgeFactor = 0.5f;

   private float phongFactor = 0.7f;

   private void initColors(float[] arg0) {
      phongColor = arg0;

      diffuseColor[0] = phongColor[0] * phongFactor;
      diffuseColor[1] = phongColor[1] * phongFactor;
      diffuseColor[2] = phongColor[2] * phongFactor;

      edgeColor[0] = phongColor[0] * edgeFactor;
      edgeColor[1] = phongColor[1] * edgeFactor;
      edgeColor[2] = phongColor[2] * edgeFactor;

   }

   private void initOutlineTorus() {
      CullState cs = display.getRenderer().createCullState();
      cs.setCullMode(CullState.CS_FRONT);
      cs.setEnabled(true);

      WireframeState ws = display.getRenderer().createWireframeState();
      ws.setLineWidth(10.0f);
      ws.setFace(WireframeState.WS_FRONT);
      ws.setEnabled(true);

      outlineTorus = new Torus("outlineTorus", 128, 32, 3.0f, 5.0f);
      outlineTorus.setDefaultColor(ColorRGBA.black.clone());
      outlineTorus.setRenderState(cs);
      outlineTorus.setRenderState(ws);
   }

   private void initShadedTorus() {
      GLSLShaderObjectsState sos = display.getRenderer().createGLSLShaderObjectsState();

      sos.load(Test2.class.getClassLoader().getResource("jmetest/data/images/toon.vert"),
            Test2.class.getClassLoader().getResource("jmetest/data/images/toon.frag"));
      sos.setUniform("Edge", edgeFactor);
      sos.setUniform("Phong", phongFactor);
      sos.setUniform("PhongColor", phongColor[0], phongColor[1], phongColor[2]);
      sos.setUniform("DiffuseColor", diffuseColor[0], diffuseColor[1], diffuseColor[2]);
      sos.setUniform("EdgeColor", edgeColor[0], edgeColor[1], edgeColor[2]);
      sos.setEnabled(true);

      CullState cs = display.getRenderer().createCullState();
      cs.setCullMode(CullState.CS_BACK);
      cs.setEnabled(true);

      shadedGLSLTorus = new Torus("shadedGLSLTorus", 128, 32, 3.0f, 5.0f);
      shadedGLSLTorus.setRenderState(sos);
      shadedGLSLTorus.setRenderState(cs);

   }

   protected void simpleInitGame() {
      display.setTitle("GLSL");
      display.getRenderer().setBackgroundColor(new ColorRGBA(0.25f, 0.25f, 0.25f, 1.0f));

      cam.setLocation(new Vector3f(0, 0, 45));
      cam.update();
      input = new NodeHandler(rootNode, 10, 2);

      lightState.detachAll();

      initColors(ColorRGBA.orange.getColorArray());

      initShadedTorus();
      initOutlineTorus();

      rootNode.attachChild(outlineTorus);
      rootNode.attachChild(shadedGLSLTorus);

      rootNode.updateRenderState();
   }
}



toon.frag:


uniform vec3 DiffuseColor;
uniform vec3 PhongColor;
uniform vec3 EdgeColor;
uniform float Edge;
uniform float Phong;
varying vec3 Normal;

void main (void)
{
   vec3 color = DiffuseColor;
   float f = dot(vec3(0,0,1),Normal);
   if (abs(f) < Edge)
      color = EdgeColor;
   if (f > Phong)
      color = PhongColor;

   gl_FragColor = vec4(color, 1);
}



toon.vert


varying vec3 Normal;

void main(void)
{
   Normal = normalize(gl_NormalMatrix * gl_Normal);
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}



Kinda fun to play around with the Edge and Phong variables.  :)

Hey,



Just stumbled upon your little conversation with yourself  (:D) and it actually really helped me get started with imported shaders, something I have struggled to find any beginners resources on (maybe im just blind)!



Just thinking, maybe you should make an entry to the Wiki about starting with a simple shader (or just use this toon shader which is really cool)!



Anyways… Thanks!