[jME3] [Solved] Super confused on passing variables to shader

Hello!



I’ve been chasing my tail for hours, maybe even more than a day at this point, with a passing variables to a custom shader. The weirdness that I can’t explain is that when I hardcode the values that should be passed into the shader, it works as expected. However, when I change it to use variables that should be passed from the main program to the shader, it chokes and gives me the wrong result (usually just maps the entire quad with the 0,0 pixel of the texture). I bet I’m doing something stupid, but I can’t put my finger on where I fouled it up. Also, should the variables that I pass from the program to the shader be uniforms or attributes? I read the documentation on this, from here and other sites, and it still isn’t clear to me. I used uniforms only because it seemed like everything else being passed in was as well :stuck_out_tongue: I get some complaints from the shader when it’s loaded, but I don’t understand if this is just the shader looking for prefixed m_ variables as well as the ones in the shader, because when I add m_ to my variables, it adds ANOTHER m_, so you end up with m_m_variable.



[java]

Mar 3, 2011 9:33:31 AM com.jme3.renderer.lwjgl.LwjglRenderer updateUniformLocation

INFO: Uniform m_Sprite_X is not declared in shader.

Mar 3, 2011 9:33:31 AM com.jme3.renderer.lwjgl.LwjglRenderer updateUniformLocation

INFO: Uniform m_Sprite_Y is not declared in shader.

Mar 3, 2011 9:33:31 AM com.jme3.renderer.lwjgl.LwjglRenderer updateUniformLocation

INFO: Uniform m_FrameDimensions is not declared in shader.

Mar 3, 2011 9:33:31 AM com.jme3.renderer.lwjgl.LwjglRenderer updateUniformLocation

INFO: Uniform m_VertexColor is not declared in shader.

[/java]



I just tried some things with keeping everything a float, read somewhere that integers aren’t generally welcomed by shaders, but still no dice. It just breaks differently. :stuck_out_tongue:



If someone could take a quick look at this to see if there’s any glaring issues, that would be great. All it is, is a modification to the Lighting.j3md and Lighting.vert shader files to allow for only displaying a portion of a texture and to be able to modify this position to allow for animated textures/spriting. My only modifications are to the j3md in adding the variables, a renderstate, and some modification to the main method in the vert.



Thanks!



EDIT: Fixed a typo in part of the shader that was preventing it from working 100%. Using X’s Dimensions to process Y’s size is inaccurate! :stuck_out_tongue:



My test file:



[java]

public class TestSpriteShader extends SimpleApplication {



private static AppSettings settings;



public static void main(String[] args) {

TestSpriteShader app = new TestSpriteShader();

settings = new AppSettings(true);

settings.setFrameRate(150);

settings.setTitle(“Test Sprite Shader”);

app.setSettings(settings);

app.start();

}



@Override

public void simpleInitApp() {

flyCam.setMoveSpeed(30f);



Quad q = new Quad(4, 4);

Geometry g = new Geometry(“Quad”, q);

Material m = new Material(assetManager, “resources/sprite/SpriteLighting.j3md”);

Texture texture = assetManager.loadTexture(“resources/sprite/sprite_dummy.png”);

texture.setMagFilter(MagFilter.Nearest);

texture.setMinFilter(MinFilter.Trilinear);

m.setTexture(“DiffuseMap”, texture);

m.setFloat(“Shininess”, 1000f);

m.setInt(“Sprite_X”, 64);

m.setInt(“Sprite_Y”, 64);

m.setVector2(“FrameDimensions”, new Vector2f(64, 64));

g.setMaterial(m);

g.setQueueBucket(Bucket.Transparent);

rootNode.attachChild(g);



PointLight pl = new PointLight();

pl.setPosition(new Vector3f(1,1,1));

pl.setRadius(30f);

pl.setColor(ColorRGBA.White.clone());

rootNode.addLight(pl);

}

}

[/java]



The SpriteLighting.j3md:



[java]

MaterialDef Phong SpriteLighting {



MaterialParameters {



// Compute vertex lighting in the shader

// For better performance

Boolean VertexLighting



// Use more efficent algorithms to improve performance

Boolean LowQuality



// Improve quality at the cost of performance

Boolean HighQuality



// Output alpha from the diffuse map

Boolean UseAlpha



// Apha threshold for fragment discarding

Float AlphaDiscardThreshold



// Normal map is in BC5/ATI2n/LATC/3Dc compression format

Boolean LATC



// Use the provided ambient, diffuse, and specular colors

Boolean UseMaterialColors



// Activate shading along the tangent, instead of the normal

// Requires tangent data to be available on the model.

Boolean VTangent



// Use minnaert diffuse instead of lambert

Boolean Minnaert



// Use ward specular instead of phong

Boolean WardIso



// Use vertex color as an additional diffuse color.

Boolean UseVertexColor



// Ambient color

Color Ambient



// Diffuse color

Color Diffuse



// Specular color

Color Specular



// Specular power/shininess

Float Shininess



// Diffuse map

Texture2D DiffuseMap



// Normal map

Texture2D NormalMap



// Specular/gloss map

Texture2D SpecularMap



// Parallax/height map

Texture2D ParallaxMap



// Texture that specifies alpha values

Texture2D AlphaMap



// Color ramp, will map diffuse and specular values through it.

Texture2D ColorRamp



// Texture of the glowing parts of the material

Texture2D GlowMap



// The glow color of the object

Color GlowColor



// The X value of the upper left pixel of the DiffuseMap

Int Sprite_X



// The Y value of the upper left pixel of the DiffuseMap

Int Sprite_Y



// The Dimensions of the Sprite’s frame

Vector2 FrameDimensions

}



Technique {



LightMode MultiPass



VertexShader GLSL100: resources/sprite/SpriteLighting.vert

FragmentShader GLSL100: Common/MatDefs/Light/Lighting.frag



WorldParameters {

WorldViewProjectionMatrix

NormalMatrix

WorldViewMatrix

ViewMatrix

}



RenderState {

Blend Alpha

}



Defines {

LATC : LATC

VERTEX_COLOR : UseVertexColor

VERTEX_LIGHTING : VertexLighting

ATTENUATION : Attenuation

MATERIAL_COLORS : UseMaterialColors

V_TANGENT : VTangent

MINNAERT : Minnaert

WARDISO : WardIso

LOW_QUALITY : LowQuality

HQ_ATTENUATION : HighQuality



DIFFUSEMAP : DiffuseMap

NORMALMAP : NormalMap

SPECULARMAP : SpecularMap

PARALLAXMAP : ParallaxMap

ALPHAMAP : AlphaMap

COLORRAMP : ColorRamp

}

}



Technique PreShadow {



VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert

FragmentShader GLSL100 : Common/MatDefs/Shadow/PreShadow.frag



WorldParameters {

WorldViewProjectionMatrix

WorldViewMatrix

}



Defines {

DIFFUSEMAP_ALPHA : DiffuseMap

}



RenderState {

FaceCull Off

DepthTest On

DepthWrite On

PolyOffset 5 0

ColorWrite Off

}



}



Technique PreNormalPass {



VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert

FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag



WorldParameters {

WorldViewProjectionMatrix

WorldViewMatrix

NormalMatrix

}



Defines {

DIFFUSEMAP_ALPHA : DiffuseMap

}



RenderState {



}



}



Technique GBuf {



VertexShader GLSL100: Common/MatDefs/Light/GBuf.vert

FragmentShader GLSL100: Common/MatDefs/Light/GBuf.frag



WorldParameters {

WorldViewProjectionMatrix

WorldMatrix

}



Defines {

VERTEX_COLOR : UseVertexColor

MATERIAL_COLORS : UseMaterialColors

V_TANGENT : VTangent

MINNAERT : Minnaert

WARDISO : WardIso



DIFFUSEMAP : DiffuseMap

NORMALMAP : NormalMap

SPECULARMAP : SpecularMap

PARALLAXMAP : ParallaxMap

}

}



Technique FixedFunc {

LightMode FixedPipeline

}



Technique Glow {



VertexShader GLSL100: Common/MatDefs/Misc/SimpleTextured.vert

FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag



WorldParameters {

WorldViewProjectionMatrix

}



Defines {

HAS_GLOWMAP : GlowMap

HAS_GLOWCOLOR : GlowColor

}

}

}

[/java]



The SpriteLighting.vert:



[java]

#define ATTENUATION

//#define HQ_ATTENUATION



uniform mat4 g_WorldViewProjectionMatrix;

uniform mat4 g_WorldViewMatrix;

uniform mat3 g_NormalMatrix;

uniform mat4 g_ViewMatrix;



uniform vec4 m_Ambient;

uniform vec4 m_Diffuse;

uniform vec4 m_Specular;

uniform float m_Shininess;



uniform vec4 g_LightColor;

uniform vec4 g_LightPosition;

uniform vec4 g_AmbientLightColor;



uniform int Sprite_X;

uniform int Sprite_Y;

uniform vec2 FrameDimensions;



varying vec2 texCoord;



varying vec4 AmbientSum;

varying vec4 DiffuseSum;

varying vec4 SpecularSum;



attribute vec3 inPosition;

attribute vec2 inTexCoord;

attribute vec3 inNormal;



#ifdef HQ_ATTENUATION

varying vec3 lightVec;

#endif



#ifdef VERTEX_COLOR

attribute vec4 inColor;

#endif



#ifndef VERTEX_LIGHTING

attribute vec4 inTangent;



#ifndef NORMALMAP

varying vec3 vNormal;

#endif

varying vec3 vPosition;

varying vec3 vViewDir;

varying vec4 vLightDir;

#endif



// JME3 lights in world space

void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){

float posLight = step(0.5, color.w);

vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);

#ifdef ATTENUATION

float dist = length(tempVec);

lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);

lightDir.xyz = tempVec / vec3(dist);

#ifdef HQ_ATTENUATION

lightVec = tempVec;

#endif

#else

lightDir = vec4(normalize(tempVec), 1.0);

#endif

}



#ifdef VERTEX_LIGHTING

float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){

return max(0.0, dot(norm, lightdir));

}



float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){

#ifndef LOW_QUALITY

vec3 H = (viewdir + lightdir) * vec3(0.5);

return pow(max(dot(H, norm), 0.0), shiny);

#else

return 0.0;

#endif

}



vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){

vec4 lightDir;

lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);



float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);

float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);

//specularFactor *= step(0.01, diffuseFactor);

return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w);

}

#endif



void main(){

vec4 pos = vec4(inPosition, 1.0);

gl_Position = g_WorldViewProjectionMatrix * pos;

// texCoord = inTexCoord;



float uv_XDim = FrameDimensions[0] / 2048.0;

float uv_YDim = FrameDimensions[1] / 2048.0;



float possibleColumns = floor(1.0 / uv_XDim);

float possibleRows = floor(1.0 / uv_YDim);



float currCol = Sprite_X / FrameDimensions[0];

float currRow = Sprite_Y / FrameDimensions[1];



// I don’t think my variables are getting passed in or something.

// However, the 0.03125 would be uv_XDim and uv_YDim

// The 32 is possibleCols and possibleRows

// And the 0 is currCol, 1 is currRow



texCoord = vec2((inTexCoord[0] / possibleColumns)

  • (uv_XDim * currCol),

    (inTexCoord[1] / possibleRows)
  • ((1.0 - uv_YDim) - (uv_YDim * currRow)));



    vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;

    vec3 wvNormal = normalize(g_NormalMatrix * inNormal);

    vec3 viewDir = normalize(-wvPosition);



    //vec4 lightColor = g_LightColor[gl_InstanceID];

    //vec4 lightPos = g_LightPosition[gl_InstanceID];

    //vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));

    //wvLightPos.w = lightPos.w;



    vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));

    wvLightPos.w = g_LightPosition.w;

    vec4 lightColor = g_LightColor;



    #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)

    vec3 wvTangent = normalize(g_NormalMatrix * inTangent.xyz);

    vec3 wvBinormal = cross(wvNormal, wvTangent);



    mat3 tbnMat = mat3(wvTangent, wvBinormal * -inTangent.w,wvNormal);



    vPosition = wvPosition * tbnMat;

    vViewDir = viewDir * tbnMat;

    lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);

    vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;

    #elif !defined(VERTEX_LIGHTING)

    vNormal = wvNormal;



    vPosition = wvPosition;

    vViewDir = viewDir;



    lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);



    #ifdef V_TANGENT

    vNormal = normalize(g_NormalMatrix * inTangent.xyz);

    vNormal = -cross(cross(vLightDir.xyz, vNormal), vNormal);

    #endif

    #endif



    lightColor.w = 1.0;

    #ifdef MATERIAL_COLORS

    AmbientSum = m_Ambient * g_AmbientLightColor;

    DiffuseSum = m_Diffuse * lightColor;

    SpecularSum = m_Specular * lightColor;

    #else

    AmbientSum = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray

    DiffuseSum = lightColor;

    SpecularSum = lightColor;

    #endif



    #ifdef VERTEX_COLOR

    AmbientSum *= inColor;

    DiffuseSum *= inColor;

    #endif



    #ifdef VERTEX_LIGHTING

    vec2 light = computeLighting(wvPosition, wvNormal, viewDir, wvLightPos);



    AmbientSum.a = light.x;

    SpecularSum.a = light.y;

    #endif

    }

    [/java]

Yes you’re right to use uniforms.

Your uniforms MUST have a m_ prefix but only in the shader file



uniform int m_Sprite_X;

uniform int m_Sprite_Y;

uniform vec2 m_FrameDimensions;



the j3md file is fine.

Hello again!



gah! I know it’s always something simple when I spend an enormous amount of time pulling my hair out saying “WTF is this not working?!?!” :stuck_out_tongue: I probably would have never noticed this either, so you probably saved the rest of the hair on my head from fairing the same fate :stuck_out_tongue:



Thanks nehon!

~FlaH

lol :stuck_out_tongue:

Btw maybe i should explain it more clearly in the doc.

Since the m_ change it’s not as obvious as before.

Hello again!



Couldn’t hurt if it wouldn’t take much time to update. I know I was fooled by it. Before this, the older shader code I was running with was also running on an older nightly (by like 2 months) and everything had the m_ in front of it so I’d just assumed that since we dropped the m_'s that they were dropped everywhere.



Cheers!

~FlaH

Hey, cool to see you’re diving into shaders, its friggin easy with jme3, eh? :slight_smile:

hihi,



is there a list of “default” m_XXX uniforms … yesterday I tried to convert a “googled” shader into jme3 … this shader code contains uniforms sample0, sample1 and sample2 (all Texture2D) … I guess these textures are different “scene” layers (I’m a shader newbie g) … but I can’t find a list of "available jme “scene texture defaults”. Please provide a little list in the docu.



regards

Andreas

Hello again!



haha, yeah the jME3 end is easy. It’s all the craziness of GLSL shaders that’s bonkers :smiley: The only thing I think I have a handle on right now is what inTexCoords is doing. I’ll get to the rest as I need to. I’m pretty terrible when it comes to the more mathy parts of 3D manipulation unfortunately. I had so much trouble with Linear Algebra back in college way, way ago. Sorta scary that I may end up battling matrices again :stuck_out_tongue:



I mean wtf, everytime I need a dot product I still have to look it up and go durp durp, ya that’s what I need… :stuck_out_tongue: Ah well…



The thing with shaders that is nice however, is that you can just try, try, and try some more until you get it right. Because odds are, you’ll know right away the first time you look at it whether or not you got it right, close, or completely wrong. :stuck_out_tongue:



~FlaH

ahoehma said:
Please provide a little list in the docu.

A list like this one? :P Its also in your jMP manual.

No not this list …



I mean other uniforms, i.e. these from psspeed’s depthblur filter:



uniform sampler2D m_Texture;

uniform sampler2D m_DepthTexture;



I can’t see no code in the filter where these variables filled?

Thats material parameters, hence the m_ prefix?

I understand that part …

but when/where/who fill these variables with real texures …

the depth blur filter have no “material.setTexture(…)” code …

the documentation could have a “more” conceptual point of view for that (filter/shader-background) …

material.setTexture(“Texture”); ? I think you are brainfarting yourself here :wink:



Edit: well, judging from nehons comment below it was my fart ^^

m_Texture and m_DepthTexture are the rendered scene texture and the depth texture of the scene.

They are populated by the filterPostProcessor and are the only uniforms automatically filled for you.

The m_depthTexture will be filled only if your filter returns true to the isRequireDepthTexture.



But I guess the Filter part would need more explanations and a “creating you own filters” page could help.



Anyway I’m glad that more people are diving into shaders and filters!

Just realized something. Since Lighting.j3md is constantly evolving into a more and more powerful beast, and my sprite shader texcoording code is merely a modification to LIghting.j3md to manipulate the inTexCoord before the rest of the shader gets a hold of it, is there a way that I could just make a shader that feeds into the Lighting.j3md one? Sorta like how Lighting has all of those Techniques in it?



~FlaH

Can i ask a question here about shaders performance?



I noticed that Lighting.j3md uses:

6 different Technique {}

5 different vertex shaders

5 different fragment shaders.



i’m bothered by shader productivity… How much render passes will go for 1 frame? If i have normal, specular, diffuse maps on a material, for instance…



Possibly it would be better to use 1 Technique{}, 1 vertex and 1 fragment shaders for productivity?

mifth said:
i'm bothered by shader productivity... How much render passes will go for 1 frame? If i have normal, specular, diffuse maps on a material, for instance...

One per light (except for ambient light that is rendered with the first "non-ambient" light)
However if you use shadows for example it will be rendered once per light + 1 depth pass rendering casting/receiving shadows objects with the shadow technique (don't remember the exact name).

mifth said:
Possibly it would be better to use 1 Technique{}, 1 vertex and 1 fragment shaders for productivity?

Techniques are not Passes. Technique just specify the shader to use for the current geometry.
The lighting material definition has a lot of techniques because it's a all in one material really.

My question got bumped XD



But it sounds like I could combine my sprite shader and the lighting shader. Just, how would I guarantee my manipulation of the texCoords happens before the lighting shader gets a handle on it? Just pass them through? But wait, wouldn’t I have to pass through all of the Lighting.j3md parameters too… Ugh



~FlaH

If all you are doing is modifying the texture coordinates then it may be better to have your own version of the .vert and keep everything else the same. I’ve done this in a few cases and I usually heavily drop comment blocks around the part I added after copying Lighting.vert… so that I can easily recopy and reupdate when a new Lighting.vert comes out.



Shaders on their own don’t offer much composability, I’m afraid. At least not that I’m aware of.

Ah well. That’s all well and good. I was just hoping to eek a little more flexibility, but I guess I should just be thankful that all I have are two simple copy-pastes and the modification is done :stuck_out_tongue: Only reason I thought of this was because I saw that new alphaDiscardThreshold in the latest Lighting shader and I got to thinking I might have to throw my code into a new file a lot :stuck_out_tongue:



Thanks!

~FlaH