Draw New Texutre on Existing terrain

I would like to know if there is a way to draw each vertice on a terrainQuad instead of using a Material
or to
Draw my self on the material, so i can draw any texture i want on my terrain
For exemple a fonction i can call,
material.setMaterialVector2f(new vector2f(0,0), “MyTexture”);

1 Like

A geometry has to have one materialfor the entire geometry.

You might be able to do something using vertex parameters and a custom shader…

I know i can only have 1 material but can i decide where to draw the texture on the material? Exemple i want to make a fonction that will draw a road by it self , using the road texture directly on the terrainQuad

Yes, you can use the ImagePainter plugin to paint over the terrain texture at runtime.

you can do whatever you like…you might have to write a shader to do it though…

If you mean where to start the material… sure.

Modify the shader to accept a vec2(offsetX,offsetY) as a param and then add them to the textCoords.

Actually… you want to decal textures, correct? If so, this is not how you want to go about this. You’ll want to use partials of the original geometry for this.

Would it do what you want to just edit the alphamap image and change the splats that way? ie like you do in the SDK terrain editor when painting a terrain but doing it from within the application? As that is something I have done in my many experiments: I extracted the alphamap image, edited it, then applied it back into the terrain material.
I made a quick and dirty terrain editor that could re-paint the alphamap and swap out the different diffuse/normal maps associated with it or change their scale.
If that would work for you I could try to dig up my code.

my 2c :slight_smile:

Forgive the completely n00b question, but I would also like to be able to draw a random decal on my terrain, and all of these responses use terms I’m not familiar with. Could someone please point me at definitions of terms, or tutorials that explain these?

  • What is a vertex parameter?
  • What is a custom shader, and how would I go about creating one?
  • Where can I get the ImagePainter plugin? (It doesn’t seem to come with JME)
  • How do I modify a shader? What are textCoords, and how are they relevant here?
  • How do I “use partials of the original geometry”?
  • What does it mean to “edit the alphamap image and change the splats”? How can I extract the alphamap image and edit it programmatically?

Sorry if some of this is basic knowledge. I’ve gone through the ten-step newbie intro to JME, and (nearly) none of this is mentioned in any detail, that I could tell.

@roach374 said: Forgive the completely n00b question, but I would also like to be able to draw a random decal on my terrain, and all of these responses use terms I'm not familiar with. Could someone please point me at definitions of terms, or tutorials that explain these?
  • What is a vertex parameter?
  • What is a custom shader, and how would I go about creating one?
  • Where can I get the ImagePainter plugin? (It doesn’t seem to come with JME)
  • How do I modify a shader? What are textCoords, and how are they relevant here?
  • How do I “use partials of the original geometry”?
  • What does it mean to “edit the alphamap image and change the splats”? How can I extract the alphamap image and edit it programmatically?

Sorry if some of this is basic knowledge. I’ve gone through the ten-step newbie intro to JME, and (nearly) none of this is mentioned in any detail, that I could tell.

I can answer some of these:

  1. Well… there are three parts to a shader:
  • The Vertex Shader - This evaluates each vertice in the geometry being rendered
  • The Geometry Shader - This doesn’t matter at the moment, because we have no access to geometry shaders
  • The Fragment Shader - The is the program that does per pixel shading of the model

A Vertex Parameter is more than likely referring to an input parameter of the Vertex shader.

  1. The best way of learning these is to look through the shaders available in JME. @nehon has done some really awesome work there and you can’t go wrong using those as examples. As you go through them, search the forums, as most questions you have have already been asked and answered. But if you get stuck and can’t find the answer… ask specifics and you’ll get specific answers.

  2. In the SDK. Under Tools > Plugins. Check through the list. You’ll see it there as a downloadable plugin.

  3. To modify a shader, you’ll need 3 parts (in JME that is).

  • A Material Definition file (j3md)
  • A Vertex Shader - someVertShader.vert
  • A Fragment Shader - someFragShader.frag

Again, use JME’s default shaders as an example… Google, Documentation here and the Forum will help you through this.

Texture Coordinates are a a number between 0.0 and 1.0 for both the X and the Y coord. For each UV mapped vertice in the model being rendered, there is a texCoord that represents a place in the texture image - as a percentage (0.0 being 0% 1.0 being 100%) Texture lookups are not single pixels… they are a section of the image… could be 4 pixels, parts of 4 different pixels, or a 4th of a pixel. It depends on the image stretching from the UV mapping.

Hope this sorta help explain it.

  1. There are multiple ways of breaking apart a geometry. You’ll need to get familiar with what a Mesh is… extending the Mesh class (there is a portion of the tutorials that covers custom Meshes). I would try working Bounding and .contains() as a first guess at breaking apart complex Geometries. There is a project that someone is working on here that does decaling… and from the look of the vid, I think he is using this approach.

  2. You can apply multiple textures to a single geometry with the use of one Material, by using texture lookups and then blending the results of the different lookups. An alpha map is usually greyscale and used to override the alpha channel of the lookup for one of the textures. Black = 0.0, White = 1.0… if you multiple the alpha channel of the texture lookup by the alphamap color white is opaque, black is transparent and shades of grey are inbtween:

[java]
// The final frag color’s alpha channel * the red channel of some alphamap texture loopup result.
gl_FragColor.a *= texture2D(someSampler2D, theTexCoordForThisFrag).r;
[/java]

If you want to edit the alpha map, use ImpagePainter orImageRaster .getPixel / .setPixel … and then pass the updated image into the shader each render loop:

[java]
mat.setTexture(“AlphaMap”, myEditedImage); // AlphaMap is a made up uniform name… this depends on the shader, whether it makes use of alpha maps and what the dev decided to name the uniform
[/java]

2 Likes

All good, everyone’s a noob at first, as long as you’re willing to learn and try.
I can only elaborate on the point I brought up about editing the Terrain Alphamap as it’s what I’ve done work on. never touched shaders yet.

note tho: Altering the Alphamap is really only for making more permanent changes to the landscape textures, like painting in a road or putting in some “grass/dirt/rock” textures. So for temporary decals or images then probably not the way to go.

ImagePainter is a plugin, add it in using netbeans plugin system, (hint: Tools -> Plugins -> Available Plugins) I’ve not used it myself yet so can’t say more than that.

For Temporary decals maybe search this forum for the Projective Texture Mapping Plugin, maybe that’s what you need? That plugin is on my to research list :wink:

As for the AlphaMap this was my method (not saying its right but it worked for me - no image painter at that time :stuck_out_tongue: ):

[java]

/**
 * Paint the Splat AlphaMap of a TerrainQuad
 * 
 * @param tx    x location on terrain (0 to terrain size)
 * @param tz    z location on terrain (0 to terrain size)
 * @param terrain   TerrainQuad to alter
 * @param value     Value to paint as follows:
 *                      0 = Red (diffuse_0 texture)
 *                      1 = Green (diffuse_1 texture)
 *                      2 = Blue (diffuse_2 texture)
 *                      3 = Alpha (diffuse_3 texture)
 */
private void PaintSplat(int tx, int tz, TerrainQuad terrain, int value) {
    byte b1 = (byte) 0xFF;
    byte b0 = (byte) 0x00;
    Material cMat = terrain.getMaterial();      // get the material from terrain
    Texture aTex = (Texture) cMat.getParam("AlphaMap").getValue();  // get the AlphaMap texture
    Image aImg = aTex.getImage();   // get the Image from the Texture
    ByteBuffer aBuf = aImg.getData(0);  // Get the image as a bytebuffer to read/write
    int iW = aImg.getWidth();   
    int iP = (tz * iW + tx) * 4;    // calculate the point in the buffer for the point we want
    if (iP > aBuf.capacity() - 1) {
        System.err.print("outside buffer!" + iW);
        return;
    }
    aBuf.position(iP);
    if (value == 0) {
        aBuf.put(b1);
    } else {
        aBuf.put(b0);
    }
    if (value == 1) {
        aBuf.put(b1);
    } else {
        aBuf.put(b0);
    }
    if (value == 2) {
        aBuf.put(b1);
    } else {
        aBuf.put(b0);
    }
    if (value == 3) {
        aBuf.put(b1);
    } else {
        aBuf.put(b0);
    }
    aImg.setData(aBuf);     // set the modified buffer back into the Image
    aTex.setImage(aImg);    // set the Image back into the Texture
    aTex.getImage().setUpdateNeeded();
    cMat.setTexture("AlphaMap", aTex);  // set the Texture back into the Material
    terrain.setMaterial(cMat);  // set the Material back into the Terrain
}

[/java]
Please forgive the code, its a little old and I took most of the ideas at the time from reading over the source code for the Terrain Editor in the jMe SDK :slight_smile:

And that’s how I learnt all what I have so far, reading posts, searching the forums and combing over the javaDoc and the core source code.
That’s about all I can elaborate on so far without specifics. Happy to explain on why for any part of the code here… or try to :slight_smile:
Thanks.

Guys, thanks so much for your answers, they’re really helping my understanding!

To the point about ImagePainter: It may help to clarify that I’m not using the JME IDE, I’m using Eclipse. My ultimate goal is to be able to generate textures (or JME “Image” instances) programmatically, and paint them on the terrain in a non-permanent way. In this example, I’m trying to generate a sort of “heat map” texture that the user can show or hide over an existing terrain Quad, like a population map, crime rate map, property values, etc (think SimCity).

thanks again!

If you cannot use ImagePainter, you could simply write a BufferedImage, and convert it to JME image using the AWTLoader class. Not so sexy, but quite easy yet.
Otherwise, you may have to download the plugin manually (a simple JAR) and add it to your classpath.

@yang71 said: If you cannot use ImagePainter, you could simply write a BufferedImage, and convert it to JME image using the AWTLoader class. Not so sexy, but quite easy yet. Otherwise, you may have to download the plugin manually (a simple JAR) and add it to your classpath.

I wasn’t familiar with this class. Thanks!

ImagePainter is just a jar library, you can use it from eclipse. The SDK makes it easy to get hold of it though as you can just turn on the plugin and have it downloaded automatically.

@zarch said: ImagePainter is just a jar library, you can use it from eclipse. The SDK makes it easy to get hold of it though as you can just turn on the plugin and have it downloaded automatically.

Thanks! Any word on where I could download this as a non-plugin? The original thread (I think? http://hub.jmonkeyengine.org/forum/topic/image-painter-plugin-available/ ) Doesn’t actually provide a link…

EDIT: Also can’t seem to find it anywhere in the JME repo: Google Code Archive - Long-term storage for Google Code Project Hosting. Am I looking in the right place?

It’s in the plugins (contributions) repository, not the core one.