/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// #include \ /////////////////////////////////////////////////////////////////////////////// struct VS_INPUT { float4 posObj: POSITION; float3 normalObj: NORMAL; S3D_BONE_DECL_STD(boneWgh, boneSubscr) float4 diffuse: COLOR0; float2 mainTexCoord: TEXCOORD0; }; struct VS_OUTPUT { float4 posScr: POSITION; float2 mainTexCoord: TEXCOORD0; float4 diffuse: COLOR0; float4 specular: COLOR1; float fogCoord: TEXCOORD2; }; /////////////////////////////////////////////////////////////////////////////// const float4x4 projMat; S3D_MATBONE_DECL_STD(matBone) const float4 mtrlPower; const float4 mtrlEmissive; #ifdef S3D_LIGHT_CNT const s3d_StdProgLight lightArray[S3D_LIGHT_CNT]; const int activeLights; #endif float4 anim; // Animation time between 0 and 1 float4 colorAlpha; // Color and alpha factor float4 param; // x=Particle radius, y=Move-along-normal-factor float4 moveLin; // Linear movement vector float4 moveQuadr; // Quadratic movement vector float4 moveVari; // Variation amount, see below float4 moveJiggle; // Jiggle amount vector, see below. float4 shrink; // x=fadeIn, y=fadeOut, z=flickerAmp, w=flickerVel float4 other; // x=asyncFactor, y=repeat, z=jiggleVel, w=unused /////////////////////////////////////////////////////////////////////////////// // Seed values: float4 seedVariX = float4(8576, 6968, 8285, 1375); float4 seedVariY = float4(9257, 7911, 4491, 4178); float4 seedVariZ = float4(9621, 7416, 9166, 1405); float4 seedJiggleX = float4(9809, 4760, 6104, 3046); float4 seedJiggleY = float4(7590, 5729, 8471, 1556); float4 seedJiggleZ = float4(9904, 0636, 4127, 5254); float4 seedAnim = float4(8891, 1068, 3747, 5529); float4 seedRotU = float4(3147, 0722, 3324, 7158); float4 seedRotV = float4(7020, 4337, 7956, 1530); /////////////////////////////////////////////////////////////////////////////// // Utility functions: float quickSin(float phase) { float rel = frac(phase) - 0.5; float val = - 16 * rel * (0.5 - abs(rel)); return val; } /////////////////////////////////////////////////////////////////////////////// // Vertexshader // Profile: 2x0 VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT output = (VS_OUTPUT)0; float animRandom = dot(input.posObj, seedAnim); float anim = frac(other.x * animRandom + other.y * anim.x); // The movement direction is varied by a pseudo-random value. float3 variRandom; variRandom.x = dot(input.posObj, seedVariX); variRandom.y = dot(input.posObj, seedVariY); variRandom.z = dot(input.posObj, seedVariZ); float3 variUnit = (2 * frac(variRandom) - 1); float3 variDelta = variUnit * moveVari.xyz; // The particles jiggle in direction of a pseudo-random value. float3 jiggleRandom; jiggleRandom.x = dot(input.posObj, seedJiggleX); jiggleRandom.y = dot(input.posObj, seedJiggleY); jiggleRandom.z = dot(input.posObj, seedJiggleZ); float3 jiggleUnit = (2 * frac(jiggleRandom) - 1); float3 jiggleDelta = jiggleUnit * moveJiggle * quickSin(anim * other.z); // Move particle in object coordinates: float3 moveTot = moveLin.xyz; // Move into constant direction moveTot += input.normalObj * param.y; // Move along normal vector moveTot += anim * moveQuadr.xyz; // Move along a quadratic curve moveTot += variDelta; // Move into a random direction float4 posObj = input.posObj; posObj.xyz += anim * moveTot; // Add move posObj.xyz += jiggleDelta; // Jitter // Transformation from object into view coordinates: float4x4 matBoneFinal; S3D_BONE_TRANSF_STD( matBoneFinal, matBone, input.boneWgh, input.boneSubscr); // Transform vectors by matBoneFinal float4 posView = mul(posObj, matBoneFinal); // Calculate effective particle radius. // This includes fading in, fading out and flickering. float fadeIn = anim * shrink.x; float fadeOut = (1 - anim) * shrink.y; float fade = min(1, min(fadeIn, fadeOut)); float flicker = 1 - shrink.z * quickSin(anim * shrink.w); float radius = param.x * flicker * fade; // Until now we only have the particle center. // Now we alculate the corner coordinates. // The particle is rotated by a pseudo-random angle: float2 rotRandom; rotRandom.x = dot(input.posObj, seedRotU); rotRandom.y = dot(input.posObj, seedRotV); float2 rotDir = normalize(frac(rotRandom) - float2(0.5, 0.5)); float2 rotU = radius * 1.4142 * rotDir; float2 rotV = float2(- rotU.y, rotU.x); float2 coord = (input.mainTexCoord.xy - float2(0.5, 0.5)); posView.xy += rotU * coord.x + rotV * coord.y; // Projection: output.posScr = mul(posView, projMat); output.mainTexCoord = input.mainTexCoord; output.fogCoord = posView.z / posView.w; // Calculate vertex color: #ifdef S3D_LIGHT_CNT float4 colDiffuse = mtrlEmissive; float4 colSpecular = 0; for(int i = 0; i < activeLights; i++) { s3d_ColPair lightCol = s3d_calcPointLightTerm( posView.xyz, 0, mtrlPower.w, lightArray[i]); colDiffuse.rgb += lightCol.diffuse.rgb; colSpecular.rgb += lightCol.specular.rgb; } output.diffuse = colDiffuse * colorAlpha * input.diffuse; output.specular = colSpecular; #else output.diffuse = colorAlpha * input.diffuse; output.specular = 0; #endif return output; } ///////////////////////////////////////////////////////////////////////////////