====== Example wind shader ====== SpeedTree's wind system can be used in either a full SDK integration or a light/partial integration. The example code below is a DirectX 11 example of using the SDK shader wind functions. It also shows how to unpack the wind data if it was packed with the standard SDK/Standard games vertex packers in the SpeedTree Modeler. These is the approach we used for the reference application, but developers can override any or all of it as needed. /////////////////////////////////////////////////////////////////////// // Main SpeedTree wind system for shaders and C++ #include "SpeedTree/Core/SpeedTreeWind.h" /////////////////////////////////////////////////////////////////////// // Utility_UnpackNormalFibonacci // // Used for unpacking normals packed in our vertex packing example // using our Lua function pack_normal_fibonacci(). float3 UnpackNormalFibonacci(float fPacked) { float fZ = 0.99609375 - 0.0078125 * fPacked; float fRadius = sqrt(1.0 - fZ * fZ); float fTheta = fPacked * 2.39996322973; return float3(cos(fTheta) * fRadius, sin(fTheta) * fRadius, fZ); } /////////////////////////////////////////////////////////////////////// // Utility_UnpackInteger3 // // This is used for unpacking integers in the speedtree vertex packing // example using our Lua function pack_integer(). float3 UnpackInteger3(float fValue, float3 vCoef) { float3 vReturn; float fXY = vCoef.x * vCoef.y; vReturn.z = floor(fValue / fXY); fValue -= vReturn.z * fXY; vReturn.y = floor(fValue / vCoef.x); fValue -= vReturn.y * vCoef.x; vReturn.x = fValue; return vReturn / (vCoef - float3(1,1,1)); } // example shader constants // // in our reference application, these values are made available in the // shader constant "u_sBaseTree" float3 vTreeExtentsMin; float3 vTreeExtentsMax; // in C++, the SWindStateSdk value is given by the CWindStateMgr class defined // in SpeedTreeWind.h. Specifically, CWindStateMgr::GetShaderConstants() -- see // the SDK reference application and online docs for details. SWindStateSdk sCpuWindState; /////////////////////////////////////////////////////////////////////// // main void main(// mesh input float4 vPos : POSITION, float3 vNormal : TEXCOORD0, float3 vBinormal : TEXCOORD1, float3 vTangent : TEXCOORD2, float4 vWindBranch1 : TEXCOORD3, // x=weight, y=dir, z=offset, w=ripple float3 vWindBranch2 : TEXCOORD4, // x=weight, y=dir, z=offset // per-instance input float4 vInstance0 : TEXCOORD5, // xyz=position, w=scalar float3 vInstance1 : TEXCOORD6, // xyz=up vector float3 vInstance2 : TEXCOORD7, // xyz=right vector // output out float4 vOutputPos : SV_POSITION, out float3 vOutputNormal : TEXCOORD0) { // skipping several routine vs items for brevity, including orienting pos // and normals based on instance orientation // pass data into speedtree's game wind system -- SWindInputSdk has // four sections: // - m_sVertex: all per-vertex data // - m_sInstance: data about the pos and orientation of this instance // - m_sOptions: compile-time flags for which wind effects to enable // - m_sState: values from the CWindStateMgr class running on CPU SWindInputSdk sWindInput; // vertex sWindInput.m_sVertex.m_vPosition = vPos.xyz; sWindInput.m_sVertex.m_vNormal = vNormal; sWindInput.m_sVertex.m_vBinormal = vBinormal; sWindInput.m_sVertex.m_vTangent = vTangent; // wind data sWindInput.m_sVertex.m_fRippleWeight = vWindBranch1.w; sWindInput.m_sVertex.m_sBranch1.m_fWeight = vWindBranch1.x; sWindInput.m_sVertex.m_sBranch1.m_vDir = UnpackNormalFibonacci(float(vWindBranch1.y));; sWindInput.m_sVertex.m_sBranch1.m_vNoiseOffset = UnpackInteger3(vWindBranch1.z * 255, float3(9, 9, 3)) * (vTreeExtentsMax - vTreeExtentsMin); sWindInput.m_sVertex.m_sBranch2.m_fWeight = vWindBranch2.x; sWindInput.m_sVertex.m_sBranch2.m_vDir = UnpackNormalFibonacci(float(vWindBranch2.y));; sWindInput.m_sVertex.m_sBranch2.m_vNoiseOffset = UnpackInteger3(vWindBranch2.z * 255, float3(9, 9, 3)) * (vTreeExtentsMax - vTreeExtentsMin); // wind toggles sWindInput.m_sOptions.m_bDoShared = true; sWindInput.m_sOptions.m_bDoBranch1 = true; sWindInput.m_sOptions.m_bDoBranch2 = true; sWindInput.m_sOptions.m_bDoRipple = true; sWindInput.m_sOptions.m_bDoShimmer = true; sWindInput.m_sOptions.m_bLodFade = false; sWindInput.m_sOptions.m_bIsGrass = false; sWindInput.m_sOptions.m_fWindIndependence = 0.5; // instance sWindInput.m_sInstance.m_vPosition = vInstance0.xyz; sWindInput.m_sInstance.m_fScalar = vInstance0.w; sWindInput.m_sInstance.m_vOrientationUp = vInstance1; sWindInput.m_sInstance.m_vOrientationRight = vInstance2; sWindInput.m_sInstance.m_fLodValue = 0.0; // unused sWindInput.m_sInstance.m_fLodTransition = 0.0; // unused // cpu-side state sWindInput.m_sState = sCpuWindState; // call main wind function WindSdk(sWindInput); // WindSdk modifies position and can modify the normal (if m_bDoShimmer is enabled) vOutputPos = float4(sWindInput.m_sVertex.m_vPosition, 1.0); vOutputNormal = sWindInput.m_sVertex.m_vNormal; // position projection skipped for brevity... } The vertex shader above can be compiled using the following HLSL compiler fxc.exe compilation command for DirectX 11, assuming a working directory of ''[SDK]/SampleForest/Shaders/'' and a source filename of ''speedtree_wind_example_vs.hlsl''. {{:sdk:sample_wind_shader_compilation_dx11_9.5.0.jpg|}}