!!ARBvp1.0 # Vertex Program for lit, skinned avatars # Parameters PARAM gMat[45] = { program.env[0..44] }; PARAM gEmbossScale = program.env[63]; PARAM gWindDir = program.env[60]; # wind direction with strength stored in w PARAM gSinWaveParams = program.env[61]; # frequency, frequency2, frequency, phase PARAM gGravity = program.env[62]; PARAM gMinMaxConstants = {1.0, 0.166666, 0.0083143, .00018542}; #minimax-generated coefficients PARAM gPiConstants = {0.159154943, 6.28318530, 3.141592653, 1.5707963}; # {1/2PI, 2PI, PI, PI/2} PARAM gProj[4] = { state.matrix.projection }; PARAM gModelAmbient = state.lightmodel.ambient; PARAM gMaterialDiffuse = state.material.diffuse; PARAM gLightDir0 = state.light[0].position; PARAM gDiffuseCol0 = state.light[0].diffuse; PARAM gLightDir1 = state.light[1].position; PARAM gDiffuseCol1 = state.light[1].diffuse; PARAM gLightPos2 = state.light[2].position; PARAM gDiffuseCol2 = state.light[2].diffuse; PARAM gLightPos3 = state.light[3].position; PARAM gDiffuseCol3 = state.light[3].diffuse; # Per vertex inputs ATTRIB iPos = vertex.position; ATTRIB iNormal = vertex.normal; ATTRIB iTex0 = vertex.texcoord[0]; ATTRIB iTex1 = vertex.texcoord[1]; ATTRIB iWeight = vertex.attrib[1]; ATTRIB iClothing = vertex.attrib[4]; ATTRIB iBinormal = vertex.attrib[6]; # Temporaries TEMP blendMatX; TEMP blendMatY; TEMP blendMatZ; TEMP blendPos; # weighted sum of tpos0 and tpos1 TEMP blendNorm; # weighted sum of eyeNormal0 and eyeNormal1 TEMP blendBinorm; # result of skinned binormal TEMP temp0; TEMP temp1; # another general purpose temp TEMP temp2; ALIAS blendTangent = temp2; # result of skinned tangent ALIAS colorAcc = temp0; ALIAS offsetPos = temp1; ALIAS dots = temp1; # dot product for lighting calculations ALIAS scaledWeight = temp0; # vertex weight as decoded from input weight ALIAS divisor = temp2; ALIAS sinWave = temp0; ALIAS windEffect = temp2; ALIAS lightDir = blendMatX; ADDRESS address; # Outputs OUTPUT oPos = result.position; # position OUTPUT oCol0 = result.color; # primary color OUTPUT oTex0 = result.texcoord[0]; # texture coordinate set 0 OUTPUT oTex1 = result.texcoord[1]; # texture coordinate set 1 OUTPUT oFog = result.fogcoord; # output fog coordinates #fix input blending weight ARL address.x, iWeight.x; FRC scaledWeight.x, iWeight; # Blend joint matrices MUL blendMatX, gMat[address.x + 1], {1,1,1,1}; SUB blendMatX, blendMatX, gMat[address.x + 0]; MAD blendMatX, scaledWeight.x, blendMatX, gMat[address.x + 0]; DP3 blendNorm.x, blendMatX, iNormal; DP3 blendBinorm.x, blendMatX, iBinormal; MUL blendMatY, gMat[address.x + 16], {1,1,1,1}; SUB blendMatY, blendMatY, gMat[address.x + 15]; MAD blendMatY, scaledWeight.x, blendMatY, gMat[address.x + 15]; DP3 blendNorm.y, blendMatY, iNormal; DP3 blendBinorm.y, blendMatY, iBinormal; MUL blendMatZ, gMat[address.x + 31], {1,1,1,1}; SUB blendMatZ, blendMatZ, gMat[address.x + 30]; MAD blendMatZ, scaledWeight.x, blendMatZ, gMat[address.x + 30]; DP3 blendNorm.z, blendMatZ, iNormal; DP3 blendBinorm.z, blendMatZ, iBinormal; #wind DP3 windEffect, blendNorm, gWindDir; DP3 blendPos.x, blendMatZ, iPos; MAD windEffect.xyz, blendPos.x, {0.015, 0.015, 0.015, 0}, windEffect; MAD windEffect.w, windEffect, {0, 0, 0, 2}, {0, 0, 0, 1}; # move wind offset value to [-1, 3] MUL windEffect.w, windEffect, gWindDir; # modulate wind strength MAD windEffect.xyz, windEffect, gSinWaveParams, gSinWaveParams.w; # use sin wave params to scale and offset input #reduce to period of 2 PI MUL temp1.xyz, windEffect, gPiConstants.x; # change input as multiple of [0-2PI] to [0-1] EXP temp0, temp1.x; # find mod(x, 1) MUL windEffect.x, temp0.y, gPiConstants.y; # scale from [0,1] to [0, 2PI] ADD temp1.z, temp1.z, -gPiConstants.w; # shift normal oscillation by PI/2 EXP temp0, temp1.z; # find mod(x, 1) MUL windEffect.z, temp0.y, gPiConstants.y; # scale from [0,1] to [0, 2PI] # offset to [-PI, PI] ADD windEffect.xyz, windEffect, {-3.141592, -3.141592, -3.141592, -3.141592}; #calculate sinusoid MUL temp1, windEffect, windEffect; # x^2 MAD sinWave, -temp1, gMinMaxConstants.w, gMinMaxConstants.z; # y = -(x^2)/7! + 1/5! MAD sinWave, sinWave, -temp1, gMinMaxConstants.y; # y = -(x^2) * (-(x^2)/7! + 1/5!) + 1/3! MAD sinWave, sinWave, -temp1, gMinMaxConstants.x; # y = -(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1 MUL sinWave, sinWave, windEffect; # y = x * (-(x^2) * (-(x^2) * (-(x^2)/7! + 1/5!) + 1/3!) + 1) # sinWave.x holds sin(norm . wind_direction) with primary frequency # sinWave.y holds sin(norm . wind_direction) with secondary frequency # sinWave.z hold cos(norm . wind_direction) with primary frequency MAD sinWave.xyz, sinWave, gWindDir.w, windEffect.w; # multiply by wind strength in gWindDir.w [-wind, wind] # add normal facing bias offset [-wind,wind] -> [-wind - .25, wind + 1] DP3 temp1, blendNorm, gGravity; # how much is this normal facing in direction of gGravity? MIN temp1, temp1, {0.2, 0, 0, 0}; # clamp [-1, 1] to [-1, 0.2] MUL temp1, temp1, {1.5, 0, 0, 0}; # scale from [-1,0.2] to [-1.5, 0.3] ADD sinWave.x, sinWave, temp1; # add gGravity effect to sinwave (only primary frequency) MUL sinWave.xyz, sinWave, iClothing.w; # modulate by clothing coverage #MAD temp2, {1,1,1,1}, iClothing.w, {-1,-1,-1,-1}; #ADD sinWave, sinWave, temp2; MAX sinWave.xyz, sinWave, {-1, -1, -1, -1}; # clamp to underlying body shape MUL offsetPos, iClothing, sinWave.x; # multiply wind effect times clothing displacement MAD temp2, gWindDir, sinWave.z, blendNorm; # calculate normal offset due to wind oscillation MAD offsetPos, {1.0, 1.0, 1.0, 0.0}, offsetPos, iPos; # add to offset vertex position, and zero out effect from w MAD blendNorm, temp2, {2, 2, 2, 2}, blendNorm; # add sin wave effect on normals (exaggerated) #add "backlighting" effect SUB colorAcc, {1, 1, 1, 1}, iClothing; MAD blendNorm, colorAcc.w, {0, 0, -0.2, 0}, blendNorm; #renormalize normal (again) DP3 divisor.w, blendNorm, blendNorm; RSQ divisor.xyz, divisor.w; MUL blendNorm.xyz, blendNorm, divisor; #project binormal to normal plane to ensure orthogonality DP3 temp2, blendNorm, blendBinorm; SUB blendBinorm, blendBinorm, temp2; #renormalize binormal DP3 divisor.w, blendBinorm, blendBinorm; RSQ divisor.xyz, divisor.w; MUL blendBinorm.xyz, blendBinorm, divisor; #tangent = binormal X normal XPD blendTangent, blendNorm, blendBinorm; #oTex1 = iTex0 + LLVector2( gLightDir0 * tangent, gLightDir0 * binormal ); DP3 blendTangent.x, gLightDir0, blendTangent; DP3 blendTangent.y, gLightDir0, blendBinorm; MAD oTex1, gEmbossScale.x, blendTangent, iTex0; #Output position DP4 blendPos.x, blendMatX, offsetPos; DP4 blendPos.y, blendMatY, offsetPos; DP4 blendPos.z, blendMatZ, offsetPos; MOV blendPos.w, {0, 0, 0, 1}; #Projection DP4 oPos.x, gProj[0], blendPos; DP4 oPos.y, gProj[1], blendPos; DP4 oPos.z, gProj[2], blendPos; DP4 oPos.w, gProj[3], blendPos; #Light 0 DP3 colorAcc.x, blendNorm, gLightDir0; MAD colorAcc.x, colorAcc.x, {0.55, 0.55, 0.55, 0.55}, {0.3, 0.3, 0.3, 0.3}; MAX colorAcc, colorAcc, {0, 0, 0, 0}; # Accumulate color contributions. MAD colorAcc.xyz, colorAcc.x, gDiffuseCol0, gModelAmbient; #Light 1 DP3 dots.x, blendNorm, gLightDir1; #Light 2 SUB lightDir, gLightPos2, blendPos; DP3 divisor.w, lightDir, lightDir; RSQ divisor.xyz, divisor.w; MUL lightDir, lightDir, divisor; DP3 dots.y, blendNorm, lightDir; #Light 3 SUB lightDir, gLightPos3, blendPos; DP3 divisor.w, lightDir, lightDir; RSQ divisor.xyz, divisor.w; MUL lightDir, lightDir, divisor; DP3 dots.z, blendNorm, lightDir; MAD dots, dots, {0.55, 0.55, 0.55, 0.55}, {0.3, 0.3, 0.3, 0.3}; MAX dots, dots, {0, 0, 0, 0}; MAD colorAcc, dots.x, gDiffuseCol1, colorAcc; MAD colorAcc, dots.y, gDiffuseCol2, colorAcc; MAD colorAcc, dots.z, gDiffuseCol3, colorAcc; #Output color MOV colorAcc.w, {0, 0, 0, 1.0}; MUL oCol0, gMaterialDiffuse, colorAcc; #Output tex coordinate MOV oTex0, iTex0; #Output fog MOV oFog.x, blendPos.z; END