ShaderEffect.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. //-----------------------------------------------------------------------------
  2. // ShaderEffect.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.IO;
  12. using System.Text;
  13. using RacingGame.Graphics;
  14. using RacingGame.Helpers;
  15. using Texture = RacingGame.Graphics.Texture;
  16. using XnaTexture = Microsoft.Xna.Framework.Graphics.Texture;
  17. namespace RacingGame.Shaders
  18. {
  19. /// <summary>
  20. /// Shader effect class. You can either directly use this class by
  21. /// providing a fx filename in the constructor or derive from this class
  22. /// for special shader functionality (see post screen shaders for a more
  23. /// complex example).
  24. /// </summary>
  25. public class ShaderEffect : IDisposable
  26. {
  27. /// <summary>
  28. /// Line rendering shader
  29. /// </summary>
  30. public static ShaderEffect lineRendering =
  31. new ShaderEffect("LineRendering.fx");
  32. /// <summary>
  33. /// Simple shader with just per pixel lighting for testing.
  34. /// </summary>
  35. public static ShaderEffect lighting =
  36. new ShaderEffect("LightingShader.fx");
  37. /// <summary>
  38. /// Normal mapping shader for simple objects and the landscape rendering.
  39. /// </summary>
  40. public static ShaderEffect normalMapping =
  41. new ShaderEffect("NormalMapping.fx");
  42. /// <summary>
  43. /// Landscape normal mapping shader for the landscape rendering with
  44. /// detail texture support, everything else should use normalMapping.
  45. /// </summary>
  46. public static ShaderEffect landscapeNormalMapping =
  47. new ShaderEffect("LandscapeNormalMapping.fx");
  48. /// <summary>
  49. /// Shadow mapping shader
  50. /// </summary>
  51. public static ShadowMapShader shadowMapping =
  52. new ShadowMapShader();
  53. /// <summary>
  54. /// Content name for this shader
  55. /// </summary>
  56. private string shaderContentName = "";
  57. /// <summary>
  58. /// Effect
  59. /// </summary>
  60. protected Effect effect = null;
  61. /// <summary>
  62. /// Effect handles for shaders.
  63. /// </summary>
  64. protected EffectParameter worldViewProj,
  65. viewProj,
  66. world,
  67. viewInverse,
  68. projection,
  69. lightDir,
  70. ambientColor,
  71. diffuseColor,
  72. specularColor,
  73. specularPower,
  74. alphaFactor,
  75. scale,
  76. diffuseTexture,
  77. normalTexture,
  78. heightTexture,
  79. reflectionCubeTexture,
  80. detailTexture,
  81. parallaxAmount,
  82. carHueColorChange;
  83. /// <summary>
  84. /// Is this shader valid to render? If not we can't perform any rendering.
  85. /// </summary>
  86. /// <returns>Bool</returns>
  87. public bool Valid
  88. {
  89. get
  90. {
  91. return effect != null;
  92. }
  93. }
  94. /// <summary>
  95. /// Effect
  96. /// </summary>
  97. /// <returns>Effect</returns>
  98. public Effect Effect
  99. {
  100. get
  101. {
  102. return effect;
  103. }
  104. }
  105. /// <summary>
  106. /// Number of techniques
  107. /// </summary>
  108. /// <returns>Int</returns>
  109. public int NumberOfTechniques
  110. {
  111. get
  112. {
  113. return effect.Techniques.Count;
  114. }
  115. }
  116. /// <summary>
  117. /// Get technique
  118. /// </summary>
  119. /// <param name="techniqueName">Technique name</param>
  120. /// <returns>Effect technique</returns>
  121. public EffectTechnique GetTechnique(string techniqueName)
  122. {
  123. return effect.Techniques[techniqueName];
  124. }
  125. /// <summary>
  126. /// World parameter
  127. /// </summary>
  128. /// <returns>Effect parameter</returns>
  129. public EffectParameter WorldParameter
  130. {
  131. get
  132. {
  133. return world;
  134. }
  135. }
  136. /// <summary>
  137. /// Set value helper to set an effect parameter.
  138. /// </summary>
  139. /// <param name="param">Param</param>
  140. /// <param name="setMatrix">Set matrix</param>
  141. private static void SetValue(EffectParameter param,
  142. ref Matrix lastUsedMatrix, Matrix newMatrix)
  143. {
  144. // Always update, matrices change every frame anyway!
  145. lastUsedMatrix = newMatrix;
  146. param.SetValue(newMatrix);
  147. }
  148. /// <summary>
  149. /// Set value helper to set an effect parameter.
  150. /// </summary>
  151. /// <param name="param">Param</param>
  152. /// <param name="lastUsedVector">Last used vector</param>
  153. /// <param name="newVector">New vector</param>
  154. private static void SetValue(EffectParameter param,
  155. ref Vector3 lastUsedVector, Vector3 newVector)
  156. {
  157. if (param != null &&
  158. lastUsedVector != newVector)
  159. {
  160. lastUsedVector = newVector;
  161. param.SetValue(newVector);
  162. }
  163. }
  164. /// <summary>
  165. /// Set value helper to set an effect parameter.
  166. /// </summary>
  167. /// <param name="param">Param</param>
  168. /// <param name="lastUsedColor">Last used color</param>
  169. /// <param name="newColor">New color</param>
  170. private static void SetValue(EffectParameter param,
  171. ref Color lastUsedColor, Color newColor)
  172. {
  173. // Note: This check eats few % of the performance, but the color
  174. // often stays the change (around 50%).
  175. if (param != null &&
  176. //slower: lastUsedColor != newColor)
  177. lastUsedColor.PackedValue != newColor.PackedValue)
  178. {
  179. lastUsedColor = newColor;
  180. param.SetValue(newColor.ToVector4());
  181. }
  182. }
  183. /// <summary>
  184. /// Set value helper to set an effect parameter.
  185. /// </summary>
  186. /// <param name="param">Param</param>
  187. /// <param name="lastUsedValue">Last used value</param>
  188. /// <param name="newValue">New value</param>
  189. private static void SetValue(EffectParameter param,
  190. ref float lastUsedValue, float newValue)
  191. {
  192. if (param != null &&
  193. lastUsedValue != newValue)
  194. {
  195. lastUsedValue = newValue;
  196. param.SetValue(newValue);
  197. }
  198. }
  199. /// <summary>
  200. /// Set value helper to set an effect parameter.
  201. /// </summary>
  202. /// <param name="param">Param</param>
  203. /// <param name="lastUsedValue">Last used value</param>
  204. /// <param name="newValue">New value</param>
  205. private static void SetValue(EffectParameter param,
  206. ref XnaTexture lastUsedValue, XnaTexture newValue)
  207. {
  208. if (param != null &&
  209. lastUsedValue != newValue)
  210. {
  211. lastUsedValue = newValue;
  212. param.SetValue(newValue);
  213. }
  214. }
  215. protected Matrix lastUsedWorldViewProjMatrix = Matrix.Identity;
  216. /// <summary>
  217. /// Set world view proj matrix
  218. /// </summary>
  219. protected Matrix WorldViewProjMatrix
  220. {
  221. get
  222. {
  223. // Note: Only implemented for stupid FxCop rule,
  224. // you should never "get" a shader texture this way!
  225. return lastUsedWorldViewProjMatrix;
  226. }
  227. set
  228. {
  229. SetValue(worldViewProj, ref lastUsedWorldViewProjMatrix, value);
  230. }
  231. }
  232. protected Matrix lastUsedViewProjMatrix = Matrix.Identity;
  233. /// <summary>
  234. /// Set view proj matrix
  235. /// </summary>
  236. protected Matrix ViewProjMatrix
  237. {
  238. get
  239. {
  240. // Note: Only implemented for stupid FxCop rule,
  241. // you should never "get" a shader texture this way!
  242. return lastUsedViewProjMatrix;
  243. }
  244. set
  245. {
  246. SetValue(viewProj, ref lastUsedViewProjMatrix, value);
  247. }
  248. }
  249. /// <summary>
  250. /// Set world matrix
  251. /// </summary>
  252. public Matrix WorldMatrix
  253. {
  254. get
  255. {
  256. // Note: Only implemented for stupid FxCop rule,
  257. // you should never "get" a shader texture this way!
  258. return Matrix.Identity;//makes REALLY no sense!
  259. }
  260. set
  261. {
  262. // Faster, we checked world matrix in constructor.
  263. if (world != null)
  264. world.SetValue(value);
  265. }
  266. }
  267. protected Matrix lastUsedInverseViewMatrix = Matrix.Identity;
  268. /// <summary>
  269. /// Set view inverse matrix
  270. /// </summary>
  271. protected Matrix InverseViewMatrix
  272. {
  273. get
  274. {
  275. // Note: Only implemented for stupid FxCop rule,
  276. // you should never "get" a shader texture this way!
  277. return lastUsedInverseViewMatrix;
  278. }
  279. set
  280. {
  281. viewInverse.SetValue (value.Translation);
  282. //SetValue(viewInverse, ref lastUsedInverseViewMatrix, value);
  283. }
  284. }
  285. protected Matrix lastUsedProjectionMatrix = Matrix.Identity;
  286. /// <summary>
  287. /// Set projection matrix
  288. /// </summary>
  289. protected Matrix ProjectionMatrix
  290. {
  291. get
  292. {
  293. // Note: Only implemented for stupid FxCop rule,
  294. // you should never "get" a shader texture this way!
  295. return lastUsedProjectionMatrix;
  296. }
  297. set
  298. {
  299. SetValue(projection, ref lastUsedProjectionMatrix, value);
  300. }
  301. }
  302. protected Vector3 lastUsedLightDir = Vector3.Zero;
  303. /// <summary>
  304. /// Set light direction
  305. /// </summary>
  306. protected Vector3 LightDir
  307. {
  308. get
  309. {
  310. // Note: Only implemented for stupid FxCop rule,
  311. // you should never "get" a shader texture this way!
  312. return lastUsedLightDir;
  313. }
  314. set
  315. {
  316. // Make sure lightDir is normalized (fx files are optimized
  317. // to work with a normalized lightDir vector)
  318. value.Normalize();
  319. // Set negative value, shader is optimized not to negate dir!
  320. SetValue(lightDir, ref lastUsedLightDir, -value);
  321. }
  322. }
  323. protected Color lastUsedAmbientColor = ColorHelper.Empty;
  324. /// <summary>
  325. /// Ambient color
  326. /// </summary>
  327. public Color AmbientColor
  328. {
  329. get
  330. {
  331. // Note: Only implemented for stupid FxCop rule,
  332. // you should never "get" a shader texture this way!
  333. return lastUsedAmbientColor;
  334. }
  335. set
  336. {
  337. SetValue(ambientColor, ref lastUsedAmbientColor, value);
  338. }
  339. }
  340. protected Color lastUsedDiffuseColor = ColorHelper.Empty;
  341. /// <summary>
  342. /// Diffuse color
  343. /// </summary>
  344. public Color DiffuseColor
  345. {
  346. get
  347. {
  348. // Note: Only implemented for stupid FxCop rule,
  349. // you should never "get" a shader texture this way!
  350. return lastUsedDiffuseColor;
  351. }
  352. set
  353. {
  354. SetValue(diffuseColor, ref lastUsedDiffuseColor, value);
  355. }
  356. }
  357. protected Color lastUsedSpecularColor = ColorHelper.Empty;
  358. /// <summary>
  359. /// Specular color
  360. /// </summary>
  361. public Color SpecularColor
  362. {
  363. get
  364. {
  365. // Note: Only implemented for stupid FxCop rule,
  366. // you should never "get" a shader texture this way!
  367. return lastUsedSpecularColor;
  368. }
  369. set
  370. {
  371. SetValue(specularColor, ref lastUsedSpecularColor, value);
  372. }
  373. }
  374. private float lastUsedSpecularPower = 0;
  375. /// <summary>
  376. /// SpecularPower for specular color
  377. /// </summary>
  378. public float SpecularPower
  379. {
  380. get
  381. {
  382. // Note: Only implemented for stupid FxCop rule,
  383. // you should never "get" a shader texture this way!
  384. return lastUsedSpecularPower;
  385. }
  386. set
  387. {
  388. SetValue(specularPower, ref lastUsedSpecularPower, value);
  389. }
  390. }
  391. private float lastUsedAlphaFactor = 0;
  392. /// <summary>
  393. /// Alpha factor
  394. /// </summary>
  395. /// <returns>Float</returns>
  396. public float AlphaFactor
  397. {
  398. get
  399. {
  400. // Note: Only implemented for stupid FxCop rule,
  401. // you should never "get" a shader texture this way!
  402. return lastUsedAlphaFactor;
  403. }
  404. set
  405. {
  406. SetValue(alphaFactor, ref lastUsedAlphaFactor, value);
  407. }
  408. }
  409. protected XnaTexture lastUsedDiffuseTexture = null;
  410. /// <summary>
  411. /// Set diffuse texture
  412. /// </summary>
  413. public Texture DiffuseTexture
  414. {
  415. get
  416. {
  417. // Note: Only implemented for stupid FxCop rule,
  418. // you should never "get" a shader texture this way!
  419. return null;//makes no sense!
  420. }
  421. set
  422. {
  423. SetValue(diffuseTexture, ref lastUsedDiffuseTexture,
  424. value != null ? value.XnaTexture : null);
  425. }
  426. }
  427. protected XnaTexture lastUsedNormalTexture = null;
  428. /// <summary>
  429. /// Set normal texture for normal mapping
  430. /// </summary>
  431. public Texture NormalTexture
  432. {
  433. get
  434. {
  435. // Note: Only implemented for stupid FxCop rule,
  436. // you should never "get" a shader texture this way!
  437. return null;//makes no sense!
  438. }
  439. set
  440. {
  441. SetValue(normalTexture, ref lastUsedNormalTexture,
  442. value != null ? value.XnaTexture : null);
  443. }
  444. }
  445. protected XnaTexture lastUsedHeightTexture = null;
  446. /// <summary>
  447. /// Set height texture for parallax mapping
  448. /// </summary>
  449. public Texture HeightTexture
  450. {
  451. get
  452. {
  453. // Note: Only implemented for stupid FxCop rule,
  454. // you should never "get" a shader texture this way!
  455. return null;//makes no sense!
  456. }
  457. set
  458. {
  459. SetValue(heightTexture, ref lastUsedHeightTexture,
  460. value != null ? value.XnaTexture : null);
  461. }
  462. }
  463. protected TextureCube lastUsedReflectionCubeTexture = null;
  464. /// <summary>
  465. /// Set reflection cube map texture for reflection stuff.
  466. /// </summary>
  467. public TextureCube ReflectionCubeTexture
  468. {
  469. get
  470. {
  471. return lastUsedReflectionCubeTexture;
  472. }
  473. set
  474. {
  475. if (reflectionCubeTexture != null &&
  476. lastUsedReflectionCubeTexture != value)
  477. {
  478. lastUsedReflectionCubeTexture = value;
  479. reflectionCubeTexture.SetValue(value);
  480. }
  481. }
  482. }
  483. protected XnaTexture lastUsedDetailTexture = null;
  484. /// <summary>
  485. /// Set height texture for parallax mapping
  486. /// </summary>
  487. public Texture DetailTexture
  488. {
  489. get
  490. {
  491. // Note: Only implemented for stupid FxCop rule,
  492. // you should never "get" a shader texture this way!
  493. return null;//makes no sense!
  494. }
  495. set
  496. {
  497. SetValue(detailTexture, ref lastUsedDetailTexture,
  498. value != null ? value.XnaTexture : null);
  499. }
  500. }
  501. protected float lastUsedParallaxAmount = -1.0f;
  502. /// <summary>
  503. /// Parallax amount for parallax and offset shaders.
  504. /// </summary>
  505. public float ParallaxAmount
  506. {
  507. get
  508. {
  509. // Note: Only implemented for stupid FxCop rule,
  510. // you should never "get" a shader texture this way!
  511. return lastUsedParallaxAmount;
  512. }
  513. set
  514. {
  515. SetValue(parallaxAmount, ref lastUsedParallaxAmount, value);
  516. }
  517. }
  518. protected Color lastUsedCarHueColorChange = ColorHelper.Empty;
  519. /// <summary>
  520. /// Shadow car color for the special ShadowCar shader.
  521. /// </summary>
  522. public Color CarHueColorChange
  523. {
  524. get
  525. {
  526. // Note: Only implemented for stupid FxCop rule,
  527. // you should never "get" a shader texture this way!
  528. return lastUsedCarHueColorChange;
  529. }
  530. set
  531. {
  532. SetValue(carHueColorChange, ref lastUsedCarHueColorChange, value);
  533. }
  534. }
  535. [System.Diagnostics.CodeAnalysis.SuppressMessage(
  536. "Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
  537. public ShaderEffect(string shaderName)
  538. {
  539. if (BaseGame.Device == null)
  540. throw new InvalidOperationException(
  541. "XNA device is not initialized, can't create ShaderEffect.");
  542. shaderContentName = Path.GetFileNameWithoutExtension(shaderName);
  543. Reload();
  544. }
  545. /// <summary>
  546. /// Dispose
  547. /// </summary>
  548. public void Dispose()
  549. {
  550. Dispose(true);
  551. GC.SuppressFinalize(this);
  552. }
  553. /// <summary>
  554. /// Dispose
  555. /// </summary>
  556. /// <param name="disposing">Disposing</param>
  557. protected virtual void Dispose(bool disposing)
  558. {
  559. if (disposing)
  560. {
  561. // Dispose shader effect
  562. if (effect != null)
  563. effect.Dispose();
  564. }
  565. }
  566. /// <summary>
  567. /// Reload effect (can be useful if we change the fx file dynamically).
  568. /// </summary>
  569. public void Reload()
  570. {
  571. // Load shader
  572. effect = BaseGame.Content.Load<Effect>(
  573. Path.Combine(Directories.ContentDirectory,
  574. "Shaders",
  575. shaderContentName));
  576. // Reset and get all available parameters.
  577. // This is especially important for derived classes.
  578. ResetParameters();
  579. GetParameters();
  580. SetParameterDefaultValues();
  581. }
  582. /// <summary>
  583. /// Reset parameters
  584. /// </summary>
  585. protected virtual void ResetParameters()
  586. {
  587. lastUsedInverseViewMatrix = Matrix.Identity;
  588. lastUsedAmbientColor = ColorHelper.Empty;
  589. lastUsedDiffuseTexture = null;
  590. }
  591. protected virtual void SetParameterDefaultValues()
  592. {
  593. }
  594. /// <summary>
  595. /// Get parameters, override to support more
  596. /// </summary>
  597. protected virtual void GetParameters()
  598. {
  599. worldViewProj = effect.Parameters["worldViewProj"];
  600. viewProj = effect.Parameters["viewProj"];
  601. world = effect.Parameters["world"];
  602. viewInverse = effect.Parameters["viewInverse"];
  603. projection = effect.Parameters["projection"];
  604. lightDir = effect.Parameters["lightDir"];
  605. ambientColor = effect.Parameters["ambientColor"];
  606. diffuseColor = effect.Parameters["diffuseColor"];
  607. specularColor = effect.Parameters["specularColor"];
  608. specularPower = effect.Parameters["specularPower"];
  609. alphaFactor = effect.Parameters["alphaFactor"];
  610. // Default alpha factor to 1.0f for hotels and stuff
  611. AlphaFactor = 1.0f;
  612. scale = effect.Parameters["scale"];
  613. diffuseTexture = effect.Parameters["diffuseTexture"];
  614. normalTexture = effect.Parameters["normalTexture"];
  615. heightTexture = effect.Parameters["heightTexture"];
  616. reflectionCubeTexture = effect.Parameters["reflectionCubeTexture"];
  617. detailTexture = effect.Parameters["detailTexture"];
  618. parallaxAmount = effect.Parameters["parallaxAmount"];
  619. carHueColorChange = effect.Parameters["carHueColorChange"];
  620. }
  621. /// <summary>
  622. /// Set parameters, this overload sets all material parameters too.
  623. /// </summary>
  624. public virtual void SetParameters(Material setMat)
  625. {
  626. if (worldViewProj != null)
  627. worldViewProj.SetValue(BaseGame.WorldViewProjectionMatrix);
  628. if (viewProj != null)
  629. viewProj.SetValue(BaseGame.ViewProjectionMatrix);
  630. if (world != null)
  631. world.SetValue(BaseGame.WorldMatrix);
  632. if (viewInverse != null)
  633. {
  634. if (viewInverse.ParameterClass == EffectParameterClass.Matrix)
  635. viewInverse.SetValue(BaseGame.InverseViewMatrix);
  636. else
  637. viewInverse.SetValue(BaseGame.InverseViewMatrix.Translation);
  638. }
  639. if (lightDir != null)
  640. lightDir.SetValue(BaseGame.LightDirection);
  641. // Set the reflection cube texture only once
  642. if (lastUsedReflectionCubeTexture == null &&
  643. reflectionCubeTexture != null)
  644. {
  645. ReflectionCubeTexture = BaseGame.UI.SkyCubeMapTexture;
  646. }
  647. // Set all material properties
  648. if (setMat != null)
  649. {
  650. AmbientColor = setMat.ambientColor;
  651. DiffuseColor = setMat.diffuseColor;
  652. SpecularColor = setMat.specularColor;
  653. SpecularPower = setMat.specularPower;
  654. DiffuseTexture = setMat.diffuseTexture;
  655. NormalTexture = setMat.normalTexture;
  656. HeightTexture = setMat.heightTexture;
  657. ParallaxAmount = setMat.parallaxAmount;
  658. DetailTexture = setMat.detailTexture;
  659. }
  660. }
  661. /// <summary>
  662. /// Set parameters, override to set more
  663. /// </summary>
  664. public virtual void SetParameters()
  665. {
  666. SetParameters(null);
  667. }
  668. /// <summary>
  669. /// Set parameters, this overload sets all material parameters too.
  670. /// </summary>
  671. public virtual void SetParametersOptimizedGeneral()
  672. {
  673. if (worldViewProj != null)
  674. worldViewProj.SetValue(BaseGame.WorldViewProjectionMatrix);
  675. if (viewProj != null)
  676. viewProj.SetValue(BaseGame.ViewProjectionMatrix);
  677. if (world != null)
  678. world.SetValue(BaseGame.WorldMatrix);
  679. if (viewInverse != null)
  680. viewInverse.SetValue(BaseGame.InverseViewMatrix.Translation);
  681. if (lightDir != null)
  682. lightDir.SetValue(BaseGame.LightDirection);
  683. // Set the reflection cube texture only once
  684. if (lastUsedReflectionCubeTexture == null &&
  685. reflectionCubeTexture != null)
  686. {
  687. ReflectionCubeTexture = BaseGame.UI.SkyCubeMapTexture;
  688. }
  689. // lastUsed parameters for colors and textures are not used,
  690. // but we overwrite the values in SetParametersOptimized.
  691. // We fix this by clearing all lastUsed values we will use later.
  692. lastUsedAmbientColor = ColorHelper.Empty;
  693. lastUsedDiffuseColor = ColorHelper.Empty;
  694. lastUsedSpecularColor = ColorHelper.Empty;
  695. lastUsedDiffuseTexture = null;
  696. lastUsedNormalTexture = null;
  697. }
  698. /// <summary>
  699. /// Set parameters, this overload sets all material parameters too.
  700. /// </summary>
  701. public virtual void SetParametersOptimized(Material setMat)
  702. {
  703. if (setMat == null)
  704. throw new ArgumentNullException("setMat");
  705. // No need to set world matrix, will be done later in mesh rendering
  706. // in the MeshRenderManager. All the rest is set with help of the
  707. // SetParametersOptimizedGeneral above.
  708. // Only update ambient, diffuse, specular and the textures, the rest
  709. // will not change for a material change in MeshRenderManager.
  710. ambientColor.SetValue(setMat.ambientColor.ToVector4());
  711. diffuseColor.SetValue(setMat.diffuseColor.ToVector4());
  712. specularColor.SetValue(setMat.specularColor.ToVector4());
  713. if (setMat.diffuseTexture != null)
  714. diffuseTexture.SetValue(setMat.diffuseTexture.XnaTexture);
  715. if (setMat.normalTexture != null)
  716. normalTexture.SetValue(setMat.normalTexture.XnaTexture);
  717. }
  718. /// <summary>
  719. /// Update
  720. /// </summary>
  721. public void Update()
  722. {
  723. for (int num = 0; num < effect.CurrentTechnique.Passes.Count; num++)
  724. {
  725. effect.CurrentTechnique.Passes[num].Apply();
  726. }
  727. }
  728. /// <summary>
  729. /// Render
  730. /// </summary>
  731. /// <param name="setMat">Set matrix</param>
  732. /// <param name="passName">Pass name</param>
  733. /// <param name="renderDelegate">Render delegate</param>
  734. public void Render(Material setMat,
  735. string techniqueName,
  736. BaseGame.RenderHandler renderCode)
  737. {
  738. if (techniqueName == null)
  739. throw new ArgumentNullException("techniqueName");
  740. if (renderCode == null)
  741. throw new ArgumentNullException("renderCode");
  742. SetParameters(setMat);
  743. // Start shader
  744. effect.CurrentTechnique = effect.Techniques[techniqueName];
  745. // Render all passes (usually just one)
  746. //foreach (EffectPass pass in effect.CurrentTechnique.Passes)
  747. for (int num = 0; num < effect.CurrentTechnique.Passes.Count; num++)
  748. {
  749. EffectPass pass = effect.CurrentTechnique.Passes[num];
  750. pass.Apply();
  751. renderCode();
  752. }
  753. }
  754. /// <summary>
  755. /// Render
  756. /// </summary>
  757. /// <param name="techniqueName">Technique name</param>
  758. /// <param name="renderDelegate">Render delegate</param>
  759. public void Render(string techniqueName,
  760. BaseGame.RenderHandler renderDelegate)
  761. {
  762. Render(null, techniqueName, renderDelegate);
  763. }
  764. /// <summary>
  765. /// Render single pass shader
  766. /// </summary>
  767. /// <param name="renderDelegate">Render delegate</param>
  768. public void RenderSinglePassShader(
  769. BaseGame.RenderHandler renderCode)
  770. {
  771. if (renderCode == null)
  772. throw new ArgumentNullException("renderCode");
  773. // Start effect (current technique should be set)
  774. // Start first pass
  775. effect.CurrentTechnique.Passes[0].Apply();
  776. // Render
  777. renderCode();
  778. }
  779. }
  780. }