Sprites

@tralala , :

1 THANKS A LOT FOR FIXING THE ATI BUG!!!

2 @pspeed can you share with your rope vertex shader to align a plane to camera? For the good man @tralala.

@mifth said:
@tralala , :
1 THANKS A LOT FOR FIXING THE ATI BUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 @pspeed can you share with your rope vertex shader to align a plane to camera? For the good man @tralala.


My rope shader keeps it pointed at the camera along the vector of the rope. Just getting something to always point to and align with the screen is way easier.

And that's what point sprites do unless you want the sprites to be locked in some axis.

@tralala , with all latest fixes i had crash on my Nvidia. Trying to fix it again:

http://code.google.com/p/jme-glsl-shaders/source/browse/assets/Shaders/SimpleSprite/SimpleSprite.vert



Will this shader will work on your card?

wow seems glsl is not portable.



SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

com.jme3.renderer.RendererException: compile error in:ShaderSource[name=Shaders/SimpleSprite/SimpleSprite.vert, defines, type=Vertex] error:Vertex shader failed to compile with the following errors:

ERROR: 0:29: error(#160) Cannot convert from ‘highp float’ to ‘highp int’

ERROR: 0:30: error(#160) Cannot convert from ‘highp float’ to ‘highp int’

ERROR: 0:33: error(#160) Cannot convert from ‘const float’ to ‘highp int’

ERROR: 0:36: error(#160) Cannot convert from ‘float’ to ‘highp int’

ERROR: error(#273) 4 compilation errors. No code generated

Correct GLSL is portable. Some cards let you get away with stuff that isn’t supposed to be allowed.



Like:

float f = 1;



That’s a bug.

GLSL is portable but some platforms will let you run wrong code. You never can assign an int to a float or vice versa per the GLSL specs.

For example, these lines are buggy:

[java]

texCoordAni.x = -(1 - ((texCoordAni.x + mod(selectedTile , iNumTilesU) ) / iNumTilesU)); ///selectedTile;

texCoordAni.y = ((-texCoordAni.y - int(selectedTile / iNumTilesU)) / iNumTilesV); ///selectedTile;

[/java]



They both do implicit conversions from int to float. The more obvious one is the 1 instead of 1.0.

Actually I don’t think it’s true:

http://www.opengl.org/wiki/GLSL_Types#Implicit_conversion

You can believe that page or you can run on a Mac. On a mac, float f = 1; will fail. Trust me. :slight_smile:

yeah, on my pc box too. but i assume its the glsl implementation that is failing, not the code.

I was reffering to normen’s “as per GLSL spec”

Also, it might be different in a declaration or an expression

Implicit conversion was added with GLSL 1.2 (OpenGL 2.1), so its not a feature of OpenGL 2.0 which is the baseline compatibility of jME3. And as paul said, it doesn’t work on macs at all as not all cards support it properly (even if they supposedly support GLSL 1.2+).

@cghislai said:
Also, it might be different in a declaration or an expression


No, it will fail with either. If you use 0 and 1 as floats in an expression or in a declaration initialization then it will fail on some programs.

If I had a dollar for every time I fixed a shader bug by finding the decimal I forgot to add then I would be a rich man, for sure.

Moreoever, the earlier code converts floats specifically to int but then does not convert them back to float before adding/subtracing them from other floats. It pays to be rigidly typed. It's like the most OCD coding there is.

I also always make that mistake, but i thought it was due to bad implementation.

But at least now I have the correct spec file to look into !

i tried to make the billboard however it doesn’t work, it’s position and rotation is totally chaotic.



I implemented gl.glRotate exactly as stated on : http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml and yet it doesn’t work? why ?



if anyone knows about shader please help.



sprite.j3md

[java]

MaterialDef Sprite

{

MaterialParameters

{

Vector4 Color

Texture2D Texture

}

Technique

{

VertexShader GLSL100: 3d/shaders/sprite.vert

FragmentShader GLSL100: 3d/shaders/sprite.frag

WorldParameters

{

WorldViewProjectionMatrix

CameraPosition

}

}

Technique FixedFunc

{

}

}

[/java]



sprite.vert

[java]

uniform mat4 g_WorldViewProjectionMatrix;

uniform vec3 g_CameraPosition;



attribute vec3 inPosition;

const float PI = 3.14159265358979323846264;



void main()

{

vec4 pos = vec4(inPosition, 1.0);



vec3 lookAt = vec3(0, 0, 1);

vec3 objToCamProj = vec3( g_CameraPosition.x - inPosition.x, 0, g_CameraPosition.z - inPosition.z);

objToCamProj = normalize( objToCamProj );



vec3 upAux = cross( lookAt, objToCamProj );

upAux = normalize( upAux );

float angleCosine = dot(lookAt, objToCamProj);



float angle = acos(angleCosine) * 180 / PI;

float x = upAux.z;

float y = upAux.y;

float z = upAux.z;

float c = cos(angle);

float s = sin(angle);



mat4 rotationMatrix = mat4( xx(1-c)+c , yx(1-c)+zs, xz*(1-c)-ys, 0,

x
y*(1-c)-zs, yy*(1-c)+c , yz(1-c)+xs, 0,

x
z*(1-c)+ys, yz*(1-c)-xs, zz*(1-c)+c , 0,

0 , 0 , 0 , 1);



gl_Position = g_WorldViewProjectionMatrix * pos * rotationMatrix;

}

[/java]



sprite.java

[java]

uniform vec4 m_Color;



void main()

{

gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);

}

[/java]

This can’t work that way. To implement a sprite in shader you need to know the position around which it will rotate and then somehow translate the corners of the quad out to where the should be facing the screen. (And I will repeat, if you aren’t rotating it around a specific axis then this will be expensively doing exactly the same work as a point sprite.)



One approach is to use the same position for all four vertexes and then use some other vertex attribute (texture coordinate or something) to know which corner that vertex is to use for moving it. To emulate point sprite behavior this is pretty straight forward.



To rotate about a specific axis then you have to do some more complicated math to figure out the “sprite space” vectors and project out the corners based on their texture coordinates or whatever.



Also, just in general math… you never need to acos() just to then get the cos. Also, it looks like you convert the angle from radians to degrees and then pass that directly to cos() and sin(). Which is odd.

ok because it is so complicated i tried a simpler example :

just a simple rotation on X axis. it doesn’t work. Is there a bug with jme ? why the rotation matrix multiplication doesn’t work, i followed the opengl implementation, it should work.



[java]

uniform mat4 g_WorldViewProjectionMatrix;

uniform float g_Time ;



attribute vec3 inPosition;

const float PI = 3.14159265358979323846264;



void main()

{

vec4 pos = vec4(inPosition, 1.0);



float angle = g_Time0.1;

float x = 1; //x-axis

float y = 0;

float z = 0;

float c = cos(angle);

float s = sin(angle);



mat4 rotationMatrix = mat4( x
x*(1-c)+c , yx(1-c)+zs, xz*(1-c)-ys, 0,

x
y*(1-c)-zs, yy*(1-c)+c , yz(1-c)+xs, 0,

x
z*(1-c)+ys, yz*(1-c)-xs, zz*(1-c)+c , 0,

0 , 0 , 0 , 1);



gl_Position = g_WorldViewProjectionMatrix * pos * rotationMatrix;

}

[/java]

@tralala , please, try this one:

http://code.google.com/p/jme-glsl-shaders/source/browse/assets/Shaders/SimpleSprite/SimpleSprite.vert?spec=svne1d4afe2b7c2143ce6fbb4383ac25d193cb0606d&r=e1d4afe2b7c2143ce6fbb4383ac25d193cb0606d

One of the bugs i found is that the order of multiplication matters. in bold are the changes.

Now it rotates correctly, but the billboard changes size :

0 : full size

PI/2:0 size

PI : full size



why is that ?



[java]

uniform mat4 g_WorldViewProjectionMatrix;

uniform float g_Time ;



attribute vec3 inPosition;

const float PI = 3.14159265358979323846264;



void main()

{

vec4 pos = vec4(inPosition, 1.0);



float angle = g_Time0.1;

float x = 1;

float y = 0;

float z = 0;

float c = cos(angle);

float s = sin(angle);



mat4 rotationMatrix = mat4( x
x*(1-c)+c , yx(1-c)+zs, xz*(1-c)-ys, 0,

x
y*(1-c)-zs, yy*(1-c)+c , yz(1-c)+xs, 0,

x
z*(1-c)+ys, yz*(1-c)-xs, zz*(1-c)+c , 0,

0 , 0 , 0 , 1);



<strong>pos = pos * rotationMatrix;</strong>



<strong>gl_Position = g_WorldViewProjectionMatrix * pos;</strong>

}

[/java]

i tried it :

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

com.jme3.renderer.RendererException: compile error in:ShaderSource[name=Shaders/SimpleSprite/SimpleSprite.vert, defines, type=Vertex] error:Vertex shader failed to compile with the following errors:

ERROR: 0:33: error(#160) Cannot convert from ‘const float’ to ‘highp int’

ERROR: 0:36: error(#160) Cannot convert from ‘float’ to ‘highp int’

ERROR: error(#273) 2 compilation errors. No code generated





maybe you should break the big formula into many small variables with 1 action its time.