[SOLVED] Make the same shader compatible with multiple glsl versions

I have a shader with some code that is compatible only with glsl 4 and i want to provide some fallback code for older cards.
I know i can use __VERSION__ to check the version that is used to run the shader, but i don’t know what i am supposed to use as version in the matdef.
Currenty i use:
FragmentShader GLSL400
My questions are:
Will this work fine with glsl 1.5 cards, provided that i exclude the glsl4 code with a preprocessor directive that checks for __VERSION__ ?
Or will it refuse to compile because i’ve set GLSL400 in the j3md? If so how can i tell jmonkey to use the latest available version no matter what it is, or if this is not possible, how can i provide an alternative shader for older versions?

I’m still learnibg the GLSL and matdef stuff, but as far as I understand it you can define multiple shaders:
FragmentShader GLSL400 FragmentShader GLSL150
Jme will then fall back to the nearest lower version than the supported.

Thanks for the reply, i’ve just tried this, the second declaration replaces the first one, no matter what

Hmm… Have you tried declairing lower version first?
Maybe some core dev can help here?

Did you try to have separate Techniques for different versions?

Aren’t shader nodes supposed to solve this problem?

From what I read you can specify multiple GLSL versions for 1 shader node.

https://jmonkeyengine.github.io/wiki/jme3/advanced/jme3_shadernodes.html

I’d like to do it without shader nodes.

I will check this, i’ve never used techniques.

Just out of curiosity. Why do you want to do it without shader nodes?

Personal taste.
And it seems that also nobody else is using them, plus they support only fragment and vertex shaders.

So either something is wrong with the matdef or your card doesn’t really support that version.

Anyway, JME sets the version in the shader based on the version in that FragmentShader line. How you support multiple versions in JME is to define multiple versions in the matdef.

This is what i do

[...]
Technique {        
        VertexShader GLSL100:   Shader.vert
        FragmentShader GLSL400: Shader.frag
        FragmentShader GLSL150: Shader.frag
        [...]
}
[...]

But in this way, in the shader the version is set to 150.
And the card obviously really support glsl 400, and if i remove the GLSL150 line the fragment run as glsl400 correctly.

I think you need to split out into multiple techniques… as it stands you’ve defined one technique that will handle GLSL150 only.

Ok, sorry but i can’t find any documentation, i have now two techniques but how should i proceed ?
Do i need to call one like “FallbackMode” and switch to it manually if vcard is not compatible with 400 ? Or there is a way to do it automatically?

Poof. Now it’s automatic.

At least according to my understanding. Else, I guess your string is 18 cm long.

I tried
this

MaterialDef Show tangents {
  MaterialParameters {
        Boolean ComputeInFrag
        Boolean ComputeInVert
  }
  Technique {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL150 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
  Technique {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL400 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
}

this

MaterialDef Show tangents {
  MaterialParameters {
        Boolean ComputeInFrag
        Boolean ComputeInVert
  }
  Technique Default {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL150 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
  Technique Default {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL400 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
}

and this

MaterialDef Show tangents {
  MaterialParameters {
        Boolean ComputeInFrag
        Boolean ComputeInVert
  }
  Technique Default {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL150 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
  Technique A {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL150 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
  Technique A {
    VertexShader GLSL100 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL400 : MatDefs/TangentsViewer.glsl
    Defines {         
        COMPUTE_TANGENTS_IN_FRAGMENT: ComputeInFrag
        COMPUTE_TANGENTS_IN_VERTEX: ComputeInVert       
    }
    WorldParameters {
            WorldViewProjectionMatrix
            WorldMatrix
            
       }
  }
}
 m.selectTechnique("A",app.getRenderManager());

None of them works, the first technique is the one that is always used.

My string? What??

The first one is my understanding of how it should work.

It’s a joke about people asking questions about things they haven’t provided… as in “How long is this piece of string I’m holding?” The classic example is when people say they tried something but then don’t actually show what they tried.

Edit: someone more in the know on how the technique selection works may want to comment on whether you need to specify the same version for both .frag and .vert for the right technique to be selected.

Ok sorry, i didn’t feel there was need to post the code.

Tried, for the first technique

    VertexShader GLSL150 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL150 : MatDefs/TangentsViewer.glsl

and for the second technique

    VertexShader GLSL400 : MatDefs/TangentsViewer.glsl
    FragmentShader GLSL400 : MatDefs/TangentsViewer.glsl

same result. :confused:

Then you have reached the extent of my knowledge on the subject. I don’t even know if there are existing examples of this. You will have to appeal to a higher authority, I think. :slight_smile:

Ok, thanks anyway.
For now, since i use a virtual file system below the jme asset manager, i will change the version in the def before loading.
And in the meantime I will pray that a monkey god will cast light on my path.

In a pinch you can check the source code to see what it is doing. I know it is not ideal documentation, but much better than nothing. Also the vast majority of the source is fairly well written and reasonable easy to get a grip with.