1 module evael.graphics.GraphicsDevice; 2 3 debug 4 { 5 import std.stdio; 6 import std.format; 7 } 8 9 public import evael.graphics.GL; 10 public import derelict.nanovg.nanovg; 11 12 import evael.graphics.GL; 13 import evael.graphics.shaders.Shader; 14 import evael.graphics.shaders.BasicShader; 15 import evael.graphics.shaders.BasicLightShader; 16 import evael.graphics.Drawable; 17 import evael.graphics.Vertex; 18 import evael.graphics.Texture; 19 import evael.graphics.FrameBuffer; 20 import evael.graphics.Font; 21 import evael.graphics.lights; 22 import evael.graphics.shapes; 23 import evael.graphics.Environment; 24 25 import evael.system.AssetLoader; 26 27 import evael.utils.Singleton; 28 import evael.utils.Math; 29 import evael.utils.Size; 30 import evael.utils.Color; 31 32 import dnogc.DynamicArray; 33 34 /** 35 * GraphicsDevice 36 */ 37 class GraphicsDevice 38 { 39 mixin Singleton!(); 40 41 /// Asset loader 42 private AssetLoader m_assetLoader; 43 44 /// Nanovg context 45 private NVGcontext* m_nvg; 46 47 private Size!int m_viewportSize; 48 49 /// Game resolution 50 private Size!int m_resolution; 51 52 /// Matrixes 53 private mat4 m_viewMatrix, m_projectionMatrix; 54 private mat4 m_2DprojectionMatrix; 55 56 /// Current enabled shader 57 private Shader m_currentShader; 58 59 private Shader m_2dShader; 60 61 /// Vertices display mode 62 private PolygonMode m_polygonMode; 63 64 /// Projection type 65 private ProjectionType m_projectionType; 66 67 /// List of VAOs 68 private DynamicArray!uint m_vaos; 69 70 /// List of generated buffers 71 private DynamicArray!uint m_buffers; 72 73 private DynamicArray!FrameBuffer m_frameBuffers; 74 75 /// Default font 76 private Font m_defaultFont; 77 78 /// Environment 79 private Environment m_environment; 80 81 private Circle m_circle; 82 83 /// Shapes vao (lines, circles) 84 private uint m_shapesVAO; 85 private uint m_shapesVBO; 86 87 /** 88 * GraphicsDevice constructor. 89 */ 90 private this() 91 { 92 this.m_nvg = nvgCreateGL3(NVGcreateFlags.NVG_STENCIL_STROKES | NVGcreateFlags.NVG_DEBUG); 93 94 this.m_assetLoader = AssetLoader.getInstance(); 95 96 this.m_polygonMode = PolygonMode.Fill; 97 this.resolution = Size!int(1024, 768); 98 99 this.initializeOpenGL(); 100 this.initialize2DProjection(this.m_viewportSize); 101 this.initializePerspectiveProjection(60.0f); 102 103 this.m_environment = new Environment(this); 104 105 this.m_circle = new Circle(this, 16, 1); 106 this.m_circle.shader = this.m_assetLoader.load!(BasicLightShader)("colored_primitive"); 107 this.m_circle.initialize(); 108 109 this.m_shapesVAO = this.generateVAO(); 110 this.m_shapesVBO = this.createVertexBuffer(VertexPositionColor!3.sizeof * 2, null); 111 this.setVertexBuffer!(VertexPositionColor!3)(this.m_shapesVBO); 112 113 this.bindVAO(0); 114 } 115 116 /** 117 * GraphicsDevice destructor. 118 */ 119 public void dispose() 120 { 121 foreach(id; this.m_buffers) 122 { 123 gl.DeleteBuffers(1, &id); 124 } 125 126 foreach(fb; this.m_frameBuffers) 127 { 128 fb.dispose(); 129 } 130 131 foreach(vao; this.m_vaos) 132 { 133 gl.DeleteVertexArrays(1, &vao); 134 } 135 136 this.m_buffers.dispose(); 137 this.m_frameBuffers.dispose(); 138 this.m_vaos.dispose(); 139 140 nvgDeleteGL3(this.m_nvg); 141 } 142 143 /** 144 * Initializes Opengl. 145 */ 146 @nogc 147 private void initializeOpenGL() const nothrow 148 { 149 gl.ClearDepth(1.0f); 150 151 gl.Enable(GL_BLEND); 152 gl.Enable(GL_DEPTH_TEST); 153 gl.Enable(GL_MULTISAMPLE); 154 155 gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 156 } 157 158 /** 159 * Initializes a perspective projection. 160 * Params: 161 * fov: 162 * nearPlane: 163 * farPlane: 164 */ 165 public void initializePerspectiveProjection(in float fov, in float nearPlane = 0.1f, in float farPlane = 2000.0f) 166 { 167 this.m_projectionType = ProjectionType.Perspective; 168 this.m_projectionMatrix = perspectiveMatrix(cast(float)fov, this.m_viewportSize.width / this.m_viewportSize.height, nearPlane, farPlane); 169 } 170 171 /** 172 * Initializes an orthographic projection. 173 * Params: 174 */ 175 public void initializeOrthographicProjection( 176 in float left, in float right, in float bottom, in float top, in float near = -2000.0f, in float far = 2000.0f 177 ) 178 { 179 this.m_projectionType = ProjectionType.Orthographic; 180 this.m_projectionMatrix = orthoMatrix( 181 cast(float)left, cast(float)right, cast(float)bottom, cast(float)top, 182 cast(float)near, cast(float)far 183 ); 184 } 185 186 /** 187 * Begin drawing. 188 * Params: 189 * color : clear color 190 */ 191 @nogc 192 public void beginScene(in Color color = Color.Black) const nothrow 193 { 194 gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 195 196 auto colorf = color.asFloat(); 197 gl.ClearColor(colorf[0], colorf[1], colorf[2], 1.0f); 198 } 199 200 201 /** 202 * Renders a circle. 203 */ 204 public void drawCircle()(in float deltaTime, in auto ref vec3 position, in uint radius) 205 { 206 this.m_circle.position = position; 207 this.m_circle.scale = radius; 208 this.m_circle.draw(deltaTime); 209 } 210 211 /** 212 * Renders a line. 213 */ 214 public void drawLine()(in auto ref vec3 a, in auto ref vec3 b) 215 { 216 this.bindTexture(0); 217 auto shader = this.m_assetLoader.load!(BasicLightShader)("colored_primitive"); 218 219 this.enableShader(shader); 220 221 auto vertices = 222 [ 223 VertexPositionColor!3(a, Color.Red), 224 VertexPositionColor!3(b, Color.Red), 225 ]; 226 227 this.sendVertexBufferData(this.m_shapesVBO, 0, VertexPositionColor!3.sizeof * vertices.length, vertices.ptr); 228 229 this.setMatrix(shader.modelMatrix, mat4.identity.arrayof.ptr); 230 this.setMatrix(shader.viewMatrix, this.m_viewMatrix.arrayof.ptr); 231 this.setProjectionMatrix(); 232 233 this.bindVAO(this.m_shapesVAO); 234 235 this.drawPrimitives!(PrimitiveType.Lines)(1); 236 237 this.bindVAO(0); 238 239 this.disableShader(); 240 } 241 242 /** 243 * Renders primitives. 244 * Params: http://www.opengl.org/sdk/docs/man/html/glDrawArrays.xhtml 245 */ 246 @nogc 247 public void drawPrimitives(PrimitiveType type)(in int count, in int first = 0) const nothrow 248 { 249 static if(type == PrimitiveType.Triangle) 250 { 251 gl.DrawArrays(type, first, count * 3); 252 } 253 else if(type == PrimitiveType.Lines) 254 { 255 gl.DrawArrays(type, first, count * 2); 256 } 257 else gl.DrawArrays(type, first, count); 258 } 259 260 /** 261 * Renders indexed primitives. 262 * Params: https://www.opengl.org/sdk/docs/man/html/glDrawElements.xhtml 263 */ 264 @nogc 265 public void drawIndexedPrimitives(PrimitiveType type)(in int count, in void* offset) const nothrow 266 { 267 static if(type == PrimitiveType.Triangle) 268 { 269 gl.DrawElements(type, count * 3, GL_UNSIGNED_INT, offset); 270 } 271 else gl.DrawElements(type, count, GL_UNSIGNED_INT, offset); 272 } 273 274 @nogc 275 public void drawIndexedPrimitives(PrimitiveType type)(in int count, in int offset = 0) const nothrow 276 { 277 this.drawIndexedPrimitives!(type)(count, cast(void*)offset); 278 } 279 280 /** 281 * Generates a vertex array object. 282 */ 283 @nogc 284 public uint generateVAO() nothrow 285 { 286 uint id; 287 gl.GenVertexArrays(1, &id); 288 gl.BindVertexArray(id); 289 290 this.m_vaos ~= id; 291 292 return id; 293 } 294 295 /** 296 * Generates a buffer object. 297 * Params: 298 * type : buffer object type 299 */ 300 @nogc 301 public uint generateBuffer(BufferType type) nothrow 302 { 303 uint id; 304 gl.GenBuffers(1, &id); 305 gl.BindBuffer(type, id); 306 307 this.m_buffers ~= id; 308 309 return id; 310 } 311 312 /** 313 * Generates multiple vertex buffer objects. 314 * Params: 315 * type : buffer object type 316 * count : count 317 * Todo: nogc 318 */ 319 /*@nogc*/ 320 public uint[] generateBuffers(BufferType type, in int count) nothrow 321 { 322 uint[] ids = new uint[count]; 323 gl.GenBuffers(count, ids.ptr); 324 325 foreach (id; ids) 326 { 327 this.m_buffers ~= id; 328 } 329 330 return ids; 331 } 332 333 /** 334 * Generates a buffer object and send data. 335 * Params: 336 * type : buffer object type 337 * size : buffer object size 338 * data : data to send 339 * usage : usage type 340 */ 341 @nogc 342 public uint createBuffer(BufferType type, in int size, in void* data, BufferUsage usage = BufferUsage.StaticDraw) nothrow 343 { 344 immutable uint id = this.generateBuffer(type); 345 346 gl.BufferData(type, size, data, usage); 347 348 return id; 349 } 350 351 /** 352 * Creates a frame buffet object. 353 * Params: 354 * width : 355 * height : 356 */ 357 public T createFrameBuffer(T)(in int width, in int height) nothrow 358 { 359 auto frameBuffer = new T(this, width, height); 360 361 this.m_frameBuffers ~= frameBuffer; 362 363 gl.BindFramebuffer(GL_FRAMEBUFFER, 0); 364 365 return frameBuffer; 366 } 367 368 /** 369 * Creates a vertex buffer object. 370 * Params: 371 * size : buffer object size 372 * data : data to send 373 * usage : usage type 374 */ 375 @nogc 376 public uint createVertexBuffer(in int size, in void* data, BufferUsage usage = BufferUsage.StaticDraw) nothrow 377 { 378 return this.createBuffer(BufferType.VertexBuffer, size, data, usage); 379 } 380 381 /** 382 * Creates an index buffer object. 383 * Params: 384 * size : buffer object size 385 * data : data to send 386 */ 387 @nogc 388 public uint createIndexBuffer(in int size, in void* data) nothrow 389 { 390 return this.createBuffer(BufferType.IndexBuffer, size, data); 391 } 392 393 /** 394 * Deletes a buffer object. 395 * Params: 396 * id : buffer id 397 */ 398 public void deleteBuffer(in uint id) 399 { 400 gl.DeleteBuffers(1, &id); 401 402 foreach (i, bufferId; this.m_buffers) 403 { 404 if(bufferId == id) 405 { 406 this.m_buffers.remove(i); 407 break; 408 } 409 } 410 } 411 412 /** 413 * Allocates and sends data to a vertex buffer object. 414 * Params: 415 * vbo : vertex buffer object 416 * data : data to send 417 */ 418 @nogc 419 public uint allocVertexBufferData(in uint id, in int size, in void* data, BufferUsage usage = BufferUsage.StaticDraw) const nothrow 420 { 421 this.bindVertexBuffer(id); 422 gl.BufferData(BufferType.VertexBuffer, size, data, usage); 423 424 return size; 425 } 426 427 428 /** 429 * Sends data to vertex buffer object. 430 * Params: 431 * vbo : vertex buffer object 432 * data : data to send 433 */ 434 @nogc 435 public uint sendVertexBufferData(in uint id, in uint offset, in uint size, in void* data) const nothrow 436 { 437 this.bindVertexBuffer(id); 438 gl.BufferSubData(BufferType.VertexBuffer, offset, size, data); 439 440 return offset + size; 441 } 442 443 /** 444 * Binds a vertex buffer object for the next drawing operation. 445 * Params: 446 * vbo : vertex buffer object to bind 447 */ 448 @nogc 449 public void setVertexBuffer(T, int line = __LINE__, string file = __FILE__)(in uint id) const nothrow 450 { 451 this.bindVertexBuffer(id); 452 453 enum size = mixin(T.stringof ~ ".sizeof"); 454 455 T* nullStruct = null; 456 457 foreach (i, member; __traits(allMembers, T)) 458 { 459 static if (member == "opAssign") 460 { 461 continue; 462 } 463 else 464 { 465 enum UDAs = __traits(getAttributes, mixin(T.stringof ~ "." ~ member)); 466 467 static assert(UDAs.length > 0, "You need to specify UDA for member " ~ T.stringof ~ "." ~ member); 468 469 enum shaderAttribute = UDAs[0]; 470 471 static if(is(typeof(shaderAttribute) : ShaderAttribute)) 472 { 473 void* offset = i == 0 ? null : mixin("&nullStruct." ~ member); 474 475 gl.EnableVertexAttribArray(shaderAttribute.layoutIndex); 476 gl.VertexAttribPointer( 477 shaderAttribute.layoutIndex, 478 shaderAttribute.size, 479 shaderAttribute.type, 480 shaderAttribute.normalized, 481 size, offset 482 ); 483 484 version(GLDebug) 485 { 486 pragma(msg, "%s:%d : gl.VertexAttribPointer(%d, %d, %d, %d, %d, %d);".format(file, line, shaderAttribute.layoutIndex, 487 shaderAttribute.size, 488 shaderAttribute.type, 489 shaderAttribute.normalized, 490 size, 0 491 )); 492 } 493 } 494 else 495 { 496 static assert(false, "UDA defined member " ~ T.stringof ~ "." ~ member ~ " but is not of the good type."); 497 } 498 } 499 } 500 } 501 502 /** 503 * Binds a vertex array object. 504 * Params: 505 * id : id 506 */ 507 @nogc 508 public void bindVAO(in uint id) const nothrow 509 { 510 gl.BindVertexArray(id); 511 } 512 513 /** 514 * Binds a vertex buffer object. 515 * Params: 516 * id : id 517 */ 518 @nogc 519 public void bindVertexBuffer(in uint id) const nothrow 520 { 521 gl.BindBuffer(BufferType.VertexBuffer, id); 522 } 523 524 /** 525 * Binds an index array object. 526 * Params: 527 * id : id 528 */ 529 @nogc 530 public void bindIndexBuffer(in uint id) const nothrow 531 { 532 gl.BindBuffer(BufferType.IndexBuffer, id); 533 } 534 535 /** 536 * Binds a frame buffer. 537 * Params: 538 * id : id 539 */ 540 @nogc 541 public void bindFrameBuffer(in uint id) const nothrow 542 { 543 gl.BindFramebuffer(GL_FRAMEBUFFER, id); 544 } 545 546 /** 547 * Binds a vertex array object. 548 * Params: 549 * id : id 550 */ 551 @nogc 552 public void bindFrameBuffer(FrameBuffer frameBuffer) const nothrow 553 { 554 gl.BindFramebuffer(GL_FRAMEBUFFER, frameBuffer.id); 555 } 556 557 /** 558 * Enables a shader for the next drawing operation. 559 * Params: 560 * shader : shader to enable 561 */ 562 @nogc 563 public void enableShader(Shader shader) nothrow 564 { 565 gl.UseProgram(shader.programID); 566 this.m_currentShader = shader; 567 } 568 569 /** 570 * Disables last used shader. 571 */ 572 @nogc 573 public void disableShader() const nothrow 574 { 575 gl.UseProgram(0); 576 } 577 578 /** 579 * Sets environment for the next render (lights, fog...). 580 */ 581 @nogc 582 public void setEnvironment() nothrow 583 { 584 this.m_environment.set(); 585 } 586 587 /** 588 * Binds a texture. 589 * Params: 590 * texture : texture to bind 591 * target : texture type 592 */ 593 @nogc 594 public void bindTexture(Texture texture, TextureTarget target = TextureTarget.Texture2D) const nothrow 595 { 596 assert(texture !is null); 597 gl.BindTexture(target, texture.id); 598 } 599 600 /** 601 * Binds a texture. 602 * Params: 603 * textureId : texture to bind 604 * target : texture type 605 */ 606 @nogc 607 public void bindTexture(in uint textureId, TextureTarget target = TextureTarget.Texture2D) const nothrow 608 { 609 gl.BindTexture(target, textureId); 610 } 611 612 /** 613 * Unbinds last used texture. 614 * Params: 615 * target : texture type 616 */ 617 @nogc 618 public void clearTexture(TextureTarget target = TextureTarget.Texture2D) const nothrow 619 { 620 gl.BindTexture(target, 0); 621 } 622 623 /** 624 * Enables GL capability. 625 */ 626 @nogc 627 public void enable(in uint target) const nothrow 628 { 629 gl.Enable(target); 630 } 631 632 /** 633 * Disables GL capability. 634 */ 635 @nogc 636 public void disable(in uint target) const nothrow 637 { 638 gl.Disable(target); 639 } 640 641 /** 642 * Switch display mode of vertices. 643 */ 644 @nogc 645 public void switchPolygonMode() nothrow 646 { 647 final switch(this.m_polygonMode) 648 { 649 case PolygonMode.Fill: 650 this.m_polygonMode = PolygonMode.Line; 651 break; 652 case PolygonMode.Line: 653 this.m_polygonMode = PolygonMode.Point; 654 break; 655 case PolygonMode.Point: 656 this.m_polygonMode = PolygonMode.Fill; 657 break; 658 } 659 660 gl.PolygonMode(GL_FRONT_AND_BACK, this.m_polygonMode); 661 } 662 663 /** 664 * Converts screen coordinates to world coordinates. 665 * Params: 666 * mousePosition : mouse position 667 */ 668 @nogc 669 public vec3 getWorldCoordinates(in ref vec2 mousePosition) nothrow 670 { 671 immutable mouseY = this.m_resolution.height - mousePosition.y; 672 673 float z; 674 gl.ReadPixels(cast(int)mousePosition.x, cast(int)mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); 675 mat4 A = this.m_projectionMatrix * this.viewMatrix; 676 A.invert(); 677 vec4 i; 678 679 /* Map x and y from window coordinates */ 680 i.x = mousePosition.x; 681 i.y = mouseY; 682 i.z = z; 683 i.w = 1.0f; 684 685 i.x = i.x / this.m_viewportSize.width; 686 i.y = i.y / this.m_viewportSize.height; 687 688 /* Map to range -1 to 1 */ 689 i.x = i.x * 2 - 1; 690 i.y = i.y * 2 - 1; 691 i.z = i.z * 2 - 1; 692 693 vec4 o = i * A; 694 695 o.x = o.x / o.w; 696 o.y = o.y / o.w; 697 o.z = o.z / o.w; 698 699 return vec3(o.x, o.y, o.z); 700 } 701 702 /** 703 * Converts world coordinates to screen coordinates. 704 * Params: 705 * mousePosition : mouse position 706 * Credits: http://stackoverflow.com/questions/7748357/converting-3d-position-to-2d-screen-position 707 */ 708 @nogc 709 public vec2 getScreenCoordinates(in ref vec3 position) nothrow 710 { 711 auto pos = position * this.m_viewMatrix; 712 pos = pos * this.m_projectionMatrix; 713 714 pos.x = this.m_viewportSize.width * (pos.x + 1.0) / 2.0; 715 pos.y = this.m_viewportSize.height * (1.0 - ( (pos.y + 1.0) / 2.0) ); 716 717 return vec2(pos.x, pos.y); 718 } 719 720 /** 721 * Renders text using default font. 722 * Params : 723 * text : text to draw 724 * x : 725 * y : 726 */ 727 public void drawText()(in wstring text, in float x, in float y, in auto ref color = Color.Black) 728 { 729 this.m_defaultFont.draw(text, x , y, color, 20); 730 } 731 732 /** 733 * Sends values to current shader. 734 * Params: 735 T : gl uniform name 736 U : values types 737 data : values 738 */ 739 public void setUniform(string T, U)(in int uniformLocation, in U* data, in size_t count, bool normalized = false) const 740 { 741 mixin("gl.Uniform" ~ T ~ "(uniformLocation, count, normalized, data);"); 742 } 743 744 public void setUniform(string T, U)(in int uniformLocation, in U* data, in size_t count = 1) const 745 { 746 mixin("gl.Uniform" ~ T ~ "(uniformLocation, count, data);"); 747 } 748 749 public void setUniform(string T, U)(in int uniformLocation, in U data) const 750 { 751 mixin("gl.Uniform" ~ T ~ "(uniformLocation, data);"); 752 } 753 754 @nogc 755 public void setMatrix(U)(in int location, in U* data, in size_t count = 1, in bool transposed = false) const nothrow 756 { 757 gl.UniformMatrix4fv(location, count, transposed, data); 758 } 759 760 /** 761 * Sets default projection matrix. 762 */ 763 @nogc 764 public void setProjectionMatrix() nothrow 765 { 766 assert(this.m_currentShader !is null, "Trying to set projection matrix on null shader."); 767 this.setMatrix(this.m_currentShader.projectionMatrix, this.m_projectionMatrix.arrayof.ptr, 1, false); 768 } 769 770 /** 771 * Sets viewport. 772 * Params: 773 * width : viewport width 774 * height : viewport height 775 */ 776 @nogc 777 public void setViewport(in int width, in int height) const nothrow 778 { 779 gl.Viewport(0, 0, width, height); 780 } 781 782 /** 783 * Sets viewport. 784 * Params: 785 * size : viewport size 786 */ 787 @nogc 788 public void setViewport(in ref Size!int size) const nothrow 789 { 790 gl.Viewport(0, 0, size.width, size.height); 791 } 792 793 /** 794 * Sets viewport. 795 * Params: 796 * position : viewport position 797 * size : viewport size 798 */ 799 @nogc 800 public void setViewport(V)(in ref V position, in ref Size!int size) const nothrow 801 if(is(V : vec2) || is(V : ivec2)) 802 { 803 gl.Viewport(position.x, position.y, size.width, size.height); 804 } 805 806 /** 807 * Resets viewport to its initial size. 808 */ 809 @nogc 810 public void resetViewport() const nothrow 811 { 812 this.setViewport(this.m_viewportSize); 813 } 814 815 @nogc 816 public void initialize2DProjection(T)(in ref T viewportSize) nothrow 817 { 818 this.m_2DprojectionMatrix = orthoMatrix( 819 cast(float)0, cast(float)viewportSize.width, cast(float)0, cast(float)viewportSize.height, cast(float)-5,cast(float) 5 820 ); 821 } 822 823 @nogc 824 public void initialize2DProjection(V, S)(in ref V position, in ref S viewportSize) nothrow 825 if(is(V : vec2) || is(V : ivec2) && is(S : Size!int) || is(S : Size!float)) 826 { 827 this.m_2DprojectionMatrix = orthoMatrix(position.x, viewportSize.width, position.y, viewportSize.height, -5, 5); 828 } 829 830 /** 831 * Resets 2d projection (GUI) to the default value. 832 */ 833 @nogc 834 public void reset2DProjection() nothrow 835 { 836 this.initialize2DProjection(this.m_viewportSize); 837 } 838 839 /** 840 * Properties 841 */ 842 @nogc 843 @property nothrow 844 { 845 public NVGcontext* nvgContext() 846 { 847 return this.m_nvg; 848 } 849 850 public mat4 viewMatrix() const 851 { 852 return this.m_viewMatrix; 853 } 854 855 public void viewMatrix(mat4 value) 856 { 857 this.m_viewMatrix = value; 858 } 859 860 public mat4 projectionMatrix() const 861 { 862 return this.m_projectionMatrix; 863 } 864 865 public mat4 GUIprojectionMatrix() const 866 { 867 return this.m_2DprojectionMatrix; 868 } 869 870 public void projectionType(ProjectionType value) 871 { 872 this.m_projectionType = value; 873 } 874 875 public ref const(Size!int) viewportSize() const 876 { 877 return this.m_viewportSize; 878 } 879 880 881 public Font defaultFont() 882 { 883 return this.m_defaultFont; 884 } 885 886 public void defaultFont(Font value) 887 { 888 this.m_defaultFont = value; 889 } 890 891 public ref const(Size!int) resolution() const 892 { 893 return this.m_resolution; 894 } 895 896 public void resolution(in Size!int value) 897 { 898 this.m_resolution = value; 899 this.m_viewportSize = value; 900 901 this.setViewport(value); 902 } 903 904 public Environment environment() 905 { 906 return this.m_environment; 907 } 908 909 public Shader currentShader() 910 { 911 return this.m_currentShader; 912 } 913 } 914 915 }