Advertisement
Guest User

HLSL Normal Map Specular Shader - 3 Lights

a guest
Apr 9th, 2012
629
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.98 KB | None | 0 0
  1. /******************************************************************************
  2. HLSL Normal Map Specular Shader - 3 Lights
  3. by Ben Cloward
  4. bsmji@hotmail.com
  5. http://www.monitorstudios.com/bcloward/
  6.  
  7. This shader is based on several shaders written by Kevin Bjorke of Nvidia and
  8. included with the Cg plugin for 3DS Max 5.1.
  9.  
  10. This shader uses a normal map for per-pixel lighting - to give the illusion that
  11. the model surface contains more detail than is really there. It also adds a specular
  12. component for making models look shiny.
  13.  
  14. It accepts the following inputs:
  15.  
  16. Ambient Color
  17. Diffuse Color
  18. Diffuse Texture
  19. Specular Texture (a colored specular mask)
  20. Specular Color
  21. Shininess
  22. Normal Map Texture
  23. DXT5 Compressed Normal Map
  24. Flip Normal Map Green Channel
  25. Point Light1 Position
  26. Point Light1 Color
  27. Point Light2 Position
  28. Point Light2 Color
  29. Point Light3 Position
  30. Point Light3 Color
  31.  
  32. It requires hardware support for DirectX 9.
  33.  
  34. Normal Map compression is an option that you can use with this shader.
  35. Copy the red channel of your normal map to the alpha channel. Then delete the
  36. red and blue channels and save your normal map in DXT5 DDS format. Put your
  37. compressed normal map in the DXT5 Normal Map slot for the shader. Then choose
  38. "Compressed" as the technique instead of "complete."
  39.  
  40. This shader is intended to be used by the DirectX 9 shader of 3DS Max
  41. but it could also be used in other applications that support the FX format.
  42.  
  43. ******************************************************************************/
  44.  
  45. /************* TWEAKABLES **************/
  46.  
  47. half4 ambient : Ambient
  48. <
  49. string UIName = "Ambient Color";
  50. > = {0.25f, 0.25f, 0.25f, 1.0f};
  51.  
  52. half4 surfColor : Diffuse
  53. <
  54. string UIName = "Diffuse Color";
  55. > = {1.0f, 1.0f, 1.0f, 1.0f};
  56.  
  57. texture colorTexture : DiffuseMap
  58. <
  59. string name = "default_color.dds";
  60. string UIName = "Diffuse Texture";
  61. string TextureType = "2D";
  62. >;
  63.  
  64. texture specTexture : SpecularMap
  65. <
  66. string name = "default_color.dds";
  67. string UIName = "Specular Texture";
  68. string TextureType = "2D";
  69. >;
  70.  
  71. half4 specularColor : Specular
  72. <
  73. string UIName = "Specular Color";
  74. > = { 0.2f, 0.2f, 0.2f, 1.0f };
  75.  
  76. half shininess <
  77. string UIWidget = "slider";
  78. float UIMin = 1;
  79. float UIMax = 128;
  80. string UIName = "Shininess";
  81. > = 40;
  82.  
  83. texture normalMap : NormalMap
  84. <
  85. string name = "default_bump_normal.dds";
  86. string UIName = "Normal Map";
  87. string TextureType = "2D";
  88. >;
  89.  
  90. texture CnormalMap : CNormalMap
  91. <
  92. string name = "default_bump_normal.dds";
  93. string UIName = "DXT5 Normal Map";
  94. string TextureType = "2D";
  95. >;
  96.  
  97. bool direction
  98. <
  99. string gui = "slider";
  100. string UIName = "Flip Normal Map Green Channel";
  101. > = false;
  102.  
  103. /************** light info **************/
  104.  
  105. half4 light1Pos : POSITION
  106. <
  107. string UIName = "Light 1 Position";
  108. string Object = "PointLight";
  109. string Space = "World";
  110. int refID = 0;
  111. > = {100.0f, 100.0f, 100.0f, 0.0f};
  112.  
  113. half4 light1Color : LIGHTCOLOR
  114. <
  115. int LightRef = 0;
  116. > = { 1.0f, 1.0f, 1.0f, 0.0f };
  117. //----------------------------------
  118. half4 light2Pos : POSITION
  119. <
  120. string UIName = "Light 2 Position";
  121. string Object = "PointLight";
  122. string Space = "World";
  123. int refID = 1;
  124. > = {-100.0f, 100.0f, 100.0f, 0.0f};
  125.  
  126. half4 light2Color : LIGHTCOLOR
  127. <
  128. int LightRef = 1;
  129. > = { 1.0f, 1.0f, 1.0f, 0.0f };
  130. //----------------------------------
  131. half4 light3Pos : POSITION
  132. <
  133. string UIName = "Light 3 Position";
  134. string Object = "PointLight";
  135. string Space = "World";
  136. int refID = 2;
  137. > = {100.0f, -100.0f, 100.0f, 0.0f};
  138.  
  139. half4 light3Color : LIGHTCOLOR
  140. <
  141. int LightRef = 2;
  142. > = { 1.0f, 1.0f, 1.0f, 0.0f };
  143.  
  144. /****************************************************/
  145. /********** SAMPLERS ********************************/
  146. /****************************************************/
  147.  
  148. sampler2D colorTextureSampler = sampler_state
  149. {
  150. Texture = <colorTexture>;
  151. MinFilter = Linear;
  152. MagFilter = Linear;
  153. MipFilter = Anisotropic;
  154. };
  155.  
  156. sampler2D specTextureSampler = sampler_state
  157. {
  158. Texture = <specTexture>;
  159. MinFilter = Linear;
  160. MagFilter = Linear;
  161. MipFilter = Anisotropic;
  162. };
  163.  
  164. sampler2D normalMapSampler = sampler_state
  165. {
  166. Texture = <normalMap>;
  167. MinFilter = Linear;
  168. MagFilter = Linear;
  169. MipFilter = Anisotropic;
  170. };
  171.  
  172. sampler2D CnormalMapSampler = sampler_state
  173. {
  174. Texture = <CnormalMap>;
  175. MinFilter = Linear;
  176. MagFilter = Linear;
  177. MipFilter = Anisotropic;
  178. };
  179.  
  180. /***********************************************/
  181. /*** automatically-tracked "tweakables" ********/
  182. /***********************************************/
  183.  
  184. half4x4 wvp : WorldViewProjection < string UIWidget = "None"; >;
  185. half4x4 worldIT : WorldInverseTranspose < string UIWidget = "None"; >;
  186. half4x4 viewInv : ViewInverse < string UIWidget = "None"; >;
  187. half4x4 world : World < string UIWidget = "None"; >;
  188.  
  189.  
  190. /****************************************************/
  191. /********** CG SHADER FUNCTIONS *********************/
  192. /****************************************************/
  193.  
  194. // input from application
  195. struct a2v {
  196. half4 position : POSITION;
  197. half2 texCoord : TEXCOORD0;
  198. half3 tangent : TANGENT;
  199. half3 binormal : BINORMAL;
  200. half3 normal : NORMAL;
  201. };
  202.  
  203. // output to fragment program
  204. struct v2f {
  205. half4 position : POSITION;
  206. half2 texCoord : TEXCOORD0;
  207. half3 eyeVec : TEXCOORD1;
  208. half3 lightVec : TEXCOORD2;
  209. half3 worldNormal : TEXCOORD3;
  210. half3 worldTangent : TEXCOORD4;
  211. half3 worldBinormal : TEXCOORD5;
  212. };
  213.  
  214. // blinn lighting with lit function
  215. half4 blinn2(half3 N,
  216. half3 L,
  217. half3 V,
  218. uniform half4 specularColor,
  219. uniform half shininess
  220. )
  221. {
  222. half3 H = normalize(V+L);
  223. half4 lighting = lit(dot(L,N), dot(H,N), shininess);
  224. return lighting.y + specularColor*lighting.z;
  225. }
  226.  
  227. /**************************************/
  228. /***** VERTEX SHADER ******************/
  229. /**************************************/
  230.  
  231. v2f v(a2v In, uniform half4 lightPosition)
  232. {
  233. v2f Out;
  234. Out.worldNormal = mul(In.normal, worldIT).xyz;
  235. Out.worldTangent = mul(In.tangent, worldIT).xyz;
  236. Out.worldBinormal = mul(In.binormal, worldIT).xyz;
  237. //can use either positive or negative y format normal maps
  238. //comment out this if statement to save 6 instructions!
  239. if (direction == true) Out.worldTangent = -Out.worldTangent;
  240. half3 worldSpacePos = mul(In.position, world);
  241. Out.lightVec = lightPosition - worldSpacePos;
  242. Out.texCoord.xy = In.texCoord;
  243. Out.eyeVec = viewInv[3].xyz - worldSpacePos;
  244. Out.position = mul(In.position, wvp);
  245. return Out;
  246. }
  247.  
  248. /**************************************/
  249. /***** FRAGMENT PROGRAM ***************/
  250. /**************************************/
  251.  
  252. float4 f(v2f In,uniform half4 lightColor) : COLOR
  253. {
  254. //fetch the diffuse and normal and spec maps
  255. half4 colorMap = tex2D(colorTextureSampler, In.texCoord.xy);
  256. half4 specMap = tex2D(specTextureSampler, In.texCoord.xy);
  257. half3 normal = tex2D(normalMapSampler, In.texCoord).xyz * 2.0 - 1.0;
  258.  
  259. //create tangent space vectors
  260. half3 Nn = In.worldNormal;
  261. half3 Tn = In.worldTangent;
  262. half3 Bn = In.worldBinormal;
  263.  
  264. //these vectors could be normalized, but it costs 4 more instructions
  265. //and makes almost no difference to image quality
  266. //half3 Nn = normalize(In.worldNormal);
  267. //half3 Tn = normalize(In.worldTangent);
  268. //half3 Bn = normalize(In.worldBinormal);
  269.  
  270. //offset world space normal with normal map values
  271. half3 N = (Nn * normal.z) + (normal.x * Bn + normal.y * -Tn);
  272. N = normalize(N);
  273.  
  274. //create lighting vectors - view vector and light vector
  275. half3 V = normalize(In.eyeVec);
  276. half3 L = normalize(In.lightVec.xyz);
  277.  
  278. //lighting
  279.  
  280. //lighting
  281.  
  282. //ambient light
  283. half4 C = ambient*colorMap * 0.33;
  284.  
  285. //specular color
  286. half4 specCol = specularColor*specMap;
  287.  
  288. //diffuse and specular
  289. C += lightColor * blinn2(N, L, V, specCol, shininess);
  290. C *= colorMap*surfColor;
  291.  
  292. return C;
  293. }
  294.  
  295. float4 f2(v2f In,uniform half4 lightColor) : COLOR
  296. {
  297. //fetch the diffuse, specular and normal maps
  298. half4 colorMap = tex2D(colorTextureSampler, In.texCoord.xy);
  299. half4 specMap = tex2D(specTextureSampler, In.texCoord.xy);
  300. //swizzle the compressed dxt5 format
  301. half3 normal = tex2D(CnormalMapSampler, In.texCoord).wyz * 2.0 - 1.0;
  302. //generate the z component of the vector
  303. normal.z = sqrt(1 - normal.x * normal.x - normal.y * normal.y);
  304.  
  305. //create tangent space vectors
  306. half3 Nn = In.worldNormal;
  307. half3 Tn = In.worldTangent;
  308. half3 Bn = In.worldBinormal;
  309.  
  310. //these vectors could be normalized, but it costs 4 more instructions
  311. //and makes almost no difference to image quality
  312. //half3 Nn = normalize(In.worldNormal);
  313. //half3 Tn = normalize(In.worldTangent);
  314. //half3 Bn = normalize(In.worldBinormal);
  315.  
  316. //offset world space normal with normal map values
  317. half3 N = (Nn * normal.z) + (normal.x * Bn + normal.y * -Tn);
  318. N = normalize(N);
  319.  
  320. //create lighting vectors - view vector and light vector
  321. half3 V = normalize(In.eyeVec);
  322. half3 L = normalize(In.lightVec.xyz);
  323.  
  324. //lighting
  325.  
  326. //ambient light
  327. half4 C = ambient*colorMap * 0.33;
  328.  
  329. //specular color
  330. half4 specCol = specularColor*specMap;
  331.  
  332. //diffuse and specular
  333. C += lightColor * blinn2(N, L, V, specCol, shininess);
  334. C *= colorMap*surfColor;
  335.  
  336. return C;
  337. }
  338.  
  339.  
  340. /****************************************************/
  341. /********** TECHNIQUES ******************************/
  342. /****************************************************/
  343.  
  344. technique Complete
  345. {
  346. pass light1
  347. {
  348. VertexShader = compile vs_1_1 v(light1Pos);
  349. ZEnable = true;
  350. ZWriteEnable = true;
  351. CullMode = cw;
  352. AlphaBlendEnable = false;
  353. PixelShader = compile ps_2_0 f(light1Color);
  354. }
  355.  
  356. pass light2
  357. {
  358. VertexShader = compile vs_1_1 v(light2Pos);
  359. ZEnable = true;
  360. ZWriteEnable = false;
  361. ZFunc = LessEqual;
  362. CullMode = None;
  363. AlphaBlendEnable = true;
  364. SrcBlend = One;
  365. DestBlend = One;
  366. PixelShader = compile ps_2_0 f(light2Color);
  367. }
  368.  
  369. pass light3
  370. {
  371. VertexShader = compile vs_1_1 v(light3Pos);
  372. ZEnable = true;
  373. ZWriteEnable = false;
  374. ZFunc = LessEqual;
  375. CullMode = None;
  376. AlphaBlendEnable = true;
  377. SrcBlend = One;
  378. DestBlend = One;
  379. PixelShader = compile ps_2_0 f(light3Color);
  380. }
  381. }
  382.  
  383. technique Compressed
  384. {
  385. pass light1
  386. {
  387. VertexShader = compile vs_1_1 v(light1Pos);
  388. ZEnable = true;
  389. ZWriteEnable = true;
  390. CullMode = cw;
  391. AlphaBlendEnable = false;
  392. PixelShader = compile ps_2_0 f2(light1Color);
  393. }
  394.  
  395. pass light2
  396. {
  397. VertexShader = compile vs_1_1 v(light2Pos);
  398. ZEnable = true;
  399. ZWriteEnable = false;
  400. ZFunc = LessEqual;
  401. CullMode = None;
  402. AlphaBlendEnable = true;
  403. SrcBlend = One;
  404. DestBlend = One;
  405. PixelShader = compile ps_2_0 f2(light2Color);
  406. }
  407.  
  408. pass light3
  409. {
  410. VertexShader = compile vs_1_1 v(light3Pos);
  411. ZEnable = true;
  412. ZWriteEnable = false;
  413. ZFunc = LessEqual;
  414. CullMode = None;
  415. AlphaBlendEnable = true;
  416. SrcBlend = One;
  417. DestBlend = One;
  418. PixelShader = compile ps_2_0 f2(light3Color);
  419. }
  420. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement