0001: // -------------------------------------------------------------
0002: // Factored BRDF
0003: // 
0004: // Copyright (c) 2003 IMAGIRE Takashi. All rights reserved.
0005: // -------------------------------------------------------------
0006: 
0007: // -------------------------------------------------------------
0008: // グローバル変数
0009: // -------------------------------------------------------------
0010: float4x4 mWVP;
0011: float4x4 mWV;
0012: float4x4 mWV_IT;
0013: float4 LightPos;
0014: float4 EyePos;
0015: float4 alpha;
0016: 
0017: // -------------------------------------------------------------
0018: // テクスチャ
0019: // -------------------------------------------------------------
0020: texture MapP;
0021: sampler SampP = sampler_state
0022: {
0023:     Texture = <MapP>;
0024:     MinFilter = LINEAR;
0025:     MagFilter = LINEAR;
0026:     MipFilter = NONE;
0027: 
0028:     AddressU = Clamp;
0029:     AddressV = Clamp;
0030: };
0031: // -------------------------------------------------------------
0032: texture MapQ;
0033: sampler SampQ = sampler_state
0034: {
0035:     Texture = <MapQ>;
0036:     MinFilter = LINEAR;
0037:     MagFilter = LINEAR;
0038:     MipFilter = NONE;
0039: 
0040:     AddressU = Clamp;
0041:     AddressV = Clamp;
0042: };
0043: // -------------------------------------------------------------
0044: texture EnvMap;
0045: sampler SampEnv = sampler_state
0046: {
0047:     Texture = <EnvMap>;
0048:     MinFilter = POINT;
0049:     MagFilter = POINT;
0050:     MipFilter = NONE;
0051: 
0052:     AddressU = Clamp;
0053:     AddressV = Clamp;
0054: };
0055: // -------------------------------------------------------------
0056: // アプリケーションから頂点シェーダに渡すデータ
0057: // -------------------------------------------------------------
0058: struct VS_INPUT
0059: {
0060:     float4 Pos          : POSITION;
0061:     float3 Normal       : NORMAL0;
0062:     float2 Tex          : TEXCOORD0;
0063: };
0064: // -------------------------------------------------------------
0065: // 頂点シェーダからピクセルシェーダに渡すデータ
0066: // -------------------------------------------------------------
0067: struct VS_OUTPUT
0068: {
0069:     float4 Pos          : POSITION;
0070:     float4 v            : TEXCOORD0;
0071:     float4 h            : TEXCOORD1;
0072:     float4 l            : TEXCOORD2;
0073:     
0074:     float3 Nv           : TEXCOORD3;
0075:     
0076:     float4 Intensity    : COLOR0;
0077: };
0078: // -------------------------------------------------------------
0079: // 頂点シェーダからピクセルシェーダに渡すデータ
0080: // -------------------------------------------------------------
0081: struct PS_INPUT
0082: {
0083:     float4 Pos          : POSITION;
0084:     float2 Tex          : TEXCOORD0;
0085: };
0086: 
0087: // -------------------------------------------------------------
0088: // 座標変換
0089: // -------------------------------------------------------------
0090: float4 Q(float3 In, float3 B, float3 T, float3 N)
0091: {
0092:     float4 Out = (float4)0;
0093:     
0094:     // 表面座標系へ変換
0095:     float3 v;
0096:     v.x = dot(B,In);
0097:     v.y = dot(T,In);
0098:     v.z = dot(N,In);
0099:     
0100:     // 3次元パラメータを2次元パラメータに変換
0101:     float pv = 7.0f/8.0f;
0102:     float ar = 1.0/(2.0*(1.000000001+v.z));
0103: 
0104:     if(0.7*(8.0f/7.0f)<ar){
0105:         // 外に出た時は、強さを0にする
0106:         Out = 0;
0107:     }else if(0.5*(8.0f/7.0f)<ar){
0108:         // 途中は線形補間
0109:         Out = (0.7*(8.0f/7.0f)-ar)/(0.2*(8.0f/7.0f));
0110:     }else{
0111:         Out = 1;
0112:     }
0113:     
0114:     Out.x = pv * ar * v.x + 0.5;
0115:     Out.y = pv * ar * v.y + 0.5;
0116:     
0117:     return Out;
0118: }
0119: // -------------------------------------------------------------
0120: // 頂点シェーダプログラム
0121: // -------------------------------------------------------------
0122: VS_OUTPUT VS(VS_INPUT In)
0123: {   
0124:     VS_OUTPUT Out = (VS_OUTPUT)0;            // 出力データ
0125:     
0126:     // 位置座標
0127:     Out.Pos = mul( In.Pos, mWVP );
0128:     
0129:     // 表面座標系の基底ベクトルを求める
0130:     float3 N = In.Normal;                   // 法線ベクトル
0131:     float3 B = float3(0,1,0);               // 従法線ベクトル
0132:     float3 T = normalize(cross(N,B));       // 接ベクトル
0133:     B = cross(T,N);
0134:     
0135:     // 必要なベクトルを計算する
0136:     float3 V = normalize(EyePos  -In.Pos.xyz);// 視点ベクトル
0137:     float3 L = normalize(LightPos-In.Pos.xyz);// ライトベクトル
0138:     float3 H = normalize(L+V);              // ハーフベクトル
0139: 
0140:     // 各ベクトルをテクスチャ座標へ変換する
0141:     Out.v = Q(V, B,T,N);
0142:     Out.l = Q(L, B,T,N);
0143:     Out.h = Q(H, B,T,N);
0144:     
0145:     // とりあえず、ライトに関して背面の処理を入れる
0146:     Out.Intensity = Out.l.a;
0147: 
0148:     // 位置座標
0149:     Out.Nv = mul( In.Normal, mWV_IT );
0150:     
0151: 
0152:     return Out;
0153: }
0154: // -------------------------------------------------------------
0155: // ピクセルシェーダプログラム
0156: // -------------------------------------------------------------
0157: float4 PS(VS_OUTPUT In) : COLOR
0158: {   
0159:     float4 v = tex2D( SampP, In.v );
0160:     float4 h = tex2D( SampP, In.h );
0161:     float4 l = tex2D( SampQ, In.l );
0162:     float4 gross = alpha * v * h * l * In.Intensity;
0163:     
0164:     // 環境マップ
0165:     float3 Nv = normalize(In.Nv);
0166:     float3 Vv = float3(0,0,-1);
0167:     float3 r = 2 * dot(Nv, Vv)*Nv - Vv;
0168:     float  m = 0.5 * rsqrt(dot(Nv+Vv,Nv+Vv));// 規格化定数
0169:     float2 env_coord = {m * r.x + 0.5, - m * r.y + 0.5};
0170:     float4 hdr = tex2D( SampEnv, env_coord );
0171:     
0172:     float F = 0.9*pow(1-dot(Nv,r), 4) + 0.1;// 補正されたフレネル項
0173:     
0174:     // HDRをLDRに変換
0175:     float3 ldr = saturate( F * hdr.rgb * pow(2, 255*(hdr.a - 0.5) ));
0176:     
0177:     // 最終的に合成
0178:     return gross + float4(ldr,0);
0179: }
0180: // -------------------------------------------------------------
0181: // HDRをLDRに変換するピクセルシェーダプログラム
0182: // -------------------------------------------------------------
0183: float4 HDR_PS(PS_INPUT In) : COLOR
0184: {   
0185:     float4 ldr = (float4)0;
0186:     
0187:     float4 hdr = tex2D( SampEnv, In.Tex );
0188:     
0189:     ldr.rgb = saturate(hdr * pow(2, 255*(hdr.a - 0.5) ));
0190:     
0191:     return ldr;
0192: }
0193: // -------------------------------------------------------------
0194: // テクニック
0195: // -------------------------------------------------------------
0196: technique TShader
0197: {
0198:     pass P0
0199:     {
0200:         VertexShader = compile vs_1_1 VS();
0201:         PixelShader  = compile ps_2_0 PS();
0202:     }
0203:     pass P1
0204:     {
0205:         PixelShader  = compile ps_2_0 HDR_PS();
0206:     }
0207: }
0208: 
0209: