v 0. Pasted by Zeux as cpp at 2007-10-29 00:04:30 MSK and set expiration to never.

Paste will expire never. Expiration is locked.

  1. #define LIGHT_SPACE "Object"
  2. #include "bindings.h"
  3.  
  4. struct VS_IN
  5. {
  6.     float4 position: POSITION;
  7.  
  8.     float2 texcoord: TEXCOORD;
  9.  
  10.     float3 tangent: TANGENT;
  11.     float3 bitangent: BINORMAL;
  12.     float3 normal: NORMAL;
  13. };
  14.  
  15. struct VS_OUT
  16. {
  17.     float2 texcoord: TEXCOORD0;
  18.  
  19.     // view vector, tangent space
  20.     float3 view: TEXCOORD1;
  21.    
  22.     // light vectors, unnormalized, tangent space
  23.     // l0.x l1.x l2.x l3.x
  24.     // l0.y l1.y l2.y l3.y
  25.     // l0.z l1.z l2.z l3.z
  26.     // twice.
  27.     float4 lights[6]: TEXCOORD2;
  28. };
  29.  
  30. uniform float4x4 world_view_inverse: WorldViewInverse;
  31. uniform float4x4 world_view_projection: WorldViewProjection;
  32.  
  33. // light position, object space
  34. static float3 light_positions[8] =
  35. {
  36.     Lamp1Pos, Lamp2Pos, Lamp3Pos, Lamp4Pos,
  37.     Lamp5Pos, Lamp6Pos, Lamp7Pos, Lamp8Pos
  38. };
  39.  
  40. VS_OUT vs_main(VS_IN I, out float4 clippos: POSITION)
  41. {
  42.     clippos = mul(I.position, world_view_projection);
  43.  
  44.     VS_OUT O;
  45.    
  46.     O.texcoord = I.texcoord;
  47.    
  48.     // view vector
  49.     float3 eye_pos = mul(float4(0, 0, 0, 1), world_view_inverse);
  50.     float3 view = normalize(I.position - eye_pos);
  51.    
  52.     // transform to tangent space
  53.     O.view.x = dot(view, I.tangent);
  54.     O.view.y = dot(view, I.bitangent);
  55.     O.view.z = dot(view, I.normal);
  56.    
  57.     // note: this loop can be optimized if application feeds light data in SoA
  58.     // order, we can do SoA-style calculation here also. It's not quite easy to
  59.     // do in FX Composer, I guess, and anyway this is left as is for clarity.
  60.     for (int i = 0; i < 2; ++i)
  61.     {
  62.         // compute light vectors in tangent space
  63.         float3 light_vectors[4];
  64.  
  65.         for (int j = 0; j < 4; ++j)
  66.         {
  67.             float3 l = light_positions[i*4 + j] - I.position;
  68.  
  69.             light_vectors[j].x = dot(l, I.tangent);
  70.             light_vectors[j].y = dot(l, I.bitangent);
  71.             light_vectors[j].z = dot(l, I.normal);
  72.         }
  73.  
  74.         // splat in SoA order
  75.         O.lights[i*3 + 0] = float4(light_vectors[0].x, light_vectors[1].x, light_vectors[2].x, light_vectors[3].x);
  76.         O.lights[i*3 + 1] = float4(light_vectors[0].y, light_vectors[1].y, light_vectors[2].y, light_vectors[3].y);
  77.         O.lights[i*3 + 2] = float4(light_vectors[0].z, light_vectors[1].z, light_vectors[2].z, light_vectors[3].z);
  78.     }
  79.    
  80.     return O;
  81. }
  82.  
  83. // light colors
  84. static float3 light_colors[8] =
  85. {
  86.     Lamp1Col, Lamp2Col, Lamp3Col, Lamp4Col,
  87.     Lamp5Col, Lamp6Col, Lamp7Col, Lamp8Col
  88. };
  89.  
  90. // 1 / light radius^2
  91. uniform float4 light_radius_inv[2] =
  92. {
  93.     (1 / 0.25).xxxx,
  94.     (1 / 0.25).xxxx
  95. };
  96.  
  97. // specular power A, B constant
  98. // http://www.gamasutra.com/features/20020801/beaudoin_01.htm
  99. // m = 2, n = 18 => A = 6.645, B = -5.645
  100. uniform const float2 specular_ab = float2(6.645, -5.645);
  101.  
  102. texture diffuse_texture;
  103. uniform sampler2D diffuse_map = TRILINEAR_SAMPLER(diffuse_texture);
  104.  
  105. texture normal_texture;
  106. uniform sampler2D normal_map = TRILINEAR_SAMPLER(normal_texture);
  107.  
  108. texture specular_texture;
  109. uniform sampler2D specular_map = TRILINEAR_SAMPLER(specular_texture);
  110.  
  111. float4 compute_specular_power(float4 v)
  112. {
  113.     // originally: pow(v, N)
  114.     // x^N is roughly equal to (max(Ax+B, 0))^2
  115.     // A,B depend on N
  116.     float4 t = saturate(specular_ab.x * v + specular_ab.y);
  117.     return t * t;
  118. }
  119.  
  120. struct LightingData
  121. {
  122.     float4 diffuse;
  123.     float4 specular;
  124. };
  125.  
  126. LightingData computeLighting4(VS_OUT I, int light_bucket_index, float3 normal)
  127. {
  128.     // compute squared lengths in parallel
  129.     float4 squared_lengths = 0;
  130.  
  131.     for (int i = 0; i < 3; ++i)
  132.     {
  133.         squared_lengths += pow(I.lights[light_bucket_index * 3 + i], 2);
  134.     }
  135.  
  136.     // compute NdotL in parallel
  137.     float4 NdotL = 0;
  138.  
  139.     for (int i = 0; i < 3; ++i)
  140.     {
  141.         NdotL += I.lights[light_bucket_index * 3 + i] * normal[i];
  142.     }
  143.  
  144.     // compute RdotL in parallel
  145.     float3 reflected = reflect(I.view, normal);
  146.    
  147.     float4 RdotL = 0;
  148.  
  149.     for (int i = 0; i < 3; ++i)
  150.     {
  151.         RdotL += I.lights[light_bucket_index * 3 + i] * reflected[i];
  152.     }
  153.  
  154.     // correct NdotL and RdotL
  155.     float4 correction = 1 / sqrt(squared_lengths);
  156.     NdotL = saturate(NdotL * correction);
  157.     RdotL = saturate(RdotL * correction);
  158.  
  159.     // attenuation
  160.     // 1 - d^2 / r^2 for diffuse
  161.     float4 atten = squared_lengths * light_radius_inv[light_bucket_index];
  162.    
  163.     // modulate diffuse by attenuation
  164.     NdotL = saturate(NdotL - NdotL * atten);
  165.  
  166.     // specular
  167.     float4 spec = compute_specular_power(RdotL);
  168.  
  169.     LightingData data;
  170.  
  171.     data.diffuse = NdotL;
  172.     data.specular = spec;
  173.  
  174.     return data;
  175. }
  176.  
  177.  
  178. float4 ps_main(VS_OUT I): COLOR
  179. {
  180.     float3 normal = tex2D(normal_map, I.texcoord).xyz * 2 - 1;
  181.    
  182.     LightingData lights[] =
  183.     {
  184.         computeLighting4(I, 0, normal),
  185.         computeLighting4(I, 1, normal)
  186.     };
  187.  
  188.     // final diffuse color
  189.     float3 diffuse = 0;
  190.    
  191.     for (int i = 0; i < 8; ++i)
  192.     {
  193.         diffuse += lights[i/4].diffuse[i%4] * light_colors[i];
  194.     }
  195.    
  196.     // final specular color
  197.     float4 specular_color = tex2D(specular_map, I.texcoord);
  198.  
  199.     float3 specular = specular_color.rgb * saturate(dot(lights[0].specular + lights[1].specular, 1));
  200.  
  201.     // final color
  202.     float4 albedo = tex2D(diffuse_map, I.texcoord);
  203.  
  204.     return float4(albedo.rgb * diffuse + specular, albedo.a);
  205. }
  206.  
  207. technique t0
  208. {
  209.     pass p0
  210.     {
  211.         VertexShader = compile vs_1_1 vs_main();
  212.         PixelShader = compile ps_2_0 ps_main();
  213.     }
  214. }


Editing is locked.