rendermonkey and "converting to world space"

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
thespecial1
Posts: 135
Joined: Thu Oct 30, 2008 11:56 am
Location: UK
Contact:

rendermonkey and "converting to world space"

Post by thespecial1 »

hyy guys
Mel wrote:Second. Irrlicht seems to work in "world space" not in "Object space", which means that all translations, rotations, and scalations are made in world space, and thus, that vertex shader would place your object in the middle of the screen, and wouldn't move from there. That is something common to all rendermonkey shaders. You have to use the worldViewProjection matrix instead to place vertices correctly.
as a GLSL beginner could someone explain how to convert a rendermonkey from object to world space, take the GL fire inferno example which should look like this

Image
but instead it is outputting
Image
is this because of object space being used (or something else)

inferno.vert

Code: Select all

varying vec2 vTexCoord;

void main(void) {
	gl_Position = ftransform();
	vTexCoord = vec2(sign(gl_Vertex));
}
inferno.frag

Code: Select all

uniform float time;
uniform float sideFade;
uniform float sideFadeSharpness;
uniform float wobbleScale;
uniform float burnSpeed;
uniform float randomnessRate;
uniform float yFade;
uniform float xScale;
uniform float yScale;

uniform sampler3D Noise;
uniform sampler2D Flame;

varying vec2 vTexCoord;
float saturate(float inValue)
{
   return clamp(inValue, 0.0, 1.0);
}

void main(void)
{   
   // Wobble for the noise to get a more realistic appearance
   float wobbX = 2.0 * cos(6.0 * vTexCoord.x + time);
   float wobbY = 7.0 * (1.0 - vTexCoord.y) * (1.0 - vTexCoord.y);
   float wobble = sin(time + wobbX + wobbY);
 
   vec3 coord;
 
   // Wobble more in the flames than at the base
   coord.x = xScale * vTexCoord.x + wobbleScale * (vTexCoord.y + 1.0) * wobble;
 
   // Create an upwards movement
   coord.y = yScale * vTexCoord.y - burnSpeed * time;
 
   // Move in Z to get some randomness
   coord.z = randomnessRate * time;
   float noisy = texture3D(Noise, coord).x;

   // Define the shape of the fire
   float t = sideFadeSharpness * (1.0 - sideFade * vTexCoord.x * vTexCoord.x);

   // Get the color out of it all
   float heat = saturate(t + noisy - yFade * vTexCoord.y);
   vec4 flame = texture2D(Flame, vec2(heat,0.0));
   
   gl_FragColor = flame;
   
}
the parameters are straight from rendermonkey defaults,
float time = _TIME_;
float sideFade = 18;
float sideFadeSharpness = 0.05;
float wobbleScale = 0.03;
float burnSpeed = 0.57;
float randomnessRate = 0.24;
float yFade = 0.6;
float xScale = 1.5;
float yScale = 0.6;
float Noise = 1;
float Flame = 0;

the 3d noise texture is loaded correctly, just weird output, thoughts anyone?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

To me it looks more like it's not alpha blended, but rendered solid.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

ftransform() takes care of the world, view and projection transformations for you, so you don't have to worry about that. The likely cause for the difference is probably something closer to what hybrid mentioned. Remember to set the correct base material for the shader if you want transparency.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
thespecial1
Posts: 135
Joined: Thu Oct 30, 2008 11:56 am
Location: UK
Contact:

Post by thespecial1 »

BlindSide wrote:ftransform() takes care of the world, view and projection transformations for you, so you don't have to worry about that. The likely cause for the difference is probably something closer to what hybrid mentioned. Remember to set the correct base material for the shader if you want transparency.
sweet thanks for confirming how to handle world space, took fttransform from comparision with the shaders in spintz
hybrid wrote:To me it looks more like it's not alpha blended, but rendered solid.
i was hoping you were right but as you can see below transparency makes it go pink bizzare huh (have tried every mode this morning)
Image
i get a similar effect from the other rendermonkey fireshaders, weird gray background like something needs swapping, think i am going to comment the whole shader and bring it back in line by line to find the problem..

thanks
Rob
PS this shader will also cause an access violation in smgr->endScene on my laptop (ATI HD3000)

PPS the callback is below

Code: Select all

class materialCallback : public IShaderConstantSetCallBack { 
private:
public: 
	IrrlichtDevice *device;
	virtual void OnSetConstants(IMaterialRendererServices *services, s32 userData) {                 
		f32 time =  device->getTimer()->getTime()/200.0;
		f32 sideFade = 18;
		f32 sideFadeSharpness = 0.05;
		f32 wobbleScale = 0.03;
		f32 burnSpeed = 0.57;
		f32 randomnessRate = 0.24;
		f32 yFade = 0.6;		
		f32 xScale = 1.5;
		f32 yScale = 0.6;
		f32 Noise = 1;
		f32 Flame = 0;
		services->setPixelShaderConstant("time", reinterpret_cast<f32*>(&time), 1); 
		services->setPixelShaderConstant("sideFade", reinterpret_cast<f32*>(&sideFade), 1); 
		services->setPixelShaderConstant("sideFadeSharpness", reinterpret_cast<f32*>(&sideFadeSharpness), 1); 
		services->setPixelShaderConstant("wobbleScale",reinterpret_cast<f32*>(&wobbleScale),1);
		services->setPixelShaderConstant("burnSpeed", reinterpret_cast<f32*>(&burnSpeed), 1); 
		services->setPixelShaderConstant("randomnessRate", reinterpret_cast<f32*>(&randomnessRate), 1); 
		services->setPixelShaderConstant("yFade", reinterpret_cast<f32*>(&yFade), 1); 
		services->setPixelShaderConstant("xScale",reinterpret_cast<f32*>(&xScale),1);
		services->setPixelShaderConstant("yScale",reinterpret_cast<f32*>(&yScale),1);
		services->setPixelShaderConstant("Noise",reinterpret_cast<f32*>(&Noise),1);
		services->setPixelShaderConstant("Flame",reinterpret_cast<f32*>(&Flame),1);
	} 
};
one other thing, i have never seen anyone else have a pointer to IrrlichtDevice inside their callback, is this a good idea or should i start using globals (i have avoided this so far)
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

To be perfectly honest, I don't see anything wrong with the Irrlicht image in regards to the shader code you posted, all it really does is take that textured mesh and make it wobble.

Oh wait, Irrlicht doesn't support 3D textures I'm fairly sure. :P Theres your problem.

Try the GLSL noise function from here instead:

http://www.gamedev.net/community/forums ... _id=502913

Not only that but in the GLSL callback I find that you have to cast an int rather than float for the texture variables, otherwise your second texture won't show up:

Code: Select all

int Flame = 0;
int Noise = 1;
(Still cast it to f32* anyway)
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
thespecial1
Posts: 135
Joined: Thu Oct 30, 2008 11:56 am
Location: UK
Contact:

Post by thespecial1 »

hyy blindSide thanx for getting back
BlindSide wrote:To be perfectly honest, I don't see anything wrong with the Irrlicht image in regards to the shader code you posted, all it really does is take that textured mesh and make it wobble.
Oh wait, Irrlicht doesn't support 3D textures I'm fairly sure. :P Theres your problem.
previously i would have agreed with you except that i have got this glitter shader
Image
and this woodrings shader
Image
working and both are using the same rendermonkey texture NoiseVolume.dds as the all of the fire examples, i used egrath's dds loader http://irrlicht.sourceforge.net/phpBB2/ ... hlight=dds
the key difference is that the fire uses two textures rather than one
BlindSide wrote: Try the GLSL noise function from here instead:
http://www.gamedev.net/community/forums ... _id=502913
i will investigate that one, will be useful generally, as i have the noise loaded it is annoying me that i have got some of the simpler rendermonkey examples working but not the fire (which i actually need badly as have a hell ish project that needs to burn hence my obsession with this particular shader) even though is using the same noise, booo
BlindSide wrote: Not only that but in the GLSL callback I find that you have to cast an int rather than float for the texture variables, otherwise your second texture won't show up:

Code: Select all

int Flame = 0;
int Noise = 1;
(Still cast it to f32* anyway)
thanks for that one, definatly true, with those set as ints i get this which does match colour wise to the wanted output but is completly static, i get the same output whether the noise texture is the first texture or not
Image
which looks rather noiseless to me (and the same as HLSL), more booo, not sure why the noise doesnt work except on examples where the noise is the only texture loaded, have tried all of the material types, the one pictured is using "trans_add", i think it should be oneTextureBlend but that renders a black texture ;0)
thespecial1
Posts: 135
Joined: Thu Oct 30, 2008 11:56 am
Location: UK
Contact:

Post by thespecial1 »

also i did look into 3dnoise functions as suggested, i found this one which gens 3d noise from a 2d source quite cool some of the effects you can get out of the shader thou not really looking like fire, this one moves at high speed, a fire pinapple me thinks
Image

the modified shader is below, i found a DDS plugin for photoshop and saved it as a 2d tga for the permTexture, u can get some crazy effects depending upon what noise pic u feed it

Code: Select all

uniform float time;
uniform float sideFade;
uniform float sideFadeSharpness;
uniform float wobbleScale;
uniform float burnSpeed;
uniform float randomnessRate;
uniform float yFade;
uniform float xScale;
uniform float yScale;

uniform sampler2D Flame;

varying vec2 vTexCoord;
float saturate(float inValue)
{
   return clamp(inValue, 0.0, 1.0);
}

uniform sampler2D permTexture; 
#define ONE 0.00390625
#define ONEHALF 0.001953125
float fade(float t) {
  return t*t*t*(t*(t*6.0-15.0)+10.0); // Improved fade, yields C2-continuous noise
}
float genNoise3D(vec3 P)
{
  vec3 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled so +1 moves one texel
                                  // and offset 1/2 texel to sample texel centers
  vec3 Pf = fract(P);     // Fractional part for interpolation

  // Noise contributions from (x=0, y=0), z=0 and z=1
  float perm00 = texture2D(permTexture, Pi.xy).a ;
  vec3  grad000 = texture2D(permTexture, vec2(perm00, Pi.z)).rgb * 4.0 - 1.0;
  float n000 = dot(grad000, Pf);
  vec3  grad001 = texture2D(permTexture, vec2(perm00, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n001 = dot(grad001, Pf - vec3(0.0, 0.0, 1.0));

  // Noise contributions from (x=0, y=1), z=0 and z=1
  float perm01 = texture2D(permTexture, Pi.xy + vec2(0.0, ONE)).a ;
  vec3  grad010 = texture2D(permTexture, vec2(perm01, Pi.z)).rgb * 4.0 - 1.0;
  float n010 = dot(grad010, Pf - vec3(0.0, 1.0, 0.0));
  vec3  grad011 = texture2D(permTexture, vec2(perm01, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n011 = dot(grad011, Pf - vec3(0.0, 1.0, 1.0));

  // Noise contributions from (x=1, y=0), z=0 and z=1
  float perm10 = texture2D(permTexture, Pi.xy + vec2(ONE, 0.0)).a ;
  vec3  grad100 = texture2D(permTexture, vec2(perm10, Pi.z)).rgb * 4.0 - 1.0;
  float n100 = dot(grad100, Pf - vec3(1.0, 0.0, 0.0));
  vec3  grad101 = texture2D(permTexture, vec2(perm10, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n101 = dot(grad101, Pf - vec3(1.0, 0.0, 1.0));

  // Noise contributions from (x=1, y=1), z=0 and z=1
  float perm11 = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a ;
  vec3  grad110 = texture2D(permTexture, vec2(perm11, Pi.z)).rgb * 4.0 - 1.0;
  float n110 = dot(grad110, Pf - vec3(1.0, 1.0, 0.0));
  vec3  grad111 = texture2D(permTexture, vec2(perm11, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n111 = dot(grad111, Pf - vec3(1.0, 1.0, 1.0));

  // Blend contributions along x
  vec4 n_x = mix(vec4(n000, n001, n010, n011),
                 vec4(n100, n101, n110, n111), fade(Pf.x));

  // Blend contributions along y
  vec2 n_xy = mix(n_x.xy, n_x.zw, fade(Pf.y));

  // Blend contributions along z
  float n_xyz = mix(n_xy.x, n_xy.y, fade(Pf.z));

  // We're done, return the final noise value.
  return n_xyz;
}


void main(void)
{   
   // Wobble for the noise to get a more realistic appearance
   float wobbX = 2.0 * cos(6.0 * vTexCoord.x + time);
   float wobbY = 7.0 * (1.0 - vTexCoord.y) * (1.0 - vTexCoord.y);
   float wobble = sin(time + wobbX + wobbY);
 
   vec3 coord;
 
   // Wobble more in the flames than at the base
   coord.x = xScale * vTexCoord.x + wobbleScale * (vTexCoord.y + 1.0) * wobble;
 
   // Create an upwards movement
   coord.y = yScale * vTexCoord.y - burnSpeed * time;
 
   // Move in Z to get some randomness
   coord.z = randomnessRate * time;
   //float noisy = texture3D(Noise, coord).x;
   float noisy = genNoise3D(coord);

   // Define the shape of the fire
   float t = sideFadeSharpness * (1.0 - sideFade * vTexCoord.x * vTexCoord.x);

   // Get the color out of it all
   float heat = saturate(t + noisy - yFade * vTexCoord.y);
   vec4 flame = texture2D(Flame, vec2(heat,0.0));
   
   gl_FragColor = flame;
   
}
still only good for a mess around thou, the thing am not sure if i got right is the noise function seems to sombine xyz and return just a float rather than a vec3, the noisy variable was only interested in x

still would like 3dnoise in a texture to work though really as i really want the inferno to be perfect, also must be less bloated code, must be faster aswell as the noise is already generated and loaded in memory.

;0) the whole GLSL library with funx for six kinds of noise is listed below

Code: Select all

/*
 * 2D, 3D and 4D Perlin noise, classic and simplex, in a GLSL fragment shader.
 *
 * Classic noise is implemented by the functions:
 * float noise(vec2 P)
 * float noise(vec3 P)
 * float noise(vec4 P)
 *
 * Simplex noise is implemented by the functions:
 * float snoise(vec2 P)
 * float snoise(vec3 P)
 * float snoise(vec4 P)
 *
 * Author: Stefan Gustavson ITN-LiTH (stegu@itn.liu.se) 2004-12-05
 * You may use, modify and redistribute this code free of charge,
 * provided that my name and this notice appears intact.
 */

/*
 * NOTE: there is a formal problem with the dependent texture lookups.
 * A texture coordinate of exactly 1.0 will wrap to 0.0, so strictly speaking,
 * an error occurs every 256 units of the texture domain, and the same gradient
 * is used for two adjacent noise cells. One solution is to set the texture
 * wrap mode to "CLAMP" and do the wrapping explicitly in GLSL with the "mod"
 * operator. This could also give you noise with repetition intervals other
 * than 256 without any extra cost.
 * This error is not even noticeable to the eye even if you isolate the exact
 * position in the domain where it occurs and know exactly what to look for.
 * The noise pattern is still visually correct, so I left the bug in there.
 * 
 * The value of classic 4D noise goes above 1.0 and below -1.0 at some
 * points. Not much and only very sparsely, but it happens.
 */


/*
 * "permTexture" is a 256x256 texture that is used for both the permutations
 * and the 2D and 3D gradient lookup. For details, see the main C program.
 * "simplexTexture" is a small look-up table to determine a simplex traversal
 * order for 3D and 4D simplex noise. Details are in the C program.
 * "gradTexture" is a 256x256 texture with 4D gradients, similar to
 * "permTexture" but with the permutation index in the alpha component
 * replaced by the w component of the 4D gradient.
 * 2D classic noise uses only permTexture.
 * 2D simplex noise uses permTexture and simplexTexture.
 * 3D classic noise uses only permTexture.
 * 3D simplex noise uses permTexture and simplexTexture.
 * 4D classic noise uses permTexture and gradTexture.
 * 4D simplex noise uses all three textures.
 */
uniform sampler2D permTexture;
uniform sampler1D simplexTexture;
uniform sampler2D gradTexture;

/*
 * To create offsets of one texel and one half texel in the
 * texture lookup, we need to know the texture image size.
 */
#define ONE 0.00390625
#define ONEHALF 0.001953125
// The numbers above are 1/256 and 0.5/256, change accordingly
// if you change the code to use another texture size.


/*
 * The interpolation function. This could be a 1D texture lookup
 * to get some more speed, but it's not the main part of the algorithm.
 */
float fade(float t) {
  // return t*t*(3.0-2.0*t); // Old fade, yields discontinuous second derivative
  return t*t*t*(t*(t*6.0-15.0)+10.0); // Improved fade, yields C2-continuous noise
}


/*
 * 2D classic Perlin noise. Fast, but less useful than 3D noise.
 */
float noise(vec2 P)
{
  vec2 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled and offset for texture lookup
  vec2 Pf = fract(P);             // Fractional part for interpolation

  // Noise contribution from lower left corner
  vec2 grad00 = texture2D(permTexture, Pi).rg * 4.0 - 1.0;
  float n00 = dot(grad00, Pf);

  // Noise contribution from lower right corner
  vec2 grad10 = texture2D(permTexture, Pi + vec2(ONE, 0.0)).rg * 4.0 - 1.0;
  float n10 = dot(grad10, Pf - vec2(1.0, 0.0));

  // Noise contribution from upper left corner
  vec2 grad01 = texture2D(permTexture, Pi + vec2(0.0, ONE)).rg * 4.0 - 1.0;
  float n01 = dot(grad01, Pf - vec2(0.0, 1.0));

  // Noise contribution from upper right corner
  vec2 grad11 = texture2D(permTexture, Pi + vec2(ONE, ONE)).rg * 4.0 - 1.0;
  float n11 = dot(grad11, Pf - vec2(1.0, 1.0));

  // Blend contributions along x
  vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade(Pf.x));

  // Blend contributions along y
  float n_xy = mix(n_x.x, n_x.y, fade(Pf.y));

  // We're done, return the final noise value.
  return n_xy;
}


/*
 * 3D classic noise. Slower, but a lot more useful than 2D noise.
 */
float noise(vec3 P)
{
  vec3 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled so +1 moves one texel
                                  // and offset 1/2 texel to sample texel centers
  vec3 Pf = fract(P);     // Fractional part for interpolation

  // Noise contributions from (x=0, y=0), z=0 and z=1
  float perm00 = texture2D(permTexture, Pi.xy).a ;
  vec3  grad000 = texture2D(permTexture, vec2(perm00, Pi.z)).rgb * 4.0 - 1.0;
  float n000 = dot(grad000, Pf);
  vec3  grad001 = texture2D(permTexture, vec2(perm00, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n001 = dot(grad001, Pf - vec3(0.0, 0.0, 1.0));

  // Noise contributions from (x=0, y=1), z=0 and z=1
  float perm01 = texture2D(permTexture, Pi.xy + vec2(0.0, ONE)).a ;
  vec3  grad010 = texture2D(permTexture, vec2(perm01, Pi.z)).rgb * 4.0 - 1.0;
  float n010 = dot(grad010, Pf - vec3(0.0, 1.0, 0.0));
  vec3  grad011 = texture2D(permTexture, vec2(perm01, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n011 = dot(grad011, Pf - vec3(0.0, 1.0, 1.0));

  // Noise contributions from (x=1, y=0), z=0 and z=1
  float perm10 = texture2D(permTexture, Pi.xy + vec2(ONE, 0.0)).a ;
  vec3  grad100 = texture2D(permTexture, vec2(perm10, Pi.z)).rgb * 4.0 - 1.0;
  float n100 = dot(grad100, Pf - vec3(1.0, 0.0, 0.0));
  vec3  grad101 = texture2D(permTexture, vec2(perm10, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n101 = dot(grad101, Pf - vec3(1.0, 0.0, 1.0));

  // Noise contributions from (x=1, y=1), z=0 and z=1
  float perm11 = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a ;
  vec3  grad110 = texture2D(permTexture, vec2(perm11, Pi.z)).rgb * 4.0 - 1.0;
  float n110 = dot(grad110, Pf - vec3(1.0, 1.0, 0.0));
  vec3  grad111 = texture2D(permTexture, vec2(perm11, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float n111 = dot(grad111, Pf - vec3(1.0, 1.0, 1.0));

  // Blend contributions along x
  vec4 n_x = mix(vec4(n000, n001, n010, n011),
                 vec4(n100, n101, n110, n111), fade(Pf.x));

  // Blend contributions along y
  vec2 n_xy = mix(n_x.xy, n_x.zw, fade(Pf.y));

  // Blend contributions along z
  float n_xyz = mix(n_xy.x, n_xy.y, fade(Pf.z));

  // We're done, return the final noise value.
  return n_xyz;
}


/*
 * 4D classic noise. Slow, but very useful. 4D simplex noise is a lot faster.
 *
 * This function performs 8 texture lookups and 16 dependent texture lookups,
 * 16 dot products, 4 mix operations and a lot of additions and multiplications.
 * Needless to say, it's not super fast. But it's not dead slow either.
 */
float noise(vec4 P)
{
  vec4 Pi = ONE*floor(P)+ONEHALF; // Integer part, scaled so +1 moves one texel
                                  // and offset 1/2 texel to sample texel centers
  vec4 Pf = fract(P);      // Fractional part for interpolation

  // "n0000" is the noise contribution from (x=0, y=0, z=0, w=0), and so on
  float perm00xy = texture2D(permTexture, Pi.xy).a ;
  float perm00zw = texture2D(permTexture, Pi.zw).a ;
  vec4 grad0000 = texture2D(gradTexture, vec2(perm00xy, perm00zw)).rgba * 4.0 -1.0;
  float n0000 = dot(grad0000, Pf);

  float perm01zw = texture2D(permTexture, Pi.zw  + vec2(0.0, ONE)).a ;
  vec4  grad0001 = texture2D(gradTexture, vec2(perm00xy, perm01zw)).rgba * 4.0 - 1.0;
  float n0001 = dot(grad0001, Pf - vec4(0.0, 0.0, 0.0, 1.0));

  float perm10zw = texture2D(permTexture, Pi.zw  + vec2(ONE, 0.0)).a ;
  vec4  grad0010 = texture2D(gradTexture, vec2(perm00xy, perm10zw)).rgba * 4.0 - 1.0;
  float n0010 = dot(grad0010, Pf - vec4(0.0, 0.0, 1.0, 0.0));

  float perm11zw = texture2D(permTexture, Pi.zw  + vec2(ONE, ONE)).a ;
  vec4  grad0011 = texture2D(gradTexture, vec2(perm00xy, perm11zw)).rgba * 4.0 - 1.0;
  float n0011 = dot(grad0011, Pf - vec4(0.0, 0.0, 1.0, 1.0));

  float perm01xy = texture2D(permTexture, Pi.xy + vec2(0.0, ONE)).a ;
  vec4  grad0100 = texture2D(gradTexture, vec2(perm01xy, perm00zw)).rgba * 4.0 - 1.0;
  float n0100 = dot(grad0100, Pf - vec4(0.0, 1.0, 0.0, 0.0));

  vec4  grad0101 = texture2D(gradTexture, vec2(perm01xy, perm01zw)).rgba * 4.0 - 1.0;
  float n0101 = dot(grad0101, Pf - vec4(0.0, 1.0, 0.0, 1.0));

  vec4  grad0110 = texture2D(gradTexture, vec2(perm01xy, perm10zw)).rgba * 4.0 - 1.0;
  float n0110 = dot(grad0110, Pf - vec4(0.0, 1.0, 1.0, 0.0));

  vec4  grad0111 = texture2D(gradTexture, vec2(perm01xy, perm11zw)).rgba * 4.0 - 1.0;
  float n0111 = dot(grad0111, Pf - vec4(0.0, 1.0, 1.0, 1.0));

  float perm10xy = texture2D(permTexture, Pi.xy + vec2(ONE, 0.0)).a ;
  vec4  grad1000 = texture2D(gradTexture, vec2(perm10xy, perm00zw)).rgba * 4.0 - 1.0;
  float n1000 = dot(grad1000, Pf - vec4(1.0, 0.0, 0.0, 0.0));

  vec4  grad1001 = texture2D(gradTexture, vec2(perm10xy, perm01zw)).rgba * 4.0 - 1.0;
  float n1001 = dot(grad1001, Pf - vec4(1.0, 0.0, 0.0, 1.0));

  vec4  grad1010 = texture2D(gradTexture, vec2(perm10xy, perm10zw)).rgba * 4.0 - 1.0;
  float n1010 = dot(grad1010, Pf - vec4(1.0, 0.0, 1.0, 0.0));

  vec4  grad1011 = texture2D(gradTexture, vec2(perm10xy, perm11zw)).rgba * 4.0 - 1.0;
  float n1011 = dot(grad1011, Pf - vec4(1.0, 0.0, 1.0, 1.0));

  float perm11xy = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a ;
  vec4  grad1100 = texture2D(gradTexture, vec2(perm11xy, perm00zw)).rgba * 4.0 - 1.0;
  float n1100 = dot(grad1100, Pf - vec4(1.0, 1.0, 0.0, 0.0));

  vec4  grad1101 = texture2D(gradTexture, vec2(perm11xy, perm01zw)).rgba * 4.0 - 1.0;
  float n1101 = dot(grad1101, Pf - vec4(1.0, 1.0, 0.0, 1.0));

  vec4  grad1110 = texture2D(gradTexture, vec2(perm11xy, perm10zw)).rgba * 4.0 - 1.0;
  float n1110 = dot(grad1110, Pf - vec4(1.0, 1.0, 1.0, 0.0));

  vec4  grad1111 = texture2D(gradTexture, vec2(perm11xy, perm11zw)).rgba * 4.0 - 1.0;
  float n1111 = dot(grad1111, Pf - vec4(1.0, 1.0, 1.0, 1.0));

  // Blend contributions along x
  float fadex = fade(Pf.x);
  vec4 n_x0 = mix(vec4(n0000, n0001, n0010, n0011),
                  vec4(n1000, n1001, n1010, n1011), fadex);
  vec4 n_x1 = mix(vec4(n0100, n0101, n0110, n0111),
                  vec4(n1100, n1101, n1110, n1111), fadex);

  // Blend contributions along y
  vec4 n_xy = mix(n_x0, n_x1, fade(Pf.y));

  // Blend contributions along z
  vec2 n_xyz = mix(n_xy.xy, n_xy.zw, fade(Pf.z));

  // Blend contributions along w
  float n_xyzw = mix(n_xyz.x, n_xyz.y, fade(Pf.w));

  // We're done, return the final noise value.
  return n_xyzw;
}


/*
 * 2D simplex noise. Somewhat slower but much better looking than classic noise.
 */
float snoise(vec2 P) {

// Skew and unskew factors are a bit hairy for 2D, so define them as constants
// This is (sqrt(3.0)-1.0)/2.0
#define F2 0.366025403784
// This is (3.0-sqrt(3.0))/6.0
#define G2 0.211324865405

  // Skew the (x,y) space to determine which cell of 2 simplices we're in
 	float s = (P.x + P.y) * F2;   // Hairy factor for 2D skewing
  vec2 Pi = floor(P + s);
  float t = (Pi.x + Pi.y) * G2; // Hairy factor for unskewing
  vec2 P0 = Pi - t; // Unskew the cell origin back to (x,y) space
  Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup

  vec2 Pf0 = P - P0;  // The x,y distances from the cell origin

  // For the 2D case, the simplex shape is an equilateral triangle.
  // Find out whether we are above or below the x=y diagonal to
  // determine which of the two triangles we're in.
  vec2 o1;
  if(Pf0.x > Pf0.y) o1 = vec2(1.0, 0.0);  // +x, +y traversal order
  else o1 = vec2(0.0, 1.0);               // +y, +x traversal order

  // Noise contribution from simplex origin
  vec2 grad0 = texture2D(permTexture, Pi).rg * 4.0 - 1.0;
  float t0 = 0.5 - dot(Pf0, Pf0);
  float n0;
  if (t0 < 0.0) n0 = 0.0;
  else {
    t0 *= t0;
    n0 = t0 * t0 * dot(grad0, Pf0);
  }

  // Noise contribution from middle corner
  vec2 Pf1 = Pf0 - o1 + G2;
  vec2 grad1 = texture2D(permTexture, Pi + o1*ONE).rg * 4.0 - 1.0;
  float t1 = 0.5 - dot(Pf1, Pf1);
  float n1;
  if (t1 < 0.0) n1 = 0.0;
  else {
    t1 *= t1;
    n1 = t1 * t1 * dot(grad1, Pf1);
  }
  
  // Noise contribution from last corner
  vec2 Pf2 = Pf0 - vec2(1.0-2.0*G2);
  vec2 grad2 = texture2D(permTexture, Pi + vec2(ONE, ONE)).rg * 4.0 - 1.0;
  float t2 = 0.5 - dot(Pf2, Pf2);
  float n2;
  if(t2 < 0.0) n2 = 0.0;
  else {
    t2 *= t2;
    n2 = t2 * t2 * dot(grad2, Pf2);
  }

  // Sum up and scale the result to cover the range [-1,1]
  return 70.0 * (n0 + n1 + n2);
}


/*
 * 3D simplex noise. Comparable in speed to classic noise, better looking.
 */
float snoise(vec3 P) {

// The skewing and unskewing factors are much simpler for the 3D case
#define F3 0.333333333333
#define G3 0.166666666667

  // Skew the (x,y,z) space to determine which cell of 6 simplices we're in
 	float s = (P.x + P.y + P.z) * F3; // Factor for 3D skewing
  vec3 Pi = floor(P + s);
  float t = (Pi.x + Pi.y + Pi.z) * G3;
  vec3 P0 = Pi - t; // Unskew the cell origin back to (x,y,z) space
  Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup

  vec3 Pf0 = P - P0;  // The x,y distances from the cell origin

  // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
  // To find out which of the six possible tetrahedra we're in, we need to
  // determine the magnitude ordering of x, y and z components of Pf0.
  // The method below is explained briefly in the C code. It uses a small
  // 1D texture as a lookup table. The table is designed to work for both
  // 3D and 4D noise, so only 8 (only 6, actually) of the 64 indices are
  // used here.
  float c1 = (Pf0.x > Pf0.y) ? 0.5078125 : 0.0078125; // 1/2 + 1/128
  float c2 = (Pf0.x > Pf0.z) ? 0.25 : 0.0;
  float c3 = (Pf0.y > Pf0.z) ? 0.125 : 0.0;
  float sindex = c1 + c2 + c3;
  vec3 offsets = texture1D(simplexTexture, sindex).rgb;
  vec3 o1 = step(0.375, offsets);
  vec3 o2 = step(0.125, offsets);

  // Noise contribution from simplex origin
  float perm0 = texture2D(permTexture, Pi.xy).a;
  vec3  grad0 = texture2D(permTexture, vec2(perm0, Pi.z)).rgb * 4.0 - 1.0;
  float t0 = 0.6 - dot(Pf0, Pf0);
  float n0;
  if (t0 < 0.0) n0 = 0.0;
  else {
    t0 *= t0;
    n0 = t0 * t0 * dot(grad0, Pf0);
  }

  // Noise contribution from second corner
  vec3 Pf1 = Pf0 - o1 + G3;
  float perm1 = texture2D(permTexture, Pi.xy + o1.xy*ONE).a;
  vec3  grad1 = texture2D(permTexture, vec2(perm1, Pi.z + o1.z*ONE)).rgb * 4.0 - 1.0;
  float t1 = 0.6 - dot(Pf1, Pf1);
  float n1;
  if (t1 < 0.0) n1 = 0.0;
  else {
    t1 *= t1;
    n1 = t1 * t1 * dot(grad1, Pf1);
  }
  
  // Noise contribution from third corner
  vec3 Pf2 = Pf0 - o2 + 2.0 * G3;
  float perm2 = texture2D(permTexture, Pi.xy + o2.xy*ONE).a;
  vec3  grad2 = texture2D(permTexture, vec2(perm2, Pi.z + o2.z*ONE)).rgb * 4.0 - 1.0;
  float t2 = 0.6 - dot(Pf2, Pf2);
  float n2;
  if (t2 < 0.0) n2 = 0.0;
  else {
    t2 *= t2;
    n2 = t2 * t2 * dot(grad2, Pf2);
  }
  
  // Noise contribution from last corner
  vec3 Pf3 = Pf0 - vec3(1.0-3.0*G3);
  float perm3 = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a;
  vec3  grad3 = texture2D(permTexture, vec2(perm3, Pi.z + ONE)).rgb * 4.0 - 1.0;
  float t3 = 0.6 - dot(Pf3, Pf3);
  float n3;
  if(t3 < 0.0) n3 = 0.0;
  else {
    t3 *= t3;
    n3 = t3 * t3 * dot(grad3, Pf3);
  }

  // Sum up and scale the result to cover the range [-1,1]
  return 32.0 * (n0 + n1 + n2 + n3);
}


/*
 * 4D simplex noise. A lot faster than classic 4D noise, and better looking.
 */

float snoise(vec4 P) {

// The skewing and unskewing factors are hairy again for the 4D case
// This is (sqrt(5.0)-1.0)/4.0
#define F4 0.309016994375
// This is (5.0-sqrt(5.0))/20.0
#define G4 0.138196601125

  // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
 	float s = (P.x + P.y + P.z + P.w) * F4; // Factor for 4D skewing
  vec4 Pi = floor(P + s);
  float t = (Pi.x + Pi.y + Pi.z + Pi.w) * G4;
  vec4 P0 = Pi - t; // Unskew the cell origin back to (x,y,z,w) space
  Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup

  vec4 Pf0 = P - P0;  // The x,y distances from the cell origin

  // For the 4D case, the simplex is a 4D shape I won't even try to describe.
  // To find out which of the 24 possible simplices we're in, we need to
  // determine the magnitude ordering of x, y, z and w components of Pf0.
  // The method below is presented without explanation. It uses a small 1D
  // texture as a lookup table. The table is designed to work for both
  // 3D and 4D noise and contains 64 indices, of which only 24 are actually
  // used. An extension to 5D would require a larger texture here.
  float c1 = (Pf0.x > Pf0.y) ? 0.5078125 : 0.0078125; // 1/2 + 1/128
  float c2 = (Pf0.x > Pf0.z) ? 0.25 : 0.0;
  float c3 = (Pf0.y > Pf0.z) ? 0.125 : 0.0;
  float c4 = (Pf0.x > Pf0.w) ? 0.0625 : 0.0;
  float c5 = (Pf0.y > Pf0.w) ? 0.03125 : 0.0;
  float c6 = (Pf0.z > Pf0.w) ? 0.015625 : 0.0;
  float sindex = c1 + c2 + c3 + c4 + c5 + c6;
  vec4 offsets = texture1D(simplexTexture, sindex).rgba;
  vec4 o1 = step(0.625, offsets);
  vec4 o2 = step(0.375, offsets);
  vec4 o3 = step(0.125, offsets);

  // Noise contribution from simplex origin
  float perm0xy = texture2D(permTexture, Pi.xy).a;
  float perm0zw = texture2D(permTexture, Pi.zw).a;
  vec4  grad0 = texture2D(gradTexture, vec2(perm0xy, perm0zw)).rgba * 4.0 - 1.0;
  float t0 = 0.6 - dot(Pf0, Pf0);
  float n0;
  if (t0 < 0.0) n0 = 0.0;
  else {
    t0 *= t0;
    n0 = t0 * t0 * dot(grad0, Pf0);
  }

  // Noise contribution from second corner
  vec4 Pf1 = Pf0 - o1 + G4;
  o1 = o1 * ONE;
  float perm1xy = texture2D(permTexture, Pi.xy + o1.xy).a;
  float perm1zw = texture2D(permTexture, Pi.zw + o1.zw).a;
  vec4  grad1 = texture2D(gradTexture, vec2(perm1xy, perm1zw)).rgba * 4.0 - 1.0;
  float t1 = 0.6 - dot(Pf1, Pf1);
  float n1;
  if (t1 < 0.0) n1 = 0.0;
  else {
    t1 *= t1;
    n1 = t1 * t1 * dot(grad1, Pf1);
  }
  
  // Noise contribution from third corner
  vec4 Pf2 = Pf0 - o2 + 2.0 * G4;
  o2 = o2 * ONE;
  float perm2xy = texture2D(permTexture, Pi.xy + o2.xy).a;
  float perm2zw = texture2D(permTexture, Pi.zw + o2.zw).a;
  vec4  grad2 = texture2D(gradTexture, vec2(perm2xy, perm2zw)).rgba * 4.0 - 1.0;
  float t2 = 0.6 - dot(Pf2, Pf2);
  float n2;
  if (t2 < 0.0) n2 = 0.0;
  else {
    t2 *= t2;
    n2 = t2 * t2 * dot(grad2, Pf2);
  }
  
  // Noise contribution from fourth corner
  vec4 Pf3 = Pf0 - o3 + 3.0 * G4;
  o3 = o3 * ONE;
  float perm3xy = texture2D(permTexture, Pi.xy + o3.xy).a;
  float perm3zw = texture2D(permTexture, Pi.zw + o3.zw).a;
  vec4  grad3 = texture2D(gradTexture, vec2(perm3xy, perm3zw)).rgba * 4.0 - 1.0;
  float t3 = 0.6 - dot(Pf3, Pf3);
  float n3;
  if (t3 < 0.0) n3 = 0.0;
  else {
    t3 *= t3;
    n3 = t3 * t3 * dot(grad3, Pf3);
  }
  
  // Noise contribution from last corner
  vec4 Pf4 = Pf0 - vec4(1.0-4.0*G4);
  float perm4xy = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a;
  float perm4zw = texture2D(permTexture, Pi.zw + vec2(ONE, ONE)).a;
  vec4  grad4 = texture2D(gradTexture, vec2(perm4xy, perm4zw)).rgba * 4.0 - 1.0;
  float t4 = 0.6 - dot(Pf4, Pf4);
  float n4;
  if(t4 < 0.0) n4 = 0.0;
  else {
    t4 *= t4;
    n4 = t4 * t4 * dot(grad4, Pf4);
  }

  // Sum up and scale the result to cover the range [-1,1]
  return 27.0 * (n0 + n1 + n2 + n3 + n4);
}
is abit of a beast ;0)
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

one other thing, i have never seen anyone else have a pointer to IrrlichtDevice inside their callback, is this a good idea or should i start using globals (i have avoided this so far)
You could create a callback class that used as a construction parameter the irrlicht engine, or anything you needed inside the callback. You only have to inherit the IShaderConstantsCallback interface, and implement the onSetConstants(services,int) method. The rest, is up to you.

Check this: The code is not very accurate, but explains the idea.

Code: Select all

class MyCallback : public video::IShaderConstantSetCallBack
{
	IrrlichtDevice* dev;
public:
	MyCallback::MyCallback(IrrlichtDevice* pDev){dev=pDev;}
	virtual void MyCallback::OnSetConstants(video::IMaterialRendererServices* services, s32 userData){...}
};
And create it like this:

Code: Select all

IrrlichtDevice* dev=createIrrlichtDevice(...);
MyCallback* MyCB = new MyCallback(dev);
This way, you have access to the whole engine inside the constants Callback, and you don't need global variables :).

That fire example looks like the noise function is too big, i.e, it changes very little from a point to another close to it. Perhaps if the scale was smaller, the fire effect would be more noticeable.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
thespecial1
Posts: 135
Joined: Thu Oct 30, 2008 11:56 am
Location: UK
Contact:

Post by thespecial1 »

hyy mel................................................
Mel wrote:This way, you have access to the whole engine inside the constants Callback, and you don't need global variables :).
thats what i thought too, had done it in the suggested fashion, needed device to calc ambient and view position..i have zero globals..
Mel wrote:That fire example looks like the noise function is too big, i.e, it changes very little from a point to another close to it. Perhaps if the scale was smaller, the fire effect would be more noticeable.
agreed, i only posted that out of interest, large functions all of them, quite clever though,

to be honest, i am still hoping to get the 3d noise texture working properly, this has been done before 3demon spintz so i will continue, am trying to use their code but not compiled properly as yet, egrath's loader worked for glitter which is why i was hoping something needed altering in the shader to make it work..
Post Reply