0001: // ---------------------------------------------------------------------------
0002: // 頂点シェーダ出力データ
0003: // ---------------------------------------------------------------------------
0004: struct vert2frag
0005: {
0006:     float4 hpos     : HPOS; // 頂点座標
0007:     float4 tcoords  : TEX0; // テクスチャ座標
0008:     float4 normal   : TEX1; // 法線ベクトル
0009:     float3 vlight   : TEX2; // ビュー座標のライト
0010:     float3 vhalf    : TEX3; // ビュー座標のハーフベクトル
0011: };
0012: //-----------------------------------------------------------------------------
0013: // -1から1の範囲のノイズをサンプリングする
0014: //-----------------------------------------------------------------------------
0015: float myNoise(texobj3D NoiseMap, float3 TexCoords)
0016: {
0017:     return 2.0 * f1tex3D(NoiseMap, TexCoords) - 1.0;
0018: }
0019: //-----------------------------------------------------------------------------
0020: // 木のパターンの半径を計算する
0021: //-----------------------------------------------------------------------------
0022: float getRadius(texobj3D NoiseMap, float3 fPos)
0023: {
0024:     float3 fTemp = fPos;    // 基本はテクスチャ座標
0025:     
0026:     // XY平面にノイズを追加
0027:     fTemp.x += myNoise(NoiseMap, 0.002 * fPos.xyz);
0028:     fTemp.y += myNoise(NoiseMap, 0.002 * fPos.xyz);
0029: 
0030:     float r = sqrt(dot(fTemp.xy, fTemp.xy));
0031: 
0032:     // 適当なノイズ
0033:     r += 0.1 * myNoise(NoiseMap,         fPos.xyz);
0034:     // Zで決まるノイズ
0035:     r += 0.5 * myNoise(NoiseMap, 0.001 * fPos.zzz);
0036: 
0037:     return  r;
0038: }
0039: 
0040: // ---------------------------------------------------------------------------
0041: // Perlin noise フラグメントプログラム
0042: // ---------------------------------------------------------------------------
0043: fragout main(vert2frag I
0044:             , uniform float4   fLightWood
0045:             , uniform float4   fDarkWood
0046:             , uniform float    fHighNoiseLevel
0047:             , uniform float    fBaseRadiusFreq
0048:             , uniform float    fLowPulseAmp
0049:             , uniform texobj3D NoiseMap : texunit0
0050:             , uniform texobj1D PulseTrainMap : texunit1
0051:     )
0052: {
0053:     fragout O;
0054: 
0055:     float3 fvNormal  = normalize(I.normal.xyz);
0056:     float3 fvLight   = normalize(I.vlight.xyz);
0057:     float3 fvHalfAng = normalize(I.vhalf.xyz);
0058: 
0059:     // 平行光源
0060:     float fDiffuseTerm = max(dot(fvNormal, fvLight), 0);    // ランバート
0061:     fDiffuseTerm += 0.22;                                   // 環境光
0062:     fDiffuseTerm = min(fDiffuseTerm, 1);                    // 0~1クランプ
0063: 
0064:     // 鏡面反射
0065:     float fDiffuseSpecTerm = min(fDiffuseTerm * 3, 1);      // スペキュラーの強さ
0066:     float fSpecularTerm = fDiffuseSpecTerm * pow(max(dot(fvNormal, fvHalfAng), 0), 30);
0067: 
0068: 
0069:     // 変位する大きさを決める
0070:     float fRadius = getRadius(NoiseMap, I.tcoords.xyz) * fBaseRadiusFreq;
0071: 
0072:     // 明るい色と暗い色を合成する合成係数
0073:     float t = 0.5 * (         f1tex1D(PulseTrainMap, fRadius)           // 普通に見える縞
0074:              + fLowPulseAmp * f1tex1D(PulseTrainMap, 0.131 * fRadius)); // グローバルな明暗
0075: 
0076:     // 最後の計算
0077:     O.col.xyz = (lerp(fLightWood, fDarkWood, t) * fDiffuseTerm).xyz     // 拡散光
0078:                 + ((1.3 - t) * fSpecularTerm).xxx                       // 鏡面反射
0079:                 + fHighNoiseLevel * myNoise(NoiseMap, I.tcoords.xyz);   // 高周波ノイズ
0080: 
0081: #if 0// デバッグ用。ノイズの形を見たいとき
0082: O.col.x = f1tex3D(NoiseMap, 0.01 * I.tcoords.xyz);
0083: O.col.y = f1tex3D(NoiseMap, 0.01 * I.tcoords.xyz);
0084: O.col.z = f1tex3D(NoiseMap, 0.01 * I.tcoords.xyz);
0085: #endif
0086: 
0087:     return O;
0088: } 
0089: