Line 427: |
Line 427: |
| | | |
| ==Advanced== | | ==Advanced== |
− | ===IRawTextureData and performance=== | + | ===Use <samp>IRawTextureData</samp>=== |
| + | When loading image data, creating a <samp>Texture2D</samp> instance or calling its <samp>GetData</samp>/<samp>SetData</samp> methods is very expensive and involves GPU calls. You can avoid that by loading images as SMAPI's <samp>IRawTextureData</samp> instead, which returns the data directly with no GPU calls. You can then pass it directly to other SMAPI APIs like [[Modding:Modder Guide/APIs/Content#Edit an image|<samp>PatchImage</samp>]]. |
| | | |
− | Since the move to Monogame, the creation of Texture2Ds has become quite slow. To sidestep this issue, avoid creating Texture2Ds when not necessary. You can use SMAPI's <samp>IRawTextureData</samp> instead, which you can also pass to other SMAPI functions, like [[Modding:Modder_Guide/APIs/Content#Edit_an_image|<samp>PatchImage</samp>]].
| + | For example, this mod applies an image overlay to Abigail's portrait without loading the overlay as a <samp>Texture2D</samp> instance: |
| + | <syntaxhighlight lang="c#"> |
| + | public class ModEntry : Mod |
| + | { |
| + | public override void Entry(IModHelper helper) |
| + | { |
| + | helper.Events.Content.AssetRequested += this.OnAssetRequested; |
| + | } |
| + | |
| + | private void OnAssetRequested(object sender, AssetRequestedEventArgs e) |
| + | { |
| + | if (e.NameWithoutLocale.IsEquivalentTo("Portraits/Abigail")) |
| + | { |
| + | e.Edit(asset => |
| + | { |
| + | var editor = asset.AsImage(); |
| + | |
| + | IRawTextureData overlay = this.Helper.ModContent.Load<IRawTextureData>("assets/overlay.png"); |
| + | editor.PatchImage(overlay); |
| + | }); |
| + | } |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | You can also edit the <samp>IRawTextureData</samp> data directly before passing it to other methods. For example, this converts the texture to grayscale: |
| + | <syntaxhighlight lang="c#"> |
| + | IRawTextureData image = this.Helper.ModContent.Load<IRawTextureData>("assets/image.png"); |
| + | |
| + | for (int i = 0; i < image.Data.Length; i++) |
| + | { |
| + | Color color = image.Data[i]; |
| + | if (color.A == 0) |
| + | continue; // ignore transparent color |
| + | |
| + | int grayscale = (int)((color.R * 0.3) + (color.G * 0.59) + (color.B * 0.11)); // https://stackoverflow.com/a/596282/262123 |
| + | image.Data[i] = new Color(grayscale, grayscale, grayscale, color.A); |
| + | } |
| + | </syntaxhighlight> |
| | | |
| ===Compare asset names=== | | ===Compare asset names=== |