-
Notifications
You must be signed in to change notification settings - Fork 1
/
Texture.cs
executable file
·185 lines (160 loc) · 5.67 KB
/
Texture.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using SlimDX;
using D3D = SlimDX.Direct3D10;
namespace Direct3DExtensions
{
public class Texture : DisposablePattern
{
D3D.Texture2D texture;
D3D.ShaderResourceView textureView;
D3D.EffectResourceVariable textureResource;
D3D.Device device;
public D3D.Texture2DDescription Description { get { if (texture != null) return texture.Description; return new D3D.Texture2DDescription(); } }
public int Width { get { if (texture == null) return 0; return texture.Description.Width; } }
public int Height { get { if (texture == null) return 0; return texture.Description.Height; } }
public D3D.Texture2D Texture2D { get { return texture; } }
public D3D.ShaderResourceView TextureView { get { return textureView; } }
public Texture(D3D.Device device)
{
this.device = device;
}
public Texture(D3D.Device device, D3D.Effect effect, string textureName) : this(device)
{
BindToEffect(effect, textureName);
}
public void BindToEffect(D3D.Effect effect, string textureName)
{
textureResource = effect.GetVariableByName(textureName).AsResource();
}
public void WriteTexture<T>(T[,] data) where T : IConvertible
{
int height = MathExtensions.PowerOfTwo(data.GetLength(0));
int width = MathExtensions.PowerOfTwo(data.GetLength(1));
if (!QueryLargeSize(width, height)) return;
if (texture == null || texture.Description.Width != width || texture.Description.Height != height)
{
RecreateTexture(width, height);
}
WriteToTexture<T>(texture, data, height, width);
}
public static void WriteToTexture<T>(D3D.Texture2D texture, T[,] data, int height, int width) where T : IConvertible
{
DataRectangle rect = null;
try
{
rect = texture.Map(0, D3D.MapMode.WriteDiscard, D3D.MapFlags.None);
}
catch (D3D.Direct3D10Exception)
{
rect = texture.Map(0, D3D.MapMode.Write, D3D.MapFlags.None);
}
using (DataStream stream = rect.Data)
{
for (int y = height - 1; y >= 0; y--)
for (int x = 0; x < width; x++)
{
if (y < data.GetLength(0) && x < data.GetLength(1))
stream.Write(Convert.ToSingle(data[y, x]));
else
stream.Write((float)0);
}
}
texture.Unmap(0);
}
public void RecreateTexture(D3D.Texture2DDescription tDesc)
{
DisposeUnmanaged();
texture = new D3D.Texture2D(device, tDesc);
if (tDesc.BindFlags == D3D.BindFlags.ShaderResource)
{
textureView = new D3D.ShaderResourceView(device, texture);
this.device.VertexShader.SetShaderResource(textureView, 0);
if (textureResource != null) textureResource.SetResource(textureView);
}
}
public void RecreateTexture(int width, int height)
{
if(texture == null)
RecreateTexture(CreateWritableTextureDescription(width, height, D3D.BindFlags.ShaderResource, SlimDX.DXGI.Format.R32_Float));
else
RecreateTexture(CreateWritableTextureDescription(width, height, Description.BindFlags, Description.Format));
}
public static Texture CreateStagingTexture(D3D.Device device, int width, int height, SlimDX.DXGI.Format PixelFormat)
{
Texture tex = new Texture(device);
var tDesc = CreateWritableTextureDescription(width, height, D3D.BindFlags.None, PixelFormat);
tDesc.Usage = D3D.ResourceUsage.Staging;
tDesc.Format = PixelFormat;
tDesc.CpuAccessFlags = D3D.CpuAccessFlags.Read | D3D.CpuAccessFlags.Write;
tDesc.Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm;
tDesc.BindFlags = D3D.BindFlags.None;
tex.RecreateTexture(tDesc);
return tex;
}
public static Texture CreateWritableTexture(D3D.Device device, int width, int height, D3D.BindFlags ShaderBinding, SlimDX.DXGI.Format PixelFormat)
{
Texture tex = new Texture(device);
var tDesc = CreateWritableTextureDescription(width, height, D3D.BindFlags.None, PixelFormat);
tDesc.Format = PixelFormat;
tDesc.BindFlags = ShaderBinding;
tex.RecreateTexture(tDesc);
return tex;
}
public static D3D.Texture2DDescription CreateWritableTextureDescription(int width, int height, D3D.BindFlags ShaderBinding, SlimDX.DXGI.Format PixelFormat)
{
D3D.Texture2DDescription tDesc = new D3D.Texture2DDescription()
{
ArraySize = 1,
BindFlags = ShaderBinding,
CpuAccessFlags = D3D.CpuAccessFlags.Write,
Format = PixelFormat,
Height = width,
Width = height,
MipLevels = 1,
OptionFlags = D3D.ResourceOptionFlags.None,
SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0),
Usage = D3D.ResourceUsage.Dynamic
};
return tDesc;
}
bool QueryLargeSize(int width, int height)
{
double sizeInMB = (width * height * 4) / 1024.0 / 1024.0;
if (sizeInMB >= 256)
{
System.Windows.Forms.MessageBox.Show("Image size of " + sizeInMB + " MB is crazy. Not updating.");
return false;
}
if (sizeInMB >= 64)
{
return System.Windows.Forms.MessageBox.Show("Image size of " + sizeInMB + " MB is really quite high. Continue?",
"Large File Texture", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes;
}
return true;
}
void DisposeManaged() { }
void DisposeUnmanaged()
{
if (texture != null) texture.Dispose(); texture = null;
if (textureView != null) textureView.Dispose(); textureView = null;
}
bool disposed = false;
protected override void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
DisposeManaged();
}
DisposeUnmanaged();
disposed = true;
}
base.Dispose(disposing);
}
}
}