#define TEXTURE_SIZE 256 float4 scurve(float4 v) { return v * v * (3 - 2 * v); } float noise4(in float4 vec, uniform samplerRECT p, uniform samplerRECT g) { float4 b0, b1, r0, r1; float4 u, v, u0, v0, u1, v1; r0 = modf(vec, b0); b1 = b0 + 1; r1 = r0 - 1; //b0 = fmod(b0, (TEXTURE_SIZE).xxxx); // we could avoid these //b1 = fmod(b1, (TEXTURE_SIZE).xxxx); // if rectangular textures could use GL_REPEAT mode // our textures are actually 1d so we don't care about the second coordinate /* half i0 = h1texRECT(p, b0.xx); half i1 = h1texRECT(p, b1.xx); half i00 = h1texRECT(p, i0.xx + b0.yy); half i10 = h1texRECT(p, i1.xx + b0.yy); half i01 = h1texRECT(p, i0.xx + b1.yy); half i11 = h1texRECT(p, i1.xx + b1.yy); half i000 = h1texRECT(p, i00.xx + b0.zz); half i100 = h1texRECT(p, i10.xx + b0.zz); half i010 = h1texRECT(p, i01.xx + b0.zz); half i110 = h1texRECT(p, i11.xx + b0.zz); half i001 = h1texRECT(p, i00.xx + b1.zz); half i101 = h1texRECT(p, i10.xx + b1.zz); half i011 = h1texRECT(p, i01.xx + b1.zz); half i111 = h1texRECT(p, i11.xx + b1.zz); */ float i0 = texRECT(p, b0.xx); float i1 = texRECT(p, b1.xx); float i00 = texRECT(p, i0.xx + b0.yy); float i10 = texRECT(p, i1.xx + b0.yy); float i01 = texRECT(p, i0.xx + b1.yy); float i11 = texRECT(p, i1.xx + b1.yy); float i000 = texRECT(p, i00.xx + b0.zz); float i100 = texRECT(p, i10.xx + b0.zz); float i010 = texRECT(p, i01.xx + b0.zz); float i110 = texRECT(p, i11.xx + b0.zz); float i001 = texRECT(p, i00.xx + b1.zz); float i101 = texRECT(p, i10.xx + b1.zz); float i011 = texRECT(p, i01.xx + b1.zz); float i111 = texRECT(p, i11.xx + b1.zz); // sample 16 neighbors and calculate 16 dot-products // sample at x = 0 /* u0.x = dot(f4texRECT(g, i000.xx + b0.ww), r0); u0.y = dot(f4texRECT(g, i010.xx + b0.ww), fixed4(0, 1, 0, 0) > 0 ? r1 : r0); u0.z = dot(f4texRECT(g, i000.xx + b1.ww), fixed4(0, 0, 0, 1) > 0 ? r1 : r0); u0.w = dot(f4texRECT(g, i010.xx + b1.ww), fixed4(0, 1, 0, 1) > 0 ? r1 : r0); v0.x = dot(f4texRECT(g, i001.xx + b0.ww), fixed4(0, 0, 1, 0) > 0 ? r1 : r0); v0.y = dot(f4texRECT(g, i011.xx + b0.ww), fixed4(0, 1, 1, 0) > 0 ? r1 : r0); v0.z = dot(f4texRECT(g, i001.xx + b1.ww), fixed4(0, 0, 1, 1) > 0 ? r1 : r0); v0.w = dot(f4texRECT(g, i011.xx + b1.ww), fixed4(0, 1, 1, 1) > 0 ? r1 : r0); // sample at x = 1 u1.x = dot(f4texRECT(g, i100.xx + b0.ww), fixed4(1, 0, 0, 0) > 0 ? r1 : r0); u1.y = dot(f4texRECT(g, i110.xx + b0.ww), fixed4(1, 1, 0, 0) > 0 ? r1 : r0); u1.z = dot(f4texRECT(g, i100.xx + b1.ww), fixed4(1, 0, 0, 1) > 0 ? r1 : r0); u1.w = dot(f4texRECT(g, i110.xx + b1.ww), fixed4(1, 1, 0, 1) > 0 ? r1 : r0); v1.x = dot(f4texRECT(g, i101.xx + b0.ww), fixed4(1, 0, 1, 0) > 0 ? r1 : r0); v1.y = dot(f4texRECT(g, i111.xx + b0.ww), fixed4(1, 1, 1, 0) > 0 ? r1 : r0); v1.z = dot(f4texRECT(g, i101.xx + b1.ww), fixed4(1, 0, 1, 1) > 0 ? r1 : r0); v1.w = dot(f4texRECT(g, i111.xx + b1.ww), r1); */ u0.x = dot(texRECT(g, i000.xx + b0.ww), r0); u0.y = dot(texRECT(g, i010.xx + b0.ww), float4(0, 1, 0, 0) > 0 ? r1 : r0); u0.z = dot(texRECT(g, i000.xx + b1.ww), float4(0, 0, 0, 1) > 0 ? r1 : r0); u0.w = dot(texRECT(g, i010.xx + b1.ww), float4(0, 1, 0, 1) > 0 ? r1 : r0); v0.x = dot(texRECT(g, i001.xx + b0.ww), float4(0, 0, 1, 0) > 0 ? r1 : r0); v0.y = dot(texRECT(g, i011.xx + b0.ww), float4(0, 1, 1, 0) > 0 ? r1 : r0); v0.z = dot(texRECT(g, i001.xx + b1.ww), float4(0, 0, 1, 1) > 0 ? r1 : r0); v0.w = dot(texRECT(g, i011.xx + b1.ww), float4(0, 1, 1, 1) > 0 ? r1 : r0); // sample at x = 1 u1.x = dot(texRECT(g, i100.xx + b0.ww), float4(1, 0, 0, 0) > 0 ? r1 : r0); u1.y = dot(texRECT(g, i110.xx + b0.ww), float4(1, 1, 0, 0) > 0 ? r1 : r0); u1.z = dot(texRECT(g, i100.xx + b1.ww), float4(1, 0, 0, 1) > 0 ? r1 : r0); u1.w = dot(texRECT(g, i110.xx + b1.ww), float4(1, 1, 0, 1) > 0 ? r1 : r0); v1.x = dot(texRECT(g, i101.xx + b0.ww), float4(1, 0, 1, 0) > 0 ? r1 : r0); v1.y = dot(texRECT(g, i111.xx + b0.ww), float4(1, 1, 1, 0) > 0 ? r1 : r0); v1.z = dot(texRECT(g, i101.xx + b1.ww), float4(1, 0, 1, 1) > 0 ? r1 : r0); v1.w = dot(texRECT(g, i111.xx + b1.ww), r1); // now, perform quadro-cubic interpolation between these 16 noise samples float4 s = scurve(r0); // interpolation in 4d-space requires 15 1d interpolations, // but thanks to parallel nature of lerp instruction and some swizzling // we can do the same with only 5 lerp instructions // lerp between two pairs of 8 values along x axis u = lerp(u0, u1, s.x); v = lerp(v0, v1, s.x); // lerp between two pairs of 4 values (resulted from the previous lerp) along z axis u = lerp(u, v, s.z); // now, lerp between two pairs of 2 values along y axis float2 a = lerp(u.xz, u.yw, s.y); // finally, lerp along w axis return abs(lerp(a.x, a.y, s.w)); } float turbulence4(in float4 vec, uniform samplerRECT perm, uniform samplerRECT grad) { float n; n = noise4(vec, perm, grad); // + 0.5x * noise4(vec * 2.0h, p, g) + 0.25x * noise4(vec * 4.0h, p, g) + 0.125x * noise4(vec * 8.0h, p, g) + 0.0625x * noise4(vec * 16.0h, p, g); //n = 0.0f; return n; } fragout main( in float4 pos : POSITION, in float3 col : COLOR0, in float4 u : TEXCOORD0, in float ypos : TEXCOORD1, //in float clip0 : CLP0, //in float clip1 : CLP1, //in float clip2 : CLP2, //in float clip3 : CLP3, //in float clip4 : CLP4, //in float clip5 : CLP5, // uniform samplerRECT perm, // permutations texture uniform samplerRECT perm: TEXUNIT0, // uniform samplerRECT grad, // random gradient 4d vectors texture uniform samplerRECT grad: TEXUNIT2, // uniform sampler2D firetex, // color texture uniform sampler2D firetex : TEXUNIT4, // turbulance scale uniform float turb_scale //out fragout outval ) { fragout outval; float2 uv = u.xz - 0.5x; uv += uv; uv *= uv; float4 v = u; v.y += ypos; uv.x = sqrt(uv.x + uv.y); // radial mapping //new code //float tur_res = turbulence4(v * 1.5x,permutation,gradient); //tur_res = tur_res.x + 0.5x*turbulence4(v * 3.0x,permutation,gradient); //tur_res = tur_res.x + 0.25x*turbulence4(v * 6.0x,permutation,gradient); //tur_res = tur_res.x + 0.125x*turbulence4(v * 12.0x,permutation,gradient); //tur_res = tur_res.x + 0.0625x*turbulence4(v * 24.0x,permutation,gradient); //tur_res = turb_scale.x * tur_res.x; //uv.y = u.y + sqrt(u.y) * tur_res.x; //turbulence4(v * 1.5x, perm, grad); uv.y = u.y + sqrt(u.y) * turb_scale * turbulence4(v, perm, grad); //perturb texture coordinates with turbulence() function //uv.y = u.y; outval.col.rgb = x3tex2D(firetex, uv); return outval; }