Grass doesn't Draw transparent correctly (Old code from someone else)

I’m trying to use some one else grass code with it shader but it doesn’t seem to draw correctly.
It doesn’t draw completely transparent on a side and the other way it will not be transparent at all.
I may have done a mistake some where… It s not the first time i have a hard time with the Transparency. I did try to put Transparent bucket or Translucent. I ve tryed every alpha mode possible too.

Undesired result:

The code I testing the grass with:

package LostWorld.grass;

import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;

import java.util.Random;

import jme3tools.optimize.GeometryBatchFactory;

public class CustomGrassTest extends SimpleApplication {

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

    private float elapsedTime = 0;
    private Material grassShader;
    private Geometry grassGeom;
    private Node allGrass = new Node("all grass");
    private Vector2f windDirection = new Vector2f();
    private float windStrength;
    private Random random = new Random();
    private Geometry ground;

    public void simpleInitApp() {
        
//        FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
//        TranslucentBucketFilter tbf = new TranslucentBucketFilter();
//        tbf.setEnabled(true);
//        fpp.addFilter(tbf);

        DirectionalLight light = new DirectionalLight();
        light.setColor(new ColorRGBA(0.9f, 0.9f, 0.9f, 1.9f));
        light.setDirection(new Vector3f(0.7f, 0.8f, 0.7f));
        this.getRootNode().addLight(light);

        DirectionalLight otherlight = new DirectionalLight();
        otherlight.setColor(new ColorRGBA(0.9f, 0.9f, 0.9f, 1.9f));
        otherlight.setDirection(new Vector3f(-0.7f, 0.8f, -0.7f));
        this.getRootNode().addLight(otherlight);

        this.getFlyByCamera().setMoveSpeed(10);
        ground = new Geometry("ground", new Quad(10, 10));
        ground.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"));
        ground.getMaterial().setColor("Color", ColorRGBA.Brown);

//Texture t = assetManager.loadTexture("Textures/Terrain/grass.dds");
//t.setWrap(Texture.WrapMode.Repeat);
//ground.getMaterial().setTexture("ColorMap", t );
        ground.setLocalTranslation(0, 0, 10);
        ground.rotate(-90 * FastMath.DEG_TO_RAD, 0, 0);
        rootNode.attachChild(ground);

        windDirection.x = random.nextFloat();
        windDirection.y = random.nextFloat();
        windDirection.normalize();

        grassGeom = new Geometry("grass", new Quad(2, 2));

        grassShader = new Material(assetManager, "MatDefs/Grass/MovingGrass.j3md");
        Texture grass = assetManager.loadTexture("Textures/Grass/grass.png");
        grass.setWrap(Texture.WrapAxis.S, Texture.WrapMode.Repeat);
        grassShader.setTexture("Texture", grass);
        grassShader.setTexture("Noise", assetManager.loadTexture("Textures/Grass/grass.png"));

// set wind direction
        grassShader.setVector2("WindDirection", windDirection);
        windStrength = 1.0f;
        grassShader.setFloat("WindStrength", windStrength);

        grassShader.setTransparent(true);
        grassShader.getAdditionalRenderState().setAlphaTest(true);
        grassShader.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);
        grassShader.getAdditionalRenderState().setAlphaFallOff(1f);
//        
        
        grassShader.setColor("Color", new ColorRGBA(0.53f, 0.83f, 0.53f, 1f));
        grassShader.setFloat("Time", 0);

        grassShader.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
        grassGeom.setQueueBucket(Bucket.Opaque);
        grassGeom.setMaterial(grassShader);
        grassGeom.center();

        Node[][] grassArray = new Node[10][10];
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {

                grassArray[i][j] = new Node(i+"-"+j);
                
                for (int y = 0; y < 10; y++) {
                    for (int x = 0; x < 10; x++) {
                        Geometry grassInstance = grassGeom.clone();

                        grassInstance.setLocalTranslation(x+i*10 + (float) (Math.random() * 1f), 0, y+j*10 + (float) (Math.random() * 1f));
                        grassInstance.scale(0.4f, 0.4f + random.nextFloat() * .2f, 0.4f);
                        grassArray[i][j].attachChild(grassInstance);

                        Vector3f v3f = grassInstance.getLocalTranslation();
                        grassInstance = grassGeom.clone();

                        grassInstance.setLocalTranslation(v3f.add(0.4f, 0, 0.4f));
                        grassInstance.scale(0.4f, 0.4f + random.nextFloat() * .2f, 0.4f);
                        grassInstance.rotate(0, FastMath.DEG_TO_RAD * 90, 0);
                        grassArray[i][j].attachChild(grassInstance);
                    }
                }
                allGrass.attachChild(grassArray[i][j]);
            }
        }

        Spatial grassNode = GeometryBatchFactory.optimize(allGrass);
        grassNode.setQueueBucket(Bucket.Translucent);
        grassNode.setMaterial(grassShader);
//        grassNode.updateModelBound();

        rootNode.attachChild(grassNode);

    }

    @Override
    public void simpleUpdate(float tpf) {
        elapsedTime += 0.001;
        grassShader.setFloat("Time", elapsedTime);
    }
}

The Shader Frag:

#ifdef TEXTURE
uniform sampler2D m_Texture;
varying vec2 texCoord;
#endif
 
uniform vec4 m_Color;
 
void main(void)
{
#ifdef TEXTURE
vec4 texVal = texture2D(m_Texture, texCoord);
gl_FragColor = texVal * m_Color;
#else
gl_FragColor = m_Color;
#endif
}

The Shader Vert:

uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldViewMatrix;
uniform vec4 g_LightColor;
 
uniform float m_Time;
uniform float m_WindStrength;
uniform vec2 m_WindDirection;
uniform vec3 m_ObjectCenter;
uniform vec3 m_CamPos;
 
uniform sampler2D m_Texture;
uniform sampler2D m_Noise;
uniform vec4 m_Color;
 
attribute vec2 inTexCoord;
 
attribute vec3 inPosition;
 
 //this is erroring
uniform float moveFactor = 0.06; // Play around with this
 
varying vec2 texCoord;
varying vec4 color;
 
#ifdef VERTEX_COLOR
attribute vec4 inColor;
#endif
 
void main()
{
vec3 displacedVertex;
displacedVertex = inPosition;
texCoord = inTexCoord;
 
float len = length( displacedVertex );
 
float noiseCoord = m_Time;
 
int totalTime = int(m_Time);
if (totalTime > 4096) totalTime -= 4096;
 
int pixelY = int(totalTime/64);
int pixelX = totalTime/ -pixelY;
float noiseFactor = texture2D(m_Noise, vec2( pixelX*10, pixelY*10 ) ).r;
// get pixel from noise map based on time. use to create additional variation
 
vec3 wvPosition = (g_WorldViewProjectionMatrix * vec4(displacedVertex, 1.0)).xyz;
 
if(inPosition.y>=0.1)
{
displacedVertex.x += moveFactor * sin(m_Time * texture2D(m_Noise, wvPosition.xz*50.0).r + len) + (m_WindStrength * noiseFactor * m_WindDirection.x)/10.0;
displacedVertex.z += moveFactor * cos(m_Time * texture2D(m_Noise, wvPosition.zx*50.0).r + len) + (m_WindStrength * noiseFactor * m_WindDirection.y)/10.0;
}
 
gl_Position = g_WorldViewProjectionMatrix * vec4(displacedVertex, 1.0);
 
 
#ifdef VERTEX_COLOR
color = m_Color * inColor;
color.rgb *= g_LightColor.rgb;
#else
color = m_Color;
color.rgb *= g_LightColor.rgb;
#endif
 
}

…doesn’t do anything anymore.

You have to use a discard threshold in the shader now. The JME shaders all have this but you’ll have to add it to this grass shader, I guess.

ALright i’m not quite familiar with the shader stuff, I will try to copy from the lighting shader i supose.
Thank you. I was looking at the Tutorial you did for transparency but it didn’t seem like i did something wrong. Do i have to increase the GLSL? Or at 120 it should be fine?

It has nothing to do with shader versions. AlphaTest was a deprecated feature of OpenGL and not available on some platforms so it was ‘nerfed’.

I did add the Parameter to the material (.j3md) But it doesn’t seem to work with just this. Is there something else I need to add? (to the .vert or .frag?)

MaterialDef Grass2 {
 
MaterialParameters {
Texture2D Texture
Texture2D Noise
Vector4 Color
Float Time
Float WindStrength
Vector2 WindDirection
Boolean Use_VertexColor
Vector3 CamPos
// Alpha threshold for fragment discarding
Float AlphaDiscardThreshold (AlphaTestFallOff)
}
 
Technique {
LightMode SinglePass
VertexShader GLSL120:   MatDefs/Grass/MovingGrass.vert
FragmentShader GLSL120: MatDefs/Grass/MovingGrass.frag
 
WorldParameters {
WorldViewProjectionMatrix
WorldViewMatrix
}
 
Defines {

TEXTURE : Texture
VERTEX_COLOR : Use_VertexColor
DISCARD_ALPHA : AlphaDiscardThreshold
}

}
}

Yes… you’d need to modify the shader to use it. What you’ve done is the equivalent of adding a new parameter to method but then not using it in the method. Material parameters are just parameters. Adding them just means you can use that parameter in your shader.

I m trying to read all the Jme shader and i can’t find how you guys work with the AlphaDiscardThreshold param. Is there a way you could give me a link to read about this or the file name to import please?

You looked at Ligihting.frag or Unshaded.frag and you can’t see how AlphaDiscardThreshold is used? I’m not sure I can help you then.

Alright i will look closer at them thank you for the tip!

…I mean, just hit ctrl-f and type AlphaDiscardThreshold… you will find the mentions of it pretty clearly. Just not sure how you were looking before but maybe you need a text editor with a search button?

I got it to work with transparency but Since I don’t know GLSL I created a bug i think…

Thank you for the help with the code, I wasn’t able to find at first even with the Searching since i didn’t know how Material Definition worked.

https://www.youtube.com/watch?v=POjmOwYaD1Q&feature=youtu.be