jMonkeyEngine / jmonkeyengine

A complete 3-D game development suite written in Java.
http://jmonkeyengine.org
BSD 3-Clause "New" or "Revised" License
3.78k stars 1.12k forks source link

Flat shading terrain quad #205

Closed hunterboerner closed 9 years ago

hunterboerner commented 9 years ago

Is there a way to render a TerrainQuad without the smooth shading. I am trying to create a low-poly game and it needs to be flat shaded. I'm generating the terrain from perlin noise so the SDK can't help me.

Thanks

Relic724 commented 9 years ago

Hello hunterboerner, I might be able to help guide you, though I'm kind of vague on the flat shaded... On the off chance that you are referring to pixel shader ops for anti-aliasing you might want to look into JME3's TextureFilter.MinFilter.NearestNoMipMap (or NearestNearestMipMap) and MaxFilter.Nearest. That will tend to give color texture maps a pixelated look similar to Minecraft and old PS1 games. // probably would look like this..

    Texture2D offTex = new Texture2D(512, 512, Image.Format.RGBA8);
    offTex.setMinFilter(Texture.MinFilter.NearestNoMipMap);
    offTex.setMagFilter(Texture.MagFilter.Nearest);

If you are looking to alter how light is calculated off of the surface, you might want to try either using one of the preset jme3 material shaders like good ol' unshaded.

    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.White);
    mat.setTexture("ColorMap", osrdiffuseMap);

In that material definition, it kind of translates to saying I want 100% lighting (white) on a color map that I am providing called osrdiffuseMap[edit] which is a Texture2D, btw... I don't even know if that's important to mention...[/edit]. Then I just set the material to the geometry and add it to my base node. Um, other than that you might still want shading and I think there is one that just shades on the vertex level, but not smoothly on the pixel level (kind of like FF7 for ps1 where you can easily see vertex angles on the shading.) I don't remember which preset material it's called though.

[edit]: Note: I haven't worked with the TerrainQuad class yet, so I don't know if you can handle it like a geometry... This tip may be completely useless. In which case -> Doh!

Hope this helps, Charles Anderson

hunterboerner commented 9 years ago

@Relic724 yeah, we still want there to be lighting. I guess it may be easier to build the terrain in blender with flat lightning and then import it into JME. If I do that, do you know if I am able to edit the coords of the mesh verticies after the fact (for mutable terrain and stuff)?

hunterboerner commented 9 years ago

As a side note, the JME SDK won't open on mac. It gets stuck at Loading Modules.

Relic724 commented 9 years ago

@hunterboerner Ok, so lighting it is then. It might be easy to import from blender with the material that you are wanting... but... if you would like to affect the mesh procedurally, there will be an amount of code written that may approach "from scratch" to work with it.

So, with that said, I'll throw out some more tips that might help you along with code: 1.I usually got confused when folks bandied about terms that had different meanings when used with a different graphics engine setup. So, a material in blender is a shader in opengl is a material ->material definition with options activated->selection of vertex/fragment opengl shader with supplied data linkups in jmonkeyengine is a texture in DirectX... erg.... AKA. they picked a lot of words that overlapped when they individually made the engines. It makes sense when we figure out what each term means for the specific engine, and throws us for some "confuzzlement" if someone speaks with the lingo from another. For these tips I will be talking on (JME3) materials.

2.to get the lighting that you desire for your game, make note of the fact that you will be working with (OpenGL) shaders ultimately. A (Blender)Material might be translated(<- I've been making Netbeans code so my memory is fuzzy, LOL And I'm not a core member, just someone who has worked with it.) to a (JME3)Material and put it in the Materials folder as a .j3m file... which will probably reference a (JME3)Material Definition .j3md file in the MatDefs folder... which will probably reference (OpenGL)Vertex Shader and (OpenGL)Fragment Shader as .vert and .frag files respectively in your Shaders folder. And all of those files produced are ultimately, OpenGL. yay! That's the core concept to help you along on getting your lighting correctly "awesome". If you want to look at the code behind the JME3 presets, you can view the files that are currently under construction here at Github: https://github.com/jMonkeyEngine/jmonkeyengine/tree/master/jme3-core/src/main/resources/Common or in the jme3-core import library for your working installation: commonlocation

3.yes, you can "edit" the coords of a mesh "on the fly" procedurally. Just remember that a (JME3) Geometry is a sublcass of (JME3) Spatial containing its own (JME3) Mesh. (JME3) Material, and (JME3) Bounding Volume. You would probably be focusing on the (JME3) Mesh which contains the (JME3) VertexBuffer, which contains the coords of your vertices. From there I can only think that you might use the cloneForAnim() method, adjust the coords of the clone and "swap out" meshes by queueing it up into the graphics handling thread. I have not worked too deeply with JME3's threading model so I can't refer you to the proper thread manager class, yet. I do know that you cannot work on memory locations that are "locked" by the GPU. You can prepare a new memory location with altered data and switch the GPU over to the new location when it goes to prepare the next frame, however.

4.As far as the Mac issue... I have windows, I'm not core. I just know that I d/l'd my installation from: http://hub.jmonkeyengine.org/downloads/ and I noticed that they had an SDK available for mac, but that's about all the help that I can be... so hand off to someone else on that one...., sorry.

Hope that helps, Charles Anderson

hunterboerner commented 9 years ago

Ok, thanks. When I looked at the JME forums about flat shading, they were always talking about how smooth shading will be used automatically because there are shared vertexes. I don't know what that means, but from what I understand it's not the shaders that are controlling smooth/flat shading, it's JME.

Does that make sense?

Relic724 commented 9 years ago

ah, I think I know what you are meaning by flat shading, now.

I've worked with Blender enough to get the gist of what you are wanting now. By (Blender?)flat shading you might be referring to the way that surface normals are handled. As an example, lets try refining this on an icosphere, a mesh that kind of resembles a soccer ball -ish shape. With flat shading in Blender, you can see the edges clearly because (Blender)normals are calculated per (Blender) Face so that each (Blender) Face responds to the light on it's own. It looks like a good ol' icosphere with flat sides. With smooth shading in Blender, the surface normal becomes interpolated to the (Blender) vertex normal by averaging all the (Blender) Face normals for faces that share the same vertex. Then that is linearly smoothed across a face for all vertex normals in Blender's shading system. The result is something that might look like a sphere if not viewed too closely. It works this way in Blender, mainly because I don't think they wanted to store normals, in the first place.

And, you are correct in your assumption that JME controls smooth/flat shading, but incorrect that it's not the shaders. When you assign a material to a geometry in JME, you are also assigning the shader used to calculate the display of the underlying mesh. This isn't immediately apparent, but you can see the relationship when you look at how Mesh and it's underlying VertexBuffer[s] of the various VertexBuffer.type[s] will be shipped off to the associated Material(which boils down to .vert and .frag) for rendering.

So, my final tip that I can think of, is your ultimate solution to do what you will want is that you will handle your surface normals (per face) rather than JME3's default (per vertex with linear smoothing). Yes, JME3 handles the data underlying what is shaded: The basic data of coords(vertices), UV position that the vertex has on a texture2D = (Blender) UVMap, Vertex Normals (Not Stored in Blender), and a lot of other things that you can see in the com.jme3.scene.VertexBuffer.class. but It is the shader you choose/create that displays how all that information is displayed in your graphics. The shader uses/ignores (JME3)VertexBuffer[s] and (JME3)Texture2D[s] to calculate/interpolate the color per pixel on the screen. ... whew!

oh... and JME3 also handles shading by linking shader to mesh when you assign your material, if that makes any sense.

so, get ready to go beyond default settings. Your next step in the learning curve will probably to learn how JME3 passes the vertex data (and other buffers) over to the shaders (which starts with .j3m and progresses all the way down to .vert and .frag <- all of which are viewable in a normal text editor) and be ready to learn OpenGL to create the shader for "the look" you want. You'll be able to do it, and just be ready for brain sprains on the math. LOL.

[edit] TerrainQuad might be assigning these materials->shaders in it's code, in which case, it's time to extend the class and override some methods with your own material/shader assignments. or, you can create your own class, as you like. [/edit]

Game On, Charles Anderson

hunterboerner commented 9 years ago

Whew. Looks like I may have to push more of the visual stuff back on my todo list.

A somewhat unrelated question: I'm having some trouble understanding how the indexes for a mesh work. Say I have a 3x3 heightmap that I want to turn into a mesh, what order do I connect the vertexes in? Would it be 1,4,5, 1,2,5, 2,5,6, 2,3,6, 4,7,8, 4,5,8, 5,8,9, 5,6,9? (Image of what I'm talking about below)

grid

oh, and cartman3

Relic724 commented 9 years ago

haha, lol. love the cartman!

That would be the classic Left Hand vs. Right Hand coordinate system question. the search terms for that question could also be called Clockwise vs CounterClockwise Culling.

Default for JME3 is Clockwise Culling(eg it displays all triangles that are counterclockwise), if I remember correctly. That said, it can be set either way that you like by something similar to: myGeometry.getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front); //or .Back for CounterClockwise Culling or .FrontAndBack if you want to look back and see the back side of what you just went through.... lol. [edit] oops I got it backwards on the cullMode Statement, it is Culling, after all, the default is .Back for culling all clockwise triangles, .Never displays both sides[/edit]

so your vertices order for default behavior would properly be... (1,4,5),(1,5,2),(2,5,6),(2,6,3),(4,7,8)....etc. (always counter-clockwise) to display. if the order becomes clockwise, then it becomes culled. [edit] and for the purpose of display, (1,4,5) is similar in behavior to (4,5,1) is similar to (5,1,4) [/edit]

Game On, Charles Anderson

hunterboerner commented 9 years ago

Ok, so it looks like the TerrainQuad ends up telling the terrainpatch to calculate new normals in this method:


    /**
     * recalculate all of the normal vectors in this terrain patch
     */
    protected void updateNormals() {
        FloatBuffer newNormalBuffer = geomap.writeNormalArray(null, getWorldScale());
        getMesh().getBuffer(Type.Normal).updateData(newNormalBuffer);
        FloatBuffer newTangentBuffer = null;
        FloatBuffer newBinormalBuffer = null;
        FloatBuffer[] tb = geomap.writeTangentArray(newNormalBuffer, newTangentBuffer, newBinormalBuffer, (FloatBuffer)getMesh().getBuffer(Type.TexCoord).getData(), getWorldScale());
        newTangentBuffer = tb[0];
        newBinormalBuffer = tb[1];
        getMesh().getBuffer(Type.Tangent).updateData(newTangentBuffer);
        getMesh().getBuffer(Type.Binormal).updateData(newBinormalBuffer);
    }

What do I need to change to get the right normals needed for flat shading (or am I looking in the wrong place?)?

Relic724 commented 9 years ago

That code looks to be where they make an allowance for the dynamic vertex adjustment you were wanting for your project.

What you are looking for are (JME3)Material assignments. It's the shader code that can use/ignore these normals for the look you are wanting.

hunterboerner commented 9 years ago

So do I need to mess with the normals or just modify the lighting shaders?

Relic724 commented 9 years ago

Just modify the lighting shaders.

jmaasing commented 9 years ago

Much higher chance of getting an answer if you post these types of questions on the forum rather than using the issue tracker: http://hub.jmonkeyengine.org/forum/

Relic724 commented 9 years ago

Indeed, this is a Forum type topic.

hunterboerner commented 9 years ago

I can't because the forum won't send me a confirmation email :{

Relic724 commented 9 years ago

[edit] and poof, but yeah, try again is all i can suggest [/edit]

erlend-sh commented 9 years ago

@hunterboerner still having problems? I've found your user on our forum. If you'd like I can manually approve you with a temporary password.

hunterboerner commented 9 years ago

That would be helpful. I know Charles said he could help me if I emailed him but two minds are greater than one. On Sun, Jan 4, 2015 at 5:57 AM Erlend Sogge Heggen notifications@github.com wrote:

@hunterboerner https://github.com/hunterboerner still having problems? I've found your user on our forum. If you'd like I can manually approve you with a temporary password.

— Reply to this email directly or view it on GitHub https://github.com/jMonkeyEngine/jmonkeyengine/issues/205#issuecomment-68630384 .

Relic724 commented 9 years ago

@erlend-sh oh, and I'm tossing my hat into the ring for assisting with the forum after the server reset incident. [edit] [/edit]

I thought it(the forum) would be cleared up by now, but it seems to be taking a bit. I'll help you out if I can be of assistance to speed the recovery. I know the whole php/mySQL/javascript/css pipeline from previous web projects.