renderCore.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2017 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_RENDER_MODEL_RENDERCORE
  24. #define DFPSR_RENDER_MODEL_RENDERCORE
  25. #include <stdint.h>
  26. #include "Camera.h"
  27. #include "shader/Shader.h"
  28. #include "../image/ImageRgbaU8.h"
  29. #include "../image/ImageF32.h"
  30. #include "../base/threading.h"
  31. #include "../collection/List.h"
  32. namespace dsr {
  33. struct TriangleDrawData {
  34. // Color target
  35. ImageRgbaU8Impl *targetImage;
  36. // Depth target
  37. ImageF32Impl *depthBuffer;
  38. // When perspective is used, the depth buffer stores 1 / depth instead of linear depth.
  39. bool perspective;
  40. // The target blending method
  41. Filter filter;
  42. // Unprocessed triangle data in the standard layout
  43. TriangleInput triangleInput;
  44. // Function pointer to the method that will process the command
  45. DRAW_CALLBACK_TYPE processTriangle;
  46. TriangleDrawData(ImageRgbaU8Impl *targetImage, ImageF32Impl *depthBuffer, bool perspective, Filter filter, const TriangleInput &triangleInput, DRAW_CALLBACK_TYPE processTriangle)
  47. : targetImage(targetImage), depthBuffer(depthBuffer), perspective(perspective), filter(filter), triangleInput(triangleInput), processTriangle(processTriangle) {}
  48. };
  49. struct TriangleDrawCommand : public TriangleDrawData {
  50. // Triangle corners and projection
  51. // Not a part of TriangleDrawData, because the draw command is made after clipping into multiple smaller triangles
  52. ITriangle2D triangle;
  53. // The vertex interpolation weights for each corner to allow clipping triangles without
  54. // looping the same vertex colors and texture coordinates on every sub-triangle
  55. // Corner A's weight = (subB.x, subC.x)
  56. // Corner B's weight = (subB.y, subC.y)
  57. // Corner C's weight = (subB.z, subC.z)
  58. // The final vertex weight of a corner becomes a linear interpolation of the three original vertex weights
  59. // (A * (1 - subB - subC)) + (B * subB) + (C * subC)
  60. FVector3D subB, subC;
  61. // Extra clipping in case that the receiver of the command goes out of bound
  62. IRect clipBound;
  63. // Late removal of triangles without having to shuffle around any data
  64. bool occluded;
  65. TriangleDrawCommand(const TriangleDrawData &triangleDrawData, const ITriangle2D &triangle, const FVector3D &subB, const FVector3D &subC, const IRect &clipBound)
  66. : TriangleDrawData(triangleDrawData), triangle(triangle), subB(subB), subC(subC), clipBound(clipBound), occluded(false) {}
  67. };
  68. // Get the visibility state for the triangle as seen by the camera.
  69. // If clipFrustum is false, the culling test will be done with the actual bounds of the target image.
  70. // This is used to know when a triangle needs to be drawn.
  71. // If clipFrustum is true, the culling test will be done with extended clip bounds outside of the target image.
  72. // This is used to know when a triangle needs lossy clipping in floating-point coordinates
  73. // before it can be converted to integer coordinates without causing an overflow in rasterization.
  74. Visibility getTriangleVisibility(const ITriangle2D &triangle, const Camera &camera, bool clipFrustum);
  75. // Draws according to a draw command.
  76. void executeTriangleDrawing(const TriangleDrawCommand &command, const IRect &clipBound);
  77. // A queue of draw commands
  78. class CommandQueue {
  79. public:
  80. List<TriangleDrawCommand> buffer;
  81. void add(const TriangleDrawCommand &command);
  82. // Multi-threading will be disabled if jobCount equals 1.
  83. void execute(const IRect &clipBound, int jobCount = 12) const;
  84. void clear();
  85. };
  86. // Given a triangle and a shader that holds the additional vertex data, this method can be called to draw it.
  87. // Preconditions:
  88. // * triangle should have passed the triangle visibility test for the actual image bound.
  89. // Only construct the shader and make this call if "getTriangleVisibility(triangle, camera, false) != Visibility::Hidden" passed.
  90. // Otherwise, it will waste a lot of time on rasterizing triangles that are not even visible.
  91. // * targetImage must be a render target because it needs some padding for reading out of bound while rendering.
  92. // ImageRgbaU8Impl::createRenderTarget will automatically padd any odd dimensions given.
  93. void renderTriangleWithShader(CommandQueue *commandQueue, const TriangleDrawData &triangleDrawData, const Camera &camera, const ITriangle2D &triangle, const IRect &clipBound);
  94. // Given a set of triangle data, this method can automatically draw it using the fastest default shader.
  95. // Triangle culling is handled automatically but you might want to apply culling per model or something before drawing many triangles.
  96. // commandQueue can be null to render directly using a single thread.
  97. // targetImage can be null to avoid using the pixel shader.
  98. // depthBuffer can be null to render without depth buffering.
  99. // Preconditions:
  100. // * targetImage must be a render target because it needs some padding for reading out of bound while rendering.
  101. // ImageRgbaU8Impl::createRenderTarget will automatically padd any odd dimensions given.
  102. void renderTriangleFromData(
  103. CommandQueue *commandQueue, ImageRgbaU8Impl *targetImage, ImageF32Impl *depthBuffer,
  104. const Camera &camera, const ProjectedPoint &posA, const ProjectedPoint &posB, const ProjectedPoint &posC,
  105. Filter filter, const ImageRgbaU8Impl *diffuse, const ImageRgbaU8Impl *light,
  106. TriangleTexCoords texCoords, TriangleColors colors
  107. );
  108. void renderTriangleFromDataDepth(ImageF32Impl *depthBuffer, const Camera &camera, const ProjectedPoint &posA, const ProjectedPoint &posB, const ProjectedPoint &posC);
  109. }
  110. #endif