Deform surface, Vertex Shader, How?

I am trying to deform mesh using vertex shader but some how its not working.
What I am trying to do in code is as below

  1. passing the point as pick point and radios to deform surface
  2. passing boolean parameter to switch deformation
  3. in vertex shader calculating the current position, if its around picked point withing radios on X, Z than change the Y position of the current position

Also what is the result of “CollisionResults.getContactPoint()” ? is it point of mesh surface or related to boundingbox? is it world coordinate or local coordinate?

Java Code

    Spatial surface = assetManager.loadModel("Models/BaseSnow/BaseSnow.j3o");
    Material mat = new Material(assetManager, "MatDefs/Deform/Deform.j3md");
    mat.setTexture("ColorMap", assetManager.loadTexture("Models/BaseSnow/sparkling-snow-texture.jpg"));
    mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
    mat.setBoolean("DoDeform", true);
    surface.setMaterial(mat);
    rootNode.attachChild(surface);

    inputManager.addMapping("RIGHT_CLICK", RIGHT_CLICK);
    inputManager.addMapping("LEFT_CLICK", LEFT_CLICK);
    inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {

        if (name.equals("RIGHT_CLICK")) {

        } else if (name.equals("LEFT_CLICK")) {
            Ray ray = new Ray(cam.getLocation(), cam.getDirection());
            CollisionResults results = new CollisionResults();
            int resCount = surface.collideWith(ray, results);
            if (resCount > 0) {
                Vector3f point = results.getClosestCollision().getContactPoint();
            //    point = surface.worldToLocal(point, new Vector3f());
            //    point = surface.localToWorld(point, new Vector3f());
                point.setY(point.y / 2);
                System.out.println(point);
                mat.setVector3("PickPoint", point);
                mat.setFloat("Radios", .5f);
                
            }
        }

    }, "RIGHT_CLICK", "LEFT_CLICK");

}

J3MD

MaterialDef Simple {
MaterialParameters {
    Color Color
    Texture2D ColorMap
    Vector3 PickPoint
    Vector3Array PointsToDeform
    Float LowestHeight
    Float HeighestHeight
    Float Radios 
    Boolean DoDeform
}
Technique {

    VertexShader GLSL100: MatDefs/Deform/Deform.vert
    FragmentShader GLSL100: MatDefs/Deform/Deform.frag

    WorldParameters {
        WorldViewProjectionMatrix
        WorldViewMatrix
        Time
    }

    Defines {
        COLOR : Color
        COLORMAP : ColorMap
    }
}
}

Vertex Code

    attribute vec3 inPosition;
    attribute vec4 inTexCoord;
    attribute vec3 inPickPoint;
    attribute float inLowestHeight;
    attribute float inHeighestHeight;
    attribute float inRadios;
    bool inDoDeform = false;
    uniform mat4 g_WorldViewProjectionMatrix; 
    uniform mat4 g_WorldViewMatrix; 
    uniform float g_Time;
    varying vec4 vertextPosition;
    varying vec4 texCoord;
    void main() {
        texCoord = inTexCoord;

        if(inDoDeform) {

            float dx = inPickPoint.x - inPosition.x;
            float dy = inPickPoint.z - inPosition.z;
            float distanceSquared = (dx * dx + dy * dy);
            float distance = sqrt(distanceSquared);

            float pickY = inPickPoint.y;
            float posY = inPosition.y;

            if(distance <= inRadios && pickY < posY){
            if(inPickPoint.x == inPosition.x){
                vec3 newPos = vec3(inPosition.x, pickY, inPosition.z);
                vec4 position = vec4(newPos, 1.0);
                gl_Position = g_WorldViewProjectionMatrix * position;
            } else {
                gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
            }
        } else {
    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
        }
    }

Frag Code

#ifdef COLOR
uniform vec4 m_Color;
#endif

#ifdef COLORMAP
uniform sampler2D m_ColorMap;
#endif

varying vec4 vertextPosition;
varying vec4 texCoord;

void main() {

vec4 color  = vec4(1.0);
#ifdef COLOR
color = m_Color;
#endif

#ifdef COLORMAP
color *= texture2D(m_ColorMap, texCoord.xy);
#endif

gl_FragColor = color;
}

Collisions are in world space. You will need to convert inPosition to world space or convert your collision position to model space.

Also, note that with this approach if your surface is lit then you won’t be able to fix the normals, really. I’m just guessing that you’d ultimately want this because of your other thread.

Yes your guess is correct, I want to do the same using shader as mentioned in other thread.
I doubt, my shader code is not correct. I thing whatever parameters i am passing through material in java are not passing to vertex shader.
I tried converting coordinates to world to local but its not working. I am not sure how to solve this…
The other thread…

Well, you should post the code that actually tests what you intend to show.

It’s hard for us to guess what random things you’ve tried so we’re just going to keep pointing out the dozen little things that “Oh, I’ve changed that and it didn’t work.” So post your best guess and we’ll work from there.

…but collision coordinates are definitely in world space.

Here is whole code and required files to run. Please download from this link.


<div style=font-size:9px;font-family:Arial, Helvetica, sans-serif;width:127px;font-color:#44a854;> file storage online

Do I need to pass value for “inPosition” manually?

I found the issue and fixed it… the vertex shader script war wrong.

To help others, what was the issue you found?

here are some mistakes that one should avoid while writing shader program (For novice like me).

  1. I wanted to pass parameters from java code to shader program, for that I placed some variable in vertex shader script and and J3MD file. To use any material parameter the variable name should start with prefix ‘m_’ while I used prefix ‘in’ considering ‘in’ is for input… :expressionless:
  2. Made confusion between local coordinates and world coordinates.

The “in” prefix is specifically for vertex attributes in JME.

I believe all of this was covered in one of the shader tutorials but I could be wrong. I know one of the monkeys wrote a “shaders for beginners” tutorial a long time ago.

Also, here are some advices:

  • Use branching as few as possible. Several embedded “if” can be a perf killer in a shader depending on the hardware drivers. You may want to use a Define for your “DoDefrom” parameter.
    in the J3md:
MaterialParameters {
    ...
    Boolean DoDeform
}
...
   Defines {
       DO_DEFORM : DoDeform
   }

then in the shader you can use pre-porcessor directives like this

#ifdef DO_DEFORM
    //your deform code here
#endif

This if will be evaluated at compilation time and not at runtime and will produce the appropriate shader.

Also another tip to avoid defines: use the step() function. https://www.opengl.org/sdk/docs/man/html/step.xhtml
It’s bit tricky to get right sometimes, but can help you to avoid “if” like if ( x> y ) value = 1.0;

Here, the shader tutorial series pspeed is talking about (or that is what I think. Anyway, it helps you to start with them).