vs.1.1 dcl_position v0 dcl_normal v3 // c0 = (0,0.5,1.0,2.0) (aka NumericConsts) // c1 = frequencies // c2 = phases // c3 = amplitudes // c4 = PiConsts = (1/(2PI), PI/2, PI, 2*PI) // NOTE THIS IS DIFFERENT // because we don't need oonsqpi here but do want 1/2Pi. // c5 = cosConsts = (1.0f, -1.0f/2.0f, 1.0f/ 24.0f, -1.0f/ 720.0f); // c6 = ((cMax - cMin), cMin, 2ndLayerVOffset, 2ndLayerScale); // c7 = overall color, including current opacity. Will // probably only use the opacity, which we could stuff into // the free slot of c6, but we're a wuss. // First, "move" the position to oPos mov r0, v0; //mov r0.y, -r0.yyyy; mov r0.w, c0.zzzz; mov oPos, r0; // Now the tricky part. // The base layer defines the shape of the incoming wave // The next layer has bubbles (noise) and moves in when the // wave is moving in, moves out when wave is moving out. // So calculate uvw for first layer, second uvw shares u val // and v val is const // The .x component of the normal // tells us how much to shift this vert based on the // cumulative cosine wave. // Figure c = Sigma((cosine(v0.x * freq + phase) + 1) * amp); // Note that range c must be [0..1] // Also, c(-1) must equal c(1) so it will wrap. // That implies freq = k * 2 * PI, where k is an integer. // To keep c >= 0, we can add 1 to each term in the sigma BEFORE // modulating by the amplitude. // That puts our range at [0..2*sigma(amp)], so as long as // sigma(amp) <= 0.5, we're fine. // Get our input to cosine value (v0.x * freq + phase). add r0, v0.xxxx, c0.zzzz; mul r0, r0, c1; add r0, r0, c2; // Get it into range [-Pi..Pi] // First divide out the 2PI // add r0, r0, c4.zzzz; HACKOUT mul r0, r0, c4.xxxx; // Do an integer mod expp r1.y, r0.xxxx mov r1.x, r1.yyyy expp r1.y, r0.zzzz mov r1.z, r1.yyyy expp r1.y, r0.wwww mov r1.w, r1.yyyy expp r1.y, r0.yyyy //mov oD1, r1; // HACKTEST //mov oD1.w, c0.zzzz; // HACKTEST // Move back into PI space, w/ *= 2P, -= PI mul r0, r1, c4.wwww; sub r0, r0, c4.zzzz; // Okay, compute cosine here. // cos = 1 + r0^2 * kCos.y + r0^4 * kCos.Z + r0^6 * kCos.w // Note: could pare off an instr by putting 1/kCos.w in kCos.x, // then doing a mad to get r3=(1/kCos.w + r0^6), then mad that // into the accum by kCos.w to get (1 + r0^6*kCos.x). But who cares. mul r1, r0, r0; // r0^2 mul r2, r1, r1; // r0^4 mul r3, r1, r2; // r0^6 mov r4, c5.xxxx; // r4 = 1 mad r4, r1, c5.yyyy, r4; // r4 += r0^2 * kCos.y mad r4, r2, c5.zzzz, r4; // r4 += r0^4 * kCos.z mad r4, r3, c5.wwww, r4; // r4 += r0^6 * kCos.w add r4, r4, c0.zzzz; // shift from [-1..1] to [0..2] //mov r4, c0.xxxx; // HACKLAST mul r4, r4, c3; // times amplitude dp4 r5.y, r4, c0.zzzz; // r5.x = sigma((cos() + 1) * amp); // V calculation, goes something like: // For layers 0 and 2: // V = { 1 + c6.z <= r5.y = 0 } * norm.x // norm.x == v3.x // { 1 + 0 <= r5.y = 1 } // For layer 1: // V = (norm.x + c6.z) * c6.w // Scaled like U // // Another way to formulate that is // baseV = cMin + sinAge * (cMax-cMin) where // cMin = 2 // cMax = 1 // sinAge = color.a = c7.w // delV = sigma(cos) = r5.y // Then // V0 = V2 = (baseV + delV) * v3.x // V1 = (norm.x + baseV + delV) * c6.w // // If we're sure we want cMin = 2 and cMax = 1, then it simplifies to: // baseV = 2 - sinAge = c0.w - c7.w // delV = r5.y // (baseV + delV) = c0.w - c7.w + r5.y // // If we want to stay general, then // baseV = c6.x * c7.w + c6.y // delV = -r5.y // (baseV + delV) = constant + r5.y // // make r5.y = (baseV + delV) add r5.y, c6.xxxx, r5.yyyy; //mov oD1, r5.yyyy; // HACKLAST //mov oD1.w, c0.zzzz; // HACKLAST // U is input U (or v0.x * 0.5f + 0.5f) mul r5.x, v0.x, c0.y; add r5.x, r5.x, c0.y; // Fill out wq. mov r5.zw, c0.xz; mul oT0, r5, v3.wxww; // mov oD1, r5.yyyw; // HACKTEST mul oT2, r5, v3.wxww; // Second uv shares u, but v is norm.x + c6.x; // Then we scale it. // If we want the bubble texture to move with the // wave front, we want the second UV calc (RESCALE1). // But it looks better to have the bubbles moving // slightly faster than the wave front. RESCALE0 // happens to do that, because we're scaling the // texture by a factor of 2, but we should probably // supply an independent scale of the motion vs. the // scale of the texture. // Let's move c6 to r6 for ease of use. mov r6, c6; // add r5.x, r5.x, c6.y; // add r5.y, c6.xxxx, v3.xxxx; // RESCALE0 // mul r5.xy, r5, c6.wwww; // RESCALE0 add r5.x, r5.x, r6.y; // RESCALE1 // offset U mov r5.y, v3.xx; // RESCALE1 // Init V to value stashed in normal.x mul r5.xy, r5, r6.wwww; // RESCALE1 // scale them by single scale value mad r5.y, r6.xx, r6.zz, r5.yy; // RESCALE1 // add in our scaled V offset (sinage * vScale) mov oT1, r5; //mov oT0, v7; // HACKTEST //mov oT1, v7; // HACKTEST //mov oT2, v7; // HACKTEST // Just slam in the constant color (includes our current opacity). mov oD0, c7; //mov oD0, c0.zzzz; // HACKTEST