Per-Pixel lighting?

Hello!



Work got busy there for a couple of weeks so I didn’t get much of a chance to look at this. I was hoping to try it on my home machine to see if maybe this Quatro FX1600 isn’t cutting the mustard or something. I’ve been banging my head against the desk for the past 2 hours trying all sorts of things to get a flat surface like you built, but I’ve been met with very little luck.



My vertex norms and face norms are pointing straight out. Hell, I even tried disconnecting the faces from one another at one point.



However, one thing bothers me that I haven’t tried but I have little experience with. So, right now, I’m not worrying about texture mapping and I’m just making solid color materials and applying them to the model in java code. I’m not even linking the material with the model at the moment because I thought that by setting the material manually in the code, I’m overwriting anything that the exported material file would be doing. Am I correct in thinking this?



Thanks!

~FlaH



EDIT: Here’s one wall from a level model I was working on and I’ve been playing with just this one wall forever XD Ogre XML of course.



wall.004.mesh.xml



[java]

<mesh>

<submeshes>

<submesh material=“Material” usesharedvertices=“false”>

<faces count=“32”>

<face v1=“0” v2=“1” v3=“2”/>

<face v1=“2” v2=“3” v3=“0”/>

<face v1=“4” v2=“0” v3=“3”/>

<face v1=“2” v2=“5” v3=“3”/>

<face v1=“0” v2=“4” v3=“6”/>

<face v1=“6” v2=“7” v3=“0”/>

<face v1=“1” v2=“0” v3=“7”/>

<face v1=“7” v2=“6” v3=“8”/>

<face v1=“9” v2=“10” v3=“11”/>

<face v1=“11” v2=“7” v3=“9”/>

<face v1=“8” v2=“9” v3=“7”/>

<face v1=“7” v2=“11” v3=“1”/>

<face v1=“12” v2=“8” v3=“6”/>

<face v1=“6” v2=“13” v3=“12”/>

<face v1=“14” v2=“12” v3=“13”/>

<face v1=“13” v2=“6” v3=“4”/>

<face v1=“15” v2=“16” v3=“17”/>

<face v1=“17” v2=“2” v3=“15”/>

<face v1=“1” v2=“15” v3=“2”/>

<face v1=“2” v2=“17” v3=“5”/>

<face v1=“15” v2=“1” v3=“18”/>

<face v1=“18” v2=“19” v3=“15”/>

<face v1=“16” v2=“15” v3=“19”/>

<face v1=“19” v2=“18” v3=“20”/>

<face v1=“21” v2=“22” v3=“23”/>

<face v1=“23” v2=“19” v3=“21”/>

<face v1=“20” v2=“21” v3=“19”/>

<face v1=“19” v2=“23” v3=“16”/>

<face v1=“24” v2=“20” v3=“18”/>

<face v1=“18” v2=“11” v3=“24”/>

<face v1=“10” v2=“24” v3=“11”/>

<face v1=“11” v2=“18” v3=“1”/>

</faces>

<geometry vertexcount=“25”>

<vertexbuffer positions=“true” normals=“true”>

<vertex>

<position x="-0.500000" y="-2.000000" z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-2.000000"/>

<normal x="-1.000000" y="-0.000000" z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

</vertexbuffer>

</geometry>

</submesh>

</submeshes>

</mesh>

[/java]

This mesh looks fine, just like the one in my screenshot.

Your video card should display the mesh exactly as it appears everywhere else, because it has to run the shader code.

Its like writing 1 + 1 = 2 while some video card does 1 + 1 = 3 which makes no sense in this case.



The mistake might be in the code, perhaps you can create a test case?

Oh? So I’m not going insane yet! Yay! :stuck_out_tongue:



I thought maybe it might look different on my home machine, but it turns out it looks about the same. Took me a little bit to get going since I reloaded it recently and hadn’t put Java/Eclipse/jMP on it yet.



I’ll work a test case up tomorrow afternoon.



~FlaH



Below is a screenshot of the wall ~ in game. Pointlight is attached above the player (which is a cyan box! Exciting! :p) And honestly, the two triangle wall to the left of it doesn’t look too hott either, all of them look sorta like that at the right angle.



Alrighty. I created a small, simple program that just has the wall, and the material I’ve been using (which is more or less the parameters you specified earlier in this thread @Momoko_Fan). Use the F and R keys to move the light towards and away from the wall respectively. This uses the flycam so you can get whatever angle you need to observe.



~FlaH



A screenshot of what it looks like:







The Code:



[java]

public class FlatSurfaceTest extends SimpleApplication implements AnalogListener {



/** Application /

private static FlatSurfaceTest app;

private static AppSettings settings;



/
Assets /

Node loadedWall;

PointLight light;

Geometry lightSphere;



/
Materials **/

Material refPtMaterial;

Material wallMaterial;



public static void main(String[] args) {

app = new FlatSurfaceTest();

settings = new AppSettings(true);

settings.setFrameRate(200);

settings.setTitle(“Flat Wall Test”);

app.setSettings(settings);

app.start();

}



@Override

public void simpleInitApp() {

flyCam.setMoveSpeed(35f);



// Prepare the asset Materials and Controls

prepareMaterials();

prepareControls();



// Create the wall object

loadedWall = (Node) assetManager.loadModel(“resources/flat/flatwall.mesh.xml”);

loadedWall.setMaterial(wallMaterial);



rootNode.attachChild(loadedWall);

loadedWall.move(5, 0, 0);



// Create a reference sphere for the light position

Sphere sphere = new Sphere(16, 16, .25f);

lightSphere = new Geometry(“w”, sphere);

lightSphere.setMaterial(refPtMaterial);

rootNode.attachChild(lightSphere);



// Create a light for use with the wall object’s material

light = new PointLight();

light.setColor(new ColorRGBA(1,1,1,1));

light.setRadius(10f);

light.setPosition(new Vector3f(4, 0, 0));

rootNode.addLight(light);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);



lightSphere.setLocalTranslation(light.getPosition());

}



private void prepareMaterials() {

refPtMaterial = new Material(assetManager, “Common/MatDefs/Misc/SolidColor.j3md”);

refPtMaterial.setColor(“Color”, ColorRGBA.White.clone());



wallMaterial = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

wallMaterial.setFloat(“Shininess”, 12f);

wallMaterial.setBoolean(“UseMaterialColors”, true);

wallMaterial.setBoolean(“HighQuality”, true);

wallMaterial.setColor(“Diffuse”, ColorRGBA.White.clone());

}



private void prepareControls() {

inputManager.addMapping(“MoveLightAway”, new KeyTrigger(KeyInput.KEY_R));

inputManager.addMapping(“MoveLightIn”, new KeyTrigger(KeyInput.KEY_F));



inputManager.addListener(this, new String[]{“MoveLightAway”, “MoveLightIn”});

}



@Override

public void onAnalog(String action, float value, float tpf) {

if(action.equals(“MoveLightAway”)) {

light.getPosition().x += tpf;

}

if(action.equals(“MoveLightIn”)) {

light.getPosition().x -= tpf;

}

}

}

[/java]



The Wall From before (for completeness, same as the wall from 2 posts ago):



[java]

<mesh>

<submeshes>

<submesh material=“Material” usesharedvertices=“false”>

<faces count=“32”>

<face v1=“0” v2=“1” v3=“2”/>

<face v1=“2” v2=“3” v3=“0”/>

<face v1=“4” v2=“0” v3=“3”/>

<face v1=“2” v2=“5” v3=“3”/>

<face v1=“0” v2=“4” v3=“6”/>

<face v1=“6” v2=“7” v3=“0”/>

<face v1=“1” v2=“0” v3=“7”/>

<face v1=“7” v2=“6” v3=“8”/>

<face v1=“9” v2=“10” v3=“11”/>

<face v1=“11” v2=“7” v3=“9”/>

<face v1=“8” v2=“9” v3=“7”/>

<face v1=“7” v2=“11” v3=“1”/>

<face v1=“12” v2=“8” v3=“6”/>

<face v1=“6” v2=“13” v3=“12”/>

<face v1=“14” v2=“12” v3=“13”/>

<face v1=“13” v2=“6” v3=“4”/>

<face v1=“15” v2=“16” v3=“17”/>

<face v1=“17” v2=“2” v3=“15”/>

<face v1=“1” v2=“15” v3=“2”/>

<face v1=“2” v2=“17” v3=“5”/>

<face v1=“15” v2=“1” v3=“18”/>

<face v1=“18” v2=“19” v3=“15”/>

<face v1=“16” v2=“15” v3=“19”/>

<face v1=“19” v2=“18” v3=“20”/>

<face v1=“21” v2=“22” v3=“23”/>

<face v1=“23” v2=“19” v3=“21”/>

<face v1=“20” v2=“21” v3=“19”/>

<face v1=“19” v2=“23” v3=“16”/>

<face v1=“24” v2=“20” v3=“18”/>

<face v1=“18” v2=“11” v3=“24”/>

<face v1=“10” v2=“24” v3=“11”/>

<face v1=“11” v2=“18” v3=“1”/>

</faces>

<geometry vertexcount=“25”>

<vertexbuffer positions=“true” normals=“true”>

<vertex>

<position x="-0.500000" y="-2.000000" z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z="-2.000000"/>

<normal x="-1.000000" y="-0.000000" z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y="-4.000000" z=“2.000000”/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“0.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y="-2.000000" z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-0.000000"/>

<normal x="-1.000000" y=“0.000000” z=“0.000000”/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-1.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“2.000000” z="-2.000000"/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

<vertex>

<position x="-0.500000" y=“4.000000” z=“1.000000”/>

<normal x="-1.000000" y=“0.000000” z="-0.000000"/>

</vertex>

</vertexbuffer>

</geometry>

</submesh>

</submeshes>

</mesh>

[/java]

Hello again!



I just wanted to know if anything had been done with this since I posted the test case? Is the above what you wanted? I wasn’t even sure if that was exactly what you needed to test with. I haven’t spent much more time on it myself as the answers are beyond my knowledge at the moment. I did play with the test case a bit more however and tried it with the jME3 pond.png texture (after making a different version of the wall with uv), and I observed the same problem ~ THOUGH, it was a lot harder to see with a texture on it. I had to look hard to see that the reflection highlight was warbling/distorting as it passed over edges at a very close proximity with the camera. Hell, I don’t even know if this is a fixable thing.



One thing that I guess should be mentioned is that it looks fine until the light gets close enough to start producing a reflection of the light.



Oh, and another thing, I added the pond_normal.png to the normal mapping and had some strange issues with the normal map seemingly being un-applied once the camera panned far enough away. I’m guessing this has something to do with the settings I was using (no idea where I stashed that other test case, probably on another machine), as I’m not too familiar with working with normal maps.



~FlaH

I know what the problem is.

The light direction is interpolated from vertex to vertex, rather than computed each time in the pixel shader.

It saves some instructions in the pixel shader so that is why this approach was adopted. However it causes artifacts when the light is too close to the vertices.



There’s no solution probably, unless we enable light direction computation in the pixel shader when HighQuality is specified.

This is a good idea.

Anyway, what is now the difference between HighQuality and LowQuality, and which is enabled by default? Also, I noticed that those 2 are not mutually exclusive. I mean, you can just enable both. What would that do? :slight_smile: