1 /************************************************************************** 2 * 3 * Copyright 2010 Luca Barbieri 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27 #include <vector> 28 29 #include "d3d11blit.hlsl.ps.h" 30 #include "d3d11blit.hlsl.vs.h" 31 32 template<typename index_type = unsigned> 33 struct triangle_list_indices : public std::vector<index_type> 34 { 35 unsigned base; 36 bool flip; 37 38 triangle_list_indices() 39 : base(0), flip(false) 40 {} 41 42 void poly(unsigned a, unsigned b, unsigned c) 43 { 44 this->push_back(base + a); 45 this->push_back(base + (flip ? c : b)); 46 this->push_back(base + (flip ? b : c)); 47 } 48 49 void poly(unsigned a, unsigned b, unsigned c, unsigned d) 50 { 51 poly(a, b, c); 52 poly(a, c, d); 53 } 54 55 void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e) 56 { 57 poly(a, b, c, d); 58 poly(a, d, e); 59 } 60 61 void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) 62 { 63 poly(a, b, c, d, e); 64 poly(a, e, f); 65 } 66 67 void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f, unsigned g) 68 { 69 poly(a, b, c, d, e, f); 70 poly(a, f, g); 71 } 72 73 void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f, unsigned g, unsigned h) 74 { 75 poly(a, b, c, d, e, f, g); 76 poly(a, g, h); 77 } 78 }; 79 80 struct mesh 81 { 82 ID3D11InputLayout* layout; 83 ID3D11Buffer* buffer; 84 D3D11_PRIMITIVE_TOPOLOGY topology; 85 unsigned vertex_size; 86 unsigned draw_count; 87 DXGI_FORMAT index_format; 88 unsigned index_offset; 89 90 mesh(ID3D11Device* dev, D3D11_PRIMITIVE_TOPOLOGY topology, 91 const D3D11_INPUT_ELEMENT_DESC *elements, unsigned num_elements, 92 const void* vs, unsigned vs_size, 93 const void* vertices, unsigned vertex_size, unsigned num_vertices, 94 const void* indices = 0, unsigned index_size = 0, unsigned num_indices = 0) 95 : topology(topology), vertex_size(vertex_size), draw_count(index_size ? num_indices : num_vertices) 96 { 97 dev->CreateInputLayout(elements, num_elements, vs, vs_size, &layout); 98 if(index_size == 2) 99 index_format = DXGI_FORMAT_R16_UINT; 100 else if(index_size == 4) 101 index_format = DXGI_FORMAT_R32_UINT; 102 else 103 index_format = DXGI_FORMAT_UNKNOWN; 104 this->vertex_size = vertex_size; 105 index_offset = vertex_size * num_vertices; 106 107 D3D11_BUFFER_DESC bufferd; 108 memset(&bufferd, 0, sizeof(bufferd)); 109 bufferd.Usage = D3D11_USAGE_IMMUTABLE; 110 bufferd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 111 if(index_format) 112 bufferd.BindFlags |= D3D11_BIND_INDEX_BUFFER; 113 bufferd.ByteWidth = index_offset + index_format * num_indices; 114 115 char* data = (char*)malloc(bufferd.ByteWidth); 116 memcpy(data, vertices, vertex_size * num_vertices); 117 memcpy(data + index_offset, indices, index_size * num_indices); 118 119 D3D11_SUBRESOURCE_DATA buffersd; 120 buffersd.pSysMem = data; 121 122 ensure(dev->CreateBuffer(&bufferd, &buffersd, &buffer)); 123 free(data); 124 } 125 126 ~mesh() 127 { 128 layout->Release(); 129 buffer->Release(); 130 } 131 132 void bind(ID3D11DeviceContext* ctx) 133 { 134 unsigned offset = 0; 135 ctx->IASetPrimitiveTopology(topology); 136 ctx->IASetInputLayout(layout); 137 if(index_format) 138 ctx->IASetIndexBuffer(buffer, index_format, index_offset); 139 ctx->IASetVertexBuffers(0, 1, &buffer, &vertex_size, &offset); 140 } 141 142 void draw_bound(ID3D11DeviceContext* ctx) 143 { 144 if(index_format) 145 ctx->DrawIndexed(draw_count, 0, 0); 146 else 147 ctx->Draw(draw_count, 0); 148 } 149 150 void bind_and_draw(ID3D11DeviceContext* ctx) 151 { 152 bind(ctx); 153 draw_bound(ctx); 154 } 155 }; 156 157 mesh* create_tex_quad(ID3D11Device* dev, const BYTE* vs, unsigned vs_size) 158 { 159 float quad_data[] = { 160 -1, -1, 0, 1, 161 -1, 1, 0, 0, 162 1, -1, 1, 1, 163 1, 1, 1, 0, 164 }; 165 166 D3D11_INPUT_ELEMENT_DESC elements[2] = 167 { 168 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, 169 {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, 170 }; 171 172 return new mesh(dev, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, 173 elements, 2, 174 vs, vs_size, 175 quad_data, 4 * sizeof(float), 4, 176 0, 0, 0); 177 } 178 179 struct d3d11_blitter 180 { 181 mesh* quad; 182 ID3D11VertexShader* vs; 183 ID3D11PixelShader* ps; 184 ID3D11SamplerState* sampler[2]; 185 186 d3d11_blitter(ID3D11Device* dev) 187 { 188 quad = create_tex_quad(dev, g_vs_blit, sizeof(g_vs_blit)); 189 190 dev->CreateVertexShader(g_vs_blit, sizeof(g_vs_blit), 0, &vs); 191 dev->CreatePixelShader(g_ps_blit, sizeof(g_ps_blit), 0, &ps); 192 193 for(unsigned i = 0; i < 2; ++i) 194 { 195 D3D11_SAMPLER_DESC samplerd; 196 memset(&samplerd, 0, sizeof(samplerd)); 197 samplerd.Filter = i ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_LINEAR; 198 samplerd.AddressU = samplerd.AddressV = samplerd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; 199 dev->CreateSamplerState(&samplerd, &sampler[i]); 200 } 201 } 202 203 void bind(ID3D11DeviceContext* ctx, ID3D11ShaderResourceView* srv, ID3D11RenderTargetView* rtv, float x, float y, float width, float height, bool linear) 204 { 205 D3D11_VIEWPORT vp; 206 vp.TopLeftX = x; 207 vp.TopLeftY = y; 208 vp.Width = width; 209 vp.Height = height; 210 vp.MinDepth = 0; 211 vp.MaxDepth = 1; 212 ctx->RSSetViewports(1, &vp); 213 ctx->RSSetState(0); 214 ctx->OMSetBlendState(0, 0, ~0); 215 ctx->OMSetDepthStencilState(0, 0); 216 ctx->OMSetRenderTargets(1, &rtv, 0); 217 ctx->VSSetShader(vs, 0, 0); 218 ctx->PSSetShader(ps, 0, 0); 219 ctx->PSSetShaderResources(0, 1, &srv); 220 ctx->PSSetSamplers(0, 1, &sampler[!!linear]); 221 quad->bind(ctx); 222 } 223 224 void draw_bound(ID3D11DeviceContext* ctx) 225 { 226 quad->draw_bound(ctx); 227 } 228 229 void bind_draw_and_unbind(ID3D11DeviceContext* ctx, ID3D11ShaderResourceView* srv, ID3D11RenderTargetView* rtv, float x, float y, float width, float height, bool linear) 230 { 231 bind(ctx, srv, rtv, x, y, width, height, linear); 232 draw_bound(ctx); 233 unbind(ctx); 234 } 235 236 void unbind(ID3D11DeviceContext* ctx) 237 { 238 void* null = 0; 239 ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&null); 240 ctx->PSSetSamplers(0, 1, (ID3D11SamplerState**)&null); 241 } 242 }; 243 244 template<typename T, unsigned n> 245 struct vec_t 246 { 247 T v[n]; 248 249 T& operator [](unsigned i) 250 { 251 return v[i]; 252 } 253 254 const T& operator [](unsigned i) const 255 { 256 return v[i]; 257 } 258 }; 259 260 template<typename T, unsigned n> 261 vec_t<T, n> operator -(const vec_t<T, n> a) 262 { 263 vec_t<T, n> r; 264 for(unsigned i = 0; i < n; ++i) 265 r[i] = -a[i]; 266 return r; 267 } 268 269 template<typename T, unsigned n> 270 vec_t<T, n> operator +(const vec_t<T, n>& a, const vec_t<T, n>& b) 271 { 272 vec_t<T, n> r; 273 for(unsigned i = 0; i < n; ++i) 274 r[i] = a[i] + b[i]; 275 return r; 276 } 277 278 template<typename T, unsigned n> 279 vec_t<T, n>& operator +=(vec_t<T, n>& a, const vec_t<T, n>& b) 280 { 281 for(unsigned i = 0; i < n; ++i) 282 a[i] += b[i]; 283 return a; 284 } 285 286 template<typename T, unsigned r, unsigned c> 287 struct mat_t : public vec_t<vec_t<T, r>, c> 288 {}; 289 290 template<typename T, unsigned n> 291 vec_t<T, n> operator *(const vec_t<T, n>& a, const T& b) 292 { 293 vec_t<T, n> r; 294 for(unsigned i = 0; i < n; ++i) 295 r[i] = a[i] * b; 296 return r; 297 } 298 299 template<typename T, unsigned n> 300 vec_t<T, n> operator *(const T& b, const vec_t<T, n>& a) 301 { 302 vec_t<T, n> r; 303 for(unsigned i = 0; i < n; ++i) 304 r[i] = a[i] * b; 305 return r; 306 } 307 308 template<typename T, unsigned d, unsigned e> 309 vec_t<T, e> operator *(const mat_t<T, e, d>& m, const vec_t<T, d>& b) 310 { 311 vec_t<T, e> r; 312 r = m[0] * b[0]; 313 for(unsigned i = 1; i < d; ++i) 314 r += m[i] * b[i]; 315 return r; 316 } 317 318 template<typename T, unsigned d, unsigned e, unsigned f> 319 mat_t<T, e, f> operator *(const mat_t<T, e, d>& m, const mat_t<T, d, f>& b) 320 { 321 mat_t<T, e, f> r; 322 for(unsigned i = 0; i < d; ++i) 323 r[i] = m * b[i]; 324 return r; 325 } 326 327 template<typename T> 328 vec_t<T, 3> vec(T a, T b, T c) 329 { 330 vec_t<T, 4> v; 331 v[0] = a; 332 v[1] = b; 333 v[2] = c; 334 return v; 335 } 336 337 template<typename T> 338 vec_t<T, 4> vec(T a, T b, T c, T d) 339 { 340 vec_t<T, 4> v; 341 v[0] = a; 342 v[1] = b; 343 v[2] = c; 344 v[3] = d; 345 return v; 346 } 347 348 typedef mat_t<float, 4, 4> float4x4; 349 typedef mat_t<float, 4, 3> float4x3; 350 typedef mat_t<float, 3, 4> float3x4; 351 typedef mat_t<float, 3, 3> float3x3; 352 353 typedef vec_t<float, 3> float3; 354 typedef vec_t<float, 4> float4; 355 356 template<typename T> 357 mat_t<T, 4, 4> mat4x4_frustum(T left, T right, T bottom, T top, T nearval, T farval) 358 { 359 T x = (2.0f * nearval) / (right - left); 360 T y = (2.0f * nearval) / (top - bottom); 361 T a = (right + left) / (right - left); 362 T b = (top + bottom) / (top - bottom); 363 T c = -(farval + nearval) / (farval - nearval); 364 T d = -(2.0f * farval * nearval) / (farval - nearval); 365 T _0 = (T)0; 366 367 mat_t<T, 4, 4> m; 368 m[0] = vec(x, _0, _0, _0); 369 m[1] = vec(_0, y, _0, _0); 370 m[2] = vec(a, b, c, (T)-1); 371 m[3] = vec(_0, _0, d, _0); 372 return m; 373 } 374 375 template<typename T> 376 mat_t<T, 3, 3> mat3x3_diag(T v) 377 { 378 mat_t<T, 3, 3> m; 379 T _0 = (T)0; 380 m[0] = vec(v, _0, _0); 381 m[1] = vec(_0, v, _0); 382 m[2] = vec(_0, _0, v); 383 return m; 384 } 385 386 template<typename T> 387 mat_t<T, 4, 4> mat4x4_diag(T v) 388 { 389 mat_t<T, 4, 4> m; 390 T _0 = (T)0; 391 m[0] = vec(v, _0, _0, _0); 392 m[1] = vec(_0, v, _0, _0); 393 m[2] = vec(_0, _0, v, _0); 394 m[3] = vec(_0, _0, _0, v); 395 return m; 396 } 397 398 template<typename T, unsigned n> 399 mat_t<T, n, n> mat_push_rotate(const mat_t<T, n, n>& m, unsigned axis, T angle) 400 { 401 T s = (T)sin(angle); 402 T c = (T)cos(angle); 403 404 mat_t<T, n, n> r = m; 405 unsigned a = (axis + 1) % 3; 406 unsigned b = (axis + 2) % 3; 407 r[a] = (m[a] * c) + (m[b] * s); 408 r[b] = -(m[a] * s) + (m[b] * c); 409 return r; 410 } 411 412 template<typename T, unsigned n> 413 mat_t<T, n, n> mat_push_translate(const mat_t<T, n, n>& m, float x, float y, float z) 414 { 415 mat_t<T, n, n> r = m; 416 vec_t<T, n> v; 417 v[0] = x; 418 v[1] = y; 419 v[2] = z; 420 if(n >= 4) 421 v[3] = (T)0; 422 r[3] += m * v; 423 return r; 424 } 425