TGX 1.1.2
A tiny 2D/3D graphics library optimized for 32 bits microcontrollers.
Loading...
Searching...
No Matches
Renderer3D.h
Go to the documentation of this file.
1
5//
6// Copyright 2020 Arvind Singh
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11//version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; If not, see <http://www.gnu.org/licenses/>.
20
21#ifndef _TGX_RENDERER3D_H_
22#define _TGX_RENDERER3D_H_
23
24// only C++, no plain C
25#ifdef __cplusplus
26
27
28#include "Misc.h"
29#include "Color.h"
30#include "Vec2.h"
31#include "Vec3.h"
32#include "Vec4.h"
33#include "Box2.h"
34#include "Box3.h"
35#include "Mat4.h"
36#include "Image.h"
37
38#include "Shaders.h"
39#include "Rasterizer.h"
40
41#include "Mesh3D.h"
42#include "Mesh3Dv2.h"
43
44namespace tgx
45{
46
47 // forward declaration for the vertices and faces of the unit cube [-1,1]^3
48
49 extern const tgx::fVec3 UNIT_CUBE_VERTICES[8];
50 extern const tgx::fVec3 UNIT_CUBE_NORMALS[6];
51 extern const uint16_t UNIT_CUBE_FACES[6*4];
52 extern const uint16_t UNIT_CUBE_FACES_NORMALS[6 * 4];
53
54
113 template<typename color_t, Shader LOADED_SHADERS = TGX_SHADER_MASK_ALL, typename ZBUFFER_t = float, int MAX_DIRECTIONAL_LIGHTS = 1, int MAX_SPOT_LIGHTS = 0>
115 {
116
117
118 static constexpr int MAXVIEWPORTDIMENSION = 2048 * (1 << ((8 - TGX_RASTERIZE_SUBPIXEL_BITS) >> 1));
119
120 static_assert(is_color<color_t>::value, "color_t must be one of the color types defined in color.h");
121 static_assert((std::is_same<ZBUFFER_t, float>::value) || (std::is_same<ZBUFFER_t, uint16_t>::value), "The Z-buffer type must be either float or uint16_t");
122 static_assert(MAX_DIRECTIONAL_LIGHTS >= 1, "MAX_DIRECTIONAL_LIGHTS must be at least 1");
123 static_assert(MAX_SPOT_LIGHTS >= 0, "MAX_SPOT_LIGHTS must be non-negative");
124
125 // true if some kind of texturing may be used.
126 static constexpr int ENABLE_TEXTURING = (TGX_SHADER_HAS_ONE_FLAG(LOADED_SHADERS , (SHADER_TEXTURE | TGX_SHADER_MASK_TEXTURE_MODE | TGX_SHADER_MASK_TEXTURE_QUALITY)));
127
128 static constexpr Shader ENABLED_SHADERS = LOADED_SHADERS | (ENABLE_TEXTURING ? SHADER_TEXTURE : SHADER_NOTEXTURE); // enable texturing when at least one texturing related flag is set
129 // check that disabled shaders do not completely disable all drawing operations.
130 static_assert(TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_PROJECTION), "At least one of the two shaders SHADER_PERSPECTIVE or SHADER_ORTHO must be enabled");
131 static_assert(TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_ZBUFFER), "At least one of the two shaders SHADER_NOZBUFFER or SHADER_ZBUFFER must be enabled");
132 static_assert(TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_SHADING), "At least one of the shaders SHADER_UNLIT, SHADER_FLAT or SHADER_GOURAUD must be enabled");
133 static_assert(TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_TEXTURE), "At least one of the two shaders SHADER_TEXTURE or SHADER_NOTEXTURE must be enabled");
134 static_assert((!TGX_SHADER_HAS_TEXTURE(ENABLED_SHADERS)) || (TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_TEXTURE_QUALITY)),"When using texturing, at least one of the two shaders SHADER_TEXTURE_BILINEAR or SHADER_TEXTURE_NEAREST must be enabled");
135 static_assert((!TGX_SHADER_HAS_TEXTURE(ENABLED_SHADERS)) || (TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS, TGX_SHADER_MASK_TEXTURE_MODE)), "When using texturing, at least one of the two shaders SHADER_TEXTURE_WRAP_POW2 or SHADER_TEXTURE_CLAMP must be enabled");
136
137
138
139 public:
140
141
151 TGX_NOINLINE Renderer3D(const iVec2& viewportSize = {0,0}, Image<color_t> * im = nullptr, ZBUFFER_t * zbuffer = nullptr);
152
153
154
155
156 /*****************************************************************************************
157 *****************************************************************************************/
164 /*****************************************************************************************
165 ******************************************************************************************/
166
167
188 void setViewportSize(int lx, int ly);
189
190
198 void setViewportSize(const iVec2& viewport_dim);
199
200
213
214
233 void setOffset(int ox, int oy);
234
235
243 void setOffset(const iVec2& offset);
244
245
264
265
272
273
280
281
288
289
306 void setOrtho(float left, float right, float bottom, float top, float zNear, float zFar);
307
308
325 void setFrustum(float left, float right, float bottom, float top, float zNear, float zFar);
326
327
345 void setPerspective(float fovy, float aspect, float zNear, float zFar);
346
347
365 void setCulling(int w);
366
367
380 void setZbuffer(ZBUFFER_t* zbuffer);
381
382
392
393
432 void setShaders(Shader shaders);
433
434
443
444
453
454
455
457 /*****************************************************************************************
458 *****************************************************************************************/
465 /*****************************************************************************************
466 ******************************************************************************************/
467
468
469
486 void setViewMatrix(const fMat4& M);
487
488
497
498
510 void setLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
511
512
524 void setLookAt(const fVec3 eye, const fVec3 center, const fVec3 up);
525
526
540
541
554
555
556
568 void setLightAmbiant(const RGBf& color);
569
582 void setLightDirection(const fVec3& direction);
583
584
585
586
599 void setLightDiffuse(const RGBf& color);
600
601
614 void setLightSpecular(const RGBf& color);
615
616
632 void setLight(const fVec3 direction, const RGBf& ambiantColor, const RGBf& diffuseColor, const RGBf& specularColor);
633
634
647
648
653
654
658 static constexpr int maxDirectionalLightCount() { return MAX_DIRECTIONAL_LIGHTS; }
659
660
671
672
682 void setDirectionalLightDirection(int index, const fVec3& direction);
683
684
693 void setDirectionalLightDiffuse(int index, const RGBf& color);
694
695
704 void setDirectionalLightSpecular(int index, const RGBf& color);
705
706
718 void setDirectionalLight(int index, const fVec3& direction, const RGBf& diffuseColor, const RGBf& specularColor);
719
720
721
722
723
725 /*****************************************************************************************
726 *****************************************************************************************/
733 /*****************************************************************************************
734 ******************************************************************************************/
735
736
737
748 void setModelMatrix(const fMat4& M);
749
750
759
760
782 void setModelPosScaleRot(const fVec3& center = fVec3{ 0,0,0 }, const fVec3& scale = fVec3(1, 1, 1), float rot_angle = 0, const fVec3& rot_dir = fVec3{ 0,1,0 });
783
784
796
797
810
811
823
824
833 void setMaterialAmbiantStrength(float strenght = 0.1f);
834
835
844 void setMaterialDiffuseStrength(float strenght = 0.6f);
845
846
855 void setMaterialSpecularStrength(float strenght = 0.5f);
856
857
868 void setMaterialSpecularExponent(int exponent = 16);
869
870
883 void setMaterial(RGBf color, float ambiantStrength, float diffuseStrength, float specularStrength, int specularExponent);
884
885
886
887
888
889
890
891
893 /*****************************************************************************************
894 *****************************************************************************************/
908 /*****************************************************************************************
909 ******************************************************************************************/
910
911
912
929 void drawMesh(const Mesh3D<color_t>* mesh, bool use_mesh_material = true, bool draw_chained_meshes = true);
930
931
944 void drawMesh(const Mesh3Dv2<color_t>* mesh, bool use_mesh_material = true);
945
946
960 void drawTriangle(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3,
961 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr,
962 const fVec2 * T1 = nullptr, const fVec2 * T2 = nullptr, const fVec2 * T3 = nullptr,
963 const Image<color_t> * texture = nullptr);
964
965
978 void drawTriangleWithVertexColor(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3,
979 const RGBf & col1, const RGBf & col2, const RGBf & col3,
980 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr);
981
982
1001 void drawTriangles(int nb_triangles,
1002 const uint16_t * ind_vertices, const fVec3 * vertices,
1003 const uint16_t * ind_normals = nullptr, const fVec3* normals = nullptr,
1004 const uint16_t * ind_texture = nullptr, const fVec2* textures = nullptr,
1005 const Image<color_t> * texture_image = nullptr);
1006
1007
1030 void drawTriangleStrip(int nb_indices,
1031 const uint16_t* ind_vertices, const fVec3* vertices,
1032 const uint16_t* ind_normals = nullptr, const fVec3* normals = nullptr,
1033 const uint16_t* ind_texture = nullptr, const fVec2* textures = nullptr,
1034 const Image<color_t>* texture_image = nullptr);
1035
1036
1037
1053 void drawQuad(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3, const fVec3 & P4,
1054 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr, const fVec3 * N4 = nullptr,
1055 const fVec2 * T1 = nullptr, const fVec2 * T2 = nullptr, const fVec2 * T3 = nullptr, const fVec2 * T4 = nullptr,
1056 const Image<color_t>* texture = nullptr);
1057
1058
1059
1075 void drawQuadWithVertexColor(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3, const fVec3 & P4,
1076 const RGBf & col1, const RGBf & col2, const RGBf & col3, const RGBf & col4,
1077 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr, const fVec3 * N4 = nullptr);
1078
1079
1080
1081
1102 void drawQuads(int nb_quads,
1103 const uint16_t * ind_vertices, const fVec3 * vertices,
1104 const uint16_t * ind_normals = nullptr, const fVec3* normals = nullptr,
1105 const uint16_t * ind_texture = nullptr, const fVec2* textures = nullptr,
1106 const Image<color_t>* texture_image = nullptr);
1107
1108
1109
1110
1112 /*****************************************************************************************
1113 *****************************************************************************************/
1120 /*****************************************************************************************
1121 ******************************************************************************************/
1122
1123
1124
1131 void drawCube();
1132
1133
1175 const fVec2 v_front_ABCD[4] , const Image<color_t>* texture_front,
1176 const fVec2 v_back_EFGH[4] , const Image<color_t>* texture_back,
1177 const fVec2 v_top_HADE[4] , const Image<color_t>* texture_top,
1178 const fVec2 v_bottom_BGFC[4], const Image<color_t>* texture_bottom,
1179 const fVec2 v_left_HGBA[4] , const Image<color_t>* texture_left,
1180 const fVec2 v_right_DCFE[4] , const Image<color_t>* texture_right
1181 );
1182
1183
1219 const Image<color_t>* texture_front,
1220 const Image<color_t>* texture_back,
1221 const Image<color_t>* texture_top,
1222 const Image<color_t>* texture_bottom,
1223 const Image<color_t>* texture_left,
1224 const Image<color_t>* texture_right
1225 );
1226
1227
1287 const fVec2 v_front_ABCD[4] , const Image<color_t>* texture_front,
1288 const fVec2 v_back_EFGH[4] , const Image<color_t>* texture_back,
1289 const fVec2 v_top_HADE[4] , const Image<color_t>* texture_top,
1290 const fVec2 v_bottom_BGFC[4], const Image<color_t>* texture_bottom,
1291 const fVec2 v_left_HGBA[4] , const Image<color_t>* texture_left,
1292 const fVec2 v_right_DCFE[4] , const Image<color_t>* texture_right,
1293 float rot_angle_y = 0.0f,
1294 float reference_height = 0.0f,
1295 float skybox_radius = 32768.0f,
1296 Shader texture_quality = SHADER_TEXTURE_NEAREST,
1297 Shader texture_mode = SHADER_TEXTURE_CLAMP
1298 );
1299
1300
1307 const Image<color_t>* texture_front,
1308 const Image<color_t>* texture_back,
1309 const Image<color_t>* texture_top,
1310 const Image<color_t>* texture_bottom,
1311 const Image<color_t>* texture_left,
1312 const Image<color_t>* texture_right,
1313 float rot_angle_y = 0.0f,
1314 float reference_height = 0.0f,
1315 float skybox_radius = 32768.0f,
1316 Shader texture_quality = SHADER_TEXTURE_NEAREST,
1317 Shader texture_mode = SHADER_TEXTURE_CLAMP
1318 );
1319
1320
1321
1332 void drawSphere(int nb_sectors, int nb_stacks);
1333
1334
1347 void drawSphere(int nb_sectors, int nb_stacks, const Image<color_t>* texture);
1348
1349
1364 void drawAdaptativeSphere(float quality = 1.0f);
1365
1366
1384 void drawAdaptativeSphere(const Image<color_t>* texture, float quality = 1.0f);
1385
1386
1387
1388
1389
1390
1391
1392
1394 /*****************************************************************************************
1395 *****************************************************************************************/
1410 /*****************************************************************************************
1411 ******************************************************************************************/
1412
1413
1414
1426 void drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes = true);
1427
1428
1441
1442
1453 void drawWireFrameMeshAA(const Mesh3D<color_t>* mesh, bool draw_chained_meshes = true);
1454
1455
1466
1467
1484 void drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes, float thickness, color_t color, float opacity);
1485
1486
1503 void drawWireFrameMesh(const Mesh3Dv2<color_t>* mesh, float thickness, color_t color, float opacity);
1504
1505
1515 void drawWireFrameLine(const fVec3& P1, const fVec3& P2);
1516
1517
1527 void drawWireFrameLineAA(const fVec3& P1, const fVec3& P2);
1528
1529
1542 void drawWireFrameLine(const fVec3& P1, const fVec3& P2, float thickness, color_t color, float opacity);
1543
1544
1556 void drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices);
1557
1558
1570 void drawWireFrameLinesAA(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices);
1571
1572
1587 void drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1588
1589
1600 void drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3);
1601
1602
1612 void drawWireFrameTriangleAA(const fVec3& P1, const fVec3& P2, const fVec3& P3);
1613
1614
1629 void drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3, float thickness, color_t color, float opacity);
1630
1631
1644 void drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices);
1645
1646
1658 void drawWireFrameTrianglesAA(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices);
1659
1660
1677 void drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1678
1679
1694 void drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices);
1695
1696
1710 void drawWireFrameTriangleStripAA(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices);
1711
1712
1731 void drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1732
1733
1745 void drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4);
1746
1747
1757 void drawWireFrameQuadAA(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4);
1758
1759
1775 void drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4, float thickness, color_t color, float opacity);
1776
1777
1791 void drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices);
1792
1793
1805 void drawWireFrameQuadsAA(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices);
1806
1807
1825 void drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1826
1827
1828
1829
1831 /*****************************************************************************************
1832 *****************************************************************************************/
1847 /*****************************************************************************************
1848 ******************************************************************************************/
1849
1850
1859
1860
1869
1870
1884 void drawWireFrameCube(float thickness, color_t color, float opacity);
1885
1886
1898 void drawWireFrameSphere(int nb_sectors, int nb_stacks);
1899
1900
1911 void drawWireFrameSphereAA(int nb_sectors, int nb_stacks);
1912
1913
1930 void drawWireFrameSphere(int nb_sectors, int nb_stacks, float thickness, color_t color, float opacity);
1931
1932
1946 void drawWireFrameAdaptativeSphere(float quality = 1.0f);
1947
1948
1958 void drawWireFrameAdaptativeSphereAA(float quality = 1.0f);
1959
1960
1979 void drawWireFrameAdaptativeSphere(float quality, float thickness, color_t color, float opacity);
1980
1981
1982
1983
1984
1986 /*****************************************************************************************
1987 *****************************************************************************************/
1996 /*****************************************************************************************
1997 ******************************************************************************************/
1998
1999
2000
2010 void drawPixel(const fVec3& pos);
2011
2012
2024 void drawPixel(const fVec3& pos, color_t color, float opacity);
2025
2026
2037 void drawPixels(int nb_pixels, const fVec3* pos_list);
2038
2039
2054 void drawPixels(int nb_pixels, const fVec3* pos_list, const int* colors_ind, const color_t* colors, const int* opacities_ind, const float* opacities);
2055
2056
2067 void drawDot(const fVec3& pos, int r);
2068
2069
2070
2083 void drawDot(const fVec3& pos, int r, color_t color, float opacity);
2084
2085
2097 void drawDots(int nb_dots, const fVec3* pos_list, const int radius);
2098
2099
2117 void drawDots(int nb_dots, const fVec3* pos_list, const int* radius_ind, const int* radius, const int* colors_ind, const color_t* colors, const int* opacities_ind, const float* opacities);
2118
2119
2120
2121
2122
2124
2125
2126
2127
2128
2129 private:
2130
2131
2132
2133 /*****************************************************************************************
2134 ******************************************************************************************
2135 *
2136 * BE CAREFUL PAST THIS POINT... FOR HERE BE DRAGONS !
2137 *
2138 ******************************************************************************************
2139 ******************************************************************************************/
2140
2141
2143 TGX_INLINE float _clipbound_xy() const
2144 {
2145 return (256 + 3*((MAXVIEWPORTDIMENSION * 256) / ((_lx > _ly) ? _lx : _ly))) / 1024.0f; // use integer computation up to the last divide
2146 //return (1.0f + 3.0f * (((float)MAXVIEWPORTDIMENSION) / ((_lx > _ly) ? _lx : _ly))) / 4.0f;
2147 }
2148
2149
2151 TGX_INLINE bool _validDraw() const
2152 {
2153 return ((_lx > 0) && (_ly > 0) && (_uni.im != nullptr) && (_uni.im->isValid()));
2154 }
2155
2156
2158 TGX_NOINLINE void _recompute_wa_wb();
2159
2160
2161 /***********************************************************
2162 * Making sure shader flags are coherent
2163 ************************************************************/
2164
2165 TGX_NOINLINE void _rectifyShaderOrtho();
2166
2167
2168 TGX_NOINLINE void _rectifyShaderZbuffer();
2169
2170
2171 TGX_NOINLINE void _rectifyShaderShading(Shader new_shaders);
2172
2173
2174 TGX_NOINLINE void _rectifyShaderTextureWrapping();
2175
2176
2177 TGX_NOINLINE void _rectifyShaderTextureQuality();
2178
2179
2180 /***********************************************************
2181 * DRAWING STUFF
2182 ************************************************************/
2183
2184
2186 void _drawTriangleClipped(const int RASTER_TYPE,
2187 const fVec4* Q0, const fVec4* Q1, const fVec4* Q2,
2188 const fVec3* N0, const fVec3* N1, const fVec3* N2,
2189 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2190 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2);
2191
2192
2194 void _drawTriangleClippedSub(const int RASTER_TYPE, const int plane,
2195 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3);
2196
2197
2199 void _drawTriangle(const int RASTER_TYPE,
2200 const fVec3* P0, const fVec3* P1, const fVec3* P2,
2201 const fVec3* N0, const fVec3* N1, const fVec3* N2,
2202 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2203 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2);
2204
2205
2207 void _drawTriangleStrip(const int RASTER_TYPE, int nb_indices,
2208 const uint16_t* ind_vertices, const fVec3* vertices,
2209 const uint16_t* ind_normals, const fVec3* normals,
2210 const uint16_t* ind_texture, const fVec2* textures);
2211
2212
2214 void _drawQuad(const int RASTER_TYPE,
2215 const fVec3* P0, const fVec3* P1, const fVec3* P2, const fVec3* P3,
2216 const fVec3* N0, const fVec3* N1, const fVec3* N2, const fVec3* N3,
2217 const fVec2* T0, const fVec2* T1, const fVec2* T2, const fVec2* T3,
2218 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2, const RGBf& Vcol3);
2219
2221 template<bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
2222 void _rasterizeSkyBoxTriangle(const RasterizerVec4& V0, const RasterizerVec4& V1, const RasterizerVec4& V2);
2223
2225 void _rasterizeSkyBoxTriangle(const RasterizerVec4& V0, const RasterizerVec4& V1, const RasterizerVec4& V2,
2226 Shader texture_quality, Shader texture_mode);
2227
2229 void _drawSkyBoxTriangleClippedSub(const int plane,
2230 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2231 Shader texture_quality, Shader texture_mode);
2232
2234 void _drawSkyBoxTriangleClipped(
2235 const fVec4* Q0, const fVec4* Q1, const fVec4* Q2,
2236 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2237 Shader texture_quality, Shader texture_mode);
2238
2240 void _drawSkyBoxQuad(
2241 const fVec4* P0, const fVec4* P1, const fVec4* P2, const fVec4* P3,
2242 const fVec2* T0, const fVec2* T1, const fVec2* T2, const fVec2* T3,
2243 Shader texture_quality, Shader texture_mode);
2244
2246 void _drawSkyBoxFace(const fVec4 skybox_vertices[8], const uint16_t* face, const fVec2 texture_coords[4], const Image<color_t>* texture,
2247 Shader texture_quality, Shader texture_mode);
2248
2249
2251 void _drawMesh(const int RASTER_TYPE, const Mesh3D<color_t>* mesh);
2252
2254 void _drawMesh(const int RASTER_TYPE, const Mesh3Dv2<color_t>* mesh, bool use_mesh_material);
2255
2257 TGX_INLINE inline bool _discardMeshlet16b(const fVec3& sphere_center, float sphere_radius, const fVec3& cone_dir, float cone_cos) const
2258 {
2259 if (cone_cos <= -1.0f) return false;
2260
2261 const fVec4 D = _r_modelViewM.mult0(cone_dir);
2262 const float dd = D.x * D.x + D.y * D.y + D.z * D.z;
2263 if (dd <= 1.0e-20f) return false;
2264
2265 float dot;
2266 float len2;
2267 if (_ortho)
2268 {
2269 dot = D.z; // object-to-camera direction is +Z in view space.
2270 len2 = dd;
2271 }
2272 else
2273 {
2274 const fVec3 anchor = sphere_center - (cone_dir * sphere_radius);
2275 const fVec4 A = _r_modelViewM.mult1(anchor);
2276 dot = -(D.x * A.x + D.y * A.y + D.z * A.z);
2277 const float aa = A.x * A.x + A.y * A.y + A.z * A.z;
2278 if (aa <= 1.0e-20f) return false;
2279 len2 = dd * aa;
2280 }
2281
2282 const float c2len2 = cone_cos * cone_cos * len2;
2283 const float dot2 = dot * dot;
2284 return (cone_cos >= 0.0f) ? ((dot < 0.0f) || (dot2 < c2len2))
2285 : ((dot < 0.0f) && (dot2 > c2len2));
2286 }
2287
2288
2289
2290 /***********************************************************
2291 * Drawing wireframe
2292 ************************************************************/
2293
2294 inline void _drawWireFrameLineFast(iVec2 P0, iVec2 P1, color_t color);
2295
2296 template<bool CHECK_NEIGHBOR> inline void _drawWireFrameLineAAFast(const fVec2& P0, const fVec2& P1, color_t color, int32_t op);
2297
2298 template<int MODE> void _drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes, color_t color, float opacity, float thickness);
2299
2300 template<int MODE> void _drawWireFrameMesh(const Mesh3Dv2<color_t>* mesh, color_t color, float opacity, float thickness);
2301
2302 template<int MODE> void _drawWireFrameLine(const fVec3& P1, const fVec3& P2, color_t color, float opacity, float thickness);
2303
2304 template<int MODE> void _drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2305
2306 template<int MODE> void _drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3, color_t color, float opacity, float thickness);
2307
2308 template<int MODE> void _drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2309
2310 template<int MODE> void _drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2311
2312 template<int MODE> void _drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4, color_t color, float opacity, float thickness);
2313
2314 template<int MODE> void _drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2315
2316
2317
2318
2319 /***********************************************************
2320 * Simple geometric objects
2321 ************************************************************/
2322
2323
2324 template<bool USE_BLENDING> void _drawPixel(const fVec3& pos, color_t color, float opacity);
2325
2326
2327 template<bool USE_COLORS, bool USE_BLENDING> void _drawPixels(int nb_pixels, const fVec3* pos_list, const int* colors_ind, const color_t* colors, const int* opacities_ind, const float* opacities);
2328
2329
2330 template<bool USE_BLENDING> void _drawDot(const fVec3& pos, int r, color_t color, float opacity);
2331
2332
2333 template<bool USE_RADIUS, bool USE_COLORS, bool USE_BLENDING> void _drawDots(int nb_dots, const fVec3* pos_list, const int* radius_ind, const int* radius, const int* colors_ind, const color_t* colors, const int* opacities_ind, const float* opacities);
2334
2335
2336
2337 template<bool CHECKRANGE, bool USE_BLENDING> TGX_INLINE inline void drawPixelZbuf(int x, int y, color_t color, float opacity, float z)
2338 {
2339 if (CHECKRANGE && ((x < 0) || (x >= _uni.im->lx()) || (y < 0) || (y >= _uni.im->ly()))) return;
2340 ZBUFFER_t& W = _uni.zbuf[x + _uni.im->lx() * y];
2341 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(z * _uni.wa + _uni.wb)) : ((ZBUFFER_t)z);
2342 if (W < aa)
2343 {
2344 W = aa;
2345 if (USE_BLENDING) _uni.im->template drawPixel<false>({ x, y }, color, opacity); else _uni.im->template drawPixel<false>({ x, y }, color);
2346 }
2347 }
2348
2349
2350 template<bool CHECKRANGE, bool USE_BLENDING> TGX_INLINE inline void drawHLineZbuf(int x, int y, int w, color_t color, float opacity, float z)
2351 {
2352 if (CHECKRANGE) // optimized away at compile time
2353 {
2354 const int lx = _uni.im->lx();
2355 const int ly = _uni.im->ly();
2356 if ((y < 0) || (y >= ly) || (x >= lx)) return;
2357 if (x < 0) { w += x; x = 0; }
2358 if (x + w > lx) { w = lx - x; }
2359 if (w <= 0) return;
2360 }
2361 while(w--) drawPixelZbuf<CHECKRANGE, USE_BLENDING>(x++, y, color, opacity, z);
2362 }
2363
2364
2365 template<bool CHECKRANGE, bool USE_BLENDING> void _drawCircleZbuf(int xm, int ym, int r, color_t color, float opacity, float z);
2366
2367
2371 float _unitSphereScreenDiameter();
2372
2373
2374 template<bool WIREFRAME, int MODE> void _drawSphere(int nb_sectors, int nb_stacks, const Image<color_t>* texture, float thickness, color_t color, float opacity);
2375
2376
2377
2378 /***********************************************************
2379 * CLIPPING
2380 ************************************************************/
2381
2382
2384 TGX_INLINE inline void _clip(int & fl, const fVec4 & P, float bx, float Bx, float by, float By)
2385 {
2386 if (P.x >= bx) { fl &= (~(1)); }
2387 if (P.x <= Bx) { fl &= (~(2)); }
2388 if (P.y >= by) { fl &= (~(4)); }
2389 if (P.y <= By) { fl &= (~(8)); }
2390 if ((P.z >= -1.0f)&&(P.w > 0)) { fl &= (~(16)); }
2391 if (P.z <= +1.0f) { fl &= (~(32)); }
2392 }
2393
2394
2396 TGX_INLINE inline void _clip(int & fl, const fVec3 & P, float bx, float Bx, float by, float By, const fMat4 & M)
2397 {
2398 fVec4 S = M.mult1(P);
2399 if (!_ortho) S.zdivide();
2400 return _clip(fl, S, bx, Bx, by, By);
2401 }
2402
2403
2404 /* test if a box is outside the image and should be discarded.
2405 transform the box coords with M then z-divide. */
2406 bool _discardBox(const fBox3 & bb, const fMat4 & M)
2407 {
2408 if ((bb.minX == 0) && (bb.maxX == 0) && (bb.minY == 0) && (bb.maxY == 0) && (bb.minZ == 0) && (bb.maxZ == 0))
2409 return false; // do not discard if the bounding box is uninitialized.
2410
2411 const float bx = (_ox - 1) * _ilx - 1.0f;
2412 const float Bx = (_ox + _uni.im->width() + 1) * _ilx - 1.0f;
2413 const float by = (_oy - 1) * _ily - 1.0f;
2414 const float By = (_oy + _uni.im->height() + 1) * _ily - 1.0f;
2415
2416 int fl = 63; // every bit set
2417 _clip(fl, fVec3(bb.minX, bb.minY, bb.minZ), bx, Bx, by, By, M);
2418 if (fl == 0) return false;
2419 _clip(fl, fVec3(bb.minX, bb.minY, bb.maxZ), bx, Bx, by, By, M);
2420 if (fl == 0) return false;
2421 _clip(fl, fVec3(bb.minX, bb.maxY, bb.minZ), bx, Bx, by, By, M);
2422 if (fl == 0) return false;
2423 _clip(fl, fVec3(bb.minX, bb.maxY, bb.maxZ), bx, Bx, by, By, M);
2424 if (fl == 0) return false;
2425 _clip(fl, fVec3(bb.maxX, bb.minY, bb.minZ), bx, Bx, by, By, M);
2426 if (fl == 0) return false;
2427 _clip(fl, fVec3(bb.maxX, bb.minY, bb.maxZ), bx, Bx, by, By, M);
2428 if (fl == 0) return false;
2429 _clip(fl, fVec3(bb.maxX, bb.maxY, bb.minZ), bx, Bx, by, By, M);
2430 if (fl == 0) return false;
2431 _clip(fl, fVec3(bb.maxX, bb.maxY, bb.maxZ), bx, Bx, by, By, M);
2432 if (fl == 0) return false;
2433 return true;
2434 }
2435
2436
2437 /* test if a triangle is completely outside the image and should be discarded.
2438 * coords are given after z-divide. */
2439 bool _discardTriangle(const fVec4 & P1, const fVec4 & P2, const fVec4 & P3)
2440 {
2441 const float bx = (_ox - 1) * _ilx - 1.0f;
2442 const float Bx = (_ox + _uni.im->width() + 1) * _ilx - 1.0f;
2443 const float by = (_oy - 1) * _ily - 1.0f;
2444 const float By = (_oy + _uni.im->height() + 1) * _ily - 1.0f;
2445
2446 int fl = 63; // every bit set
2447 _clip(fl, P1, bx, Bx, by, By);
2448 if (fl == 0) return false;
2449 _clip(fl, P2, bx, Bx, by, By);
2450 if (fl == 0) return false;
2451 _clip(fl, P3, bx, Bx, by, By);
2452 if (fl == 0) return false;
2453 return true;
2454 }
2455
2456
2458 bool _clip2(float clipboundXY, const fVec3 & P, const fMat4 & M)
2459 {
2460 fVec4 S = M.mult1(P);
2461 if (!_ortho)
2462 {
2463 S.zdivide();
2464 if (S.w <= 0) S.z = -2;
2465 }
2466 return ((S.x <= -clipboundXY) || (S.x >= clipboundXY)
2467 || (S.y <= -clipboundXY) || (S.y >= clipboundXY)
2468 || (S.z <= -1) || (S.z >= 1));
2469 }
2470
2471
2473 bool _clipTestNeeded(float clipboundXY, const fBox3 & bb, const fMat4 & M)
2474 {
2475 return (_clip2(clipboundXY, fVec3(bb.minX, bb.minY, bb.minZ), M)
2476 || _clip2(clipboundXY, fVec3(bb.minX, bb.minY, bb.maxZ), M)
2477 || _clip2(clipboundXY, fVec3(bb.minX, bb.maxY, bb.minZ), M)
2478 || _clip2(clipboundXY, fVec3(bb.minX, bb.maxY, bb.maxZ), M)
2479 || _clip2(clipboundXY, fVec3(bb.maxX, bb.minY, bb.minZ), M)
2480 || _clip2(clipboundXY, fVec3(bb.maxX, bb.minY, bb.maxZ), M)
2481 || _clip2(clipboundXY, fVec3(bb.maxX, bb.maxY, bb.minZ), M)
2482 || _clip2(clipboundXY, fVec3(bb.maxX, bb.maxY, bb.maxZ), M));
2483 }
2484
2485
2487 bool _wireFrameAANeighborCheckNeeded(const fBox3& bb, const fMat4& proj_modelview)
2488 {
2489 if ((_uni.im == nullptr) || (_uni.im->lx() <= 2) || (_uni.im->ly() <= 2)) return true;
2490
2491 const float bx = (_ox + 1.0f) * _ilx - 1.0f;
2492 const float Bx = (_ox + (float)(_uni.im->lx() - 2)) * _ilx - 1.0f;
2493 const float by = (_oy + 1.0f) * _ily - 1.0f;
2494 const float By = (_oy + (float)(_uni.im->ly() - 2)) * _ily - 1.0f;
2495
2496 const fVec3 C[8] = {
2497 fVec3(bb.minX, bb.minY, bb.minZ),
2498 fVec3(bb.minX, bb.minY, bb.maxZ),
2499 fVec3(bb.minX, bb.maxY, bb.minZ),
2500 fVec3(bb.minX, bb.maxY, bb.maxZ),
2501 fVec3(bb.maxX, bb.minY, bb.minZ),
2502 fVec3(bb.maxX, bb.minY, bb.maxZ),
2503 fVec3(bb.maxX, bb.maxY, bb.minZ),
2504 fVec3(bb.maxX, bb.maxY, bb.maxZ)
2505 };
2506
2507 for (int i = 0; i < 8; i++)
2508 {
2509 fVec4 P = proj_modelview.mult1(C[i]);
2510 if (!_ortho)
2511 {
2512 if (P.w <= 0) return true;
2513 P.zdivide();
2514 }
2515 if ((P.z < -1.0f) || (P.z > 1.0f)) return true;
2516 if ((P.x < bx) || (P.x > Bx) || (P.y < by) || (P.y > By)) return true;
2517 }
2518 return false;
2519 }
2520
2521
2522#if TGX_MESHLET_SPHERE_CLIP
2524 TGX_INLINE inline void _meshletClipPlanes(float clipboundXY, const fMat4& M, fVec4* planes, float* plane_norms) const
2525 {
2526 const float cx = clipboundXY;
2527 planes[0] = fVec4(M.M[0] + cx * M.M[3], M.M[4] + cx * M.M[7], M.M[8] + cx * M.M[11], M.M[12] + cx * M.M[15]);
2528 planes[1] = fVec4(-M.M[0] + cx * M.M[3], -M.M[4] + cx * M.M[7], -M.M[8] + cx * M.M[11], -M.M[12] + cx * M.M[15]);
2529 planes[2] = fVec4(M.M[1] + cx * M.M[3], M.M[5] + cx * M.M[7], M.M[9] + cx * M.M[11], M.M[13] + cx * M.M[15]);
2530 planes[3] = fVec4(-M.M[1] + cx * M.M[3], -M.M[5] + cx * M.M[7], -M.M[9] + cx * M.M[11], -M.M[13] + cx * M.M[15]);
2531 planes[4] = fVec4(M.M[2] + M.M[3], M.M[6] + M.M[7], M.M[10] + M.M[11], M.M[14] + M.M[15]);
2532 planes[5] = fVec4(-M.M[2] + M.M[3], -M.M[6] + M.M[7], -M.M[10] + M.M[11], -M.M[14] + M.M[15]);
2533 for (int i = 0; i < 6; i++)
2534 {
2535 const fVec4& P = planes[i];
2536 plane_norms[i] = sqrtf(P.x * P.x + P.y * P.y + P.z * P.z);
2537 }
2538 }
2539
2540
2542 TGX_INLINE inline int _meshletSphereClip(const fVec3& center, float radius, const fVec4* planes, const float* plane_norms) const
2543 {
2544 bool intersects = false;
2545 for (int i = 0; i < 6; i++)
2546 {
2547 const fVec4& P = planes[i];
2548 const float d = P.x * center.x + P.y * center.y + P.z * center.z + P.w;
2549 const float r = radius * plane_norms[i];
2550 if (d < -r) return -1;
2551 if (d < r) intersects = true;
2552 }
2553 return intersects ? 1 : 0;
2554 }
2555#endif
2556
2557
2558
2559
2560 /***********************************************************
2561 * TRIANGLE CLIPPING AGAINST A CLIP-PLANE
2562 ************************************************************/
2563
2572 inline float _cpdist(const tgx::fVec4& CP, float off, const tgx::fVec4& P)
2573 {
2574 return (CP.x * P.x) + (CP.y * P.y) + (CP.z * P.z) + (CP.w * P.w) + off;
2575 }
2576
2587 inline float _cpfactor(const tgx::fVec4& CP, const float sdistA, const float sdistB)
2588 {
2589 return sdistA / (sdistA - sdistB);
2590 }
2591
2592
2594 void _triangleClip1in(int shader, tgx::fVec4 CP,
2595 float cp1, float cp2, float cp3,
2596 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2597 RasterizerVec4& nP1, RasterizerVec4& nP2, RasterizerVec4& nP3, RasterizerVec4& nP4);
2598
2599
2601 void _triangleClip2in(int shader, tgx::fVec4 CP,
2602 float cp1, float cp2, float cp3,
2603 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2604 RasterizerVec4& nP1, RasterizerVec4& nP2, RasterizerVec4& nP3, RasterizerVec4& nP4);
2605
2606
2607 int _triangleClip(int shader, tgx::fVec4 CP, float off,
2608 const RasterizerVec4 & P1, const RasterizerVec4 & P2, const RasterizerVec4 & P3,
2609 RasterizerVec4 & nP1, RasterizerVec4 & nP2, RasterizerVec4 & nP3, RasterizerVec4 & nP4);
2610
2611
2612
2613 /***********************************************************
2614 * PHONG LIGHTNING
2615 ************************************************************/
2616
2617 static const int _POWTABSIZE = 32; // number of entries in the precomputed power table for specular exponent.
2618 int _currentpow; // exponent for the currently computed table (<0 if table not yet computed)
2619 float _powmax; // used to compute exponent
2620 float _fastpowtab[_POWTABSIZE]; // the precomputed power table.
2621
2623 TGX_INLINE inline void _precomputeSpecularTable(int exponent)
2624 {
2625 if (_currentpow == exponent) return;
2626 _precomputeSpecularTable2(exponent);
2627 }
2628
2629 TGX_NOINLINE void _precomputeSpecularTable2(int exponent);
2630
2631
2633 TGX_INLINE inline float _powSpecular(float x) const
2634 {
2635 const float indf = (_powmax - x) * _POWTABSIZE;
2636 const int indi = max(0,(int)indf);
2637 return (indi >= (_POWTABSIZE - 1)) ? 0.0f : (_fastpowtab[indi] + (indf - indi) * (_fastpowtab[indi + 1] - _fastpowtab[indi]));;
2638 }
2639
2640
2641
2642
2644 TGX_INLINE inline void _updateDirectionalLightTransform(int index)
2645 {
2646 _r_light[index] = _viewM.mult0(_light[index]);
2647 _r_light[index] = -_r_light[index];
2648 _r_light[index].normalize();
2649 _r_light_inorm[index] = _r_light[index] * _r_inorm;
2650 _r_H[index] = fVec3(0, 0, 1); // cheating: should use the normalized current vertex position (but this is faster with almost the same result)...
2651 _r_H[index] += _r_light[index];
2652 _r_H[index].normalize();
2653 _r_H_inorm[index] = _r_H[index] * _r_inorm;
2654 }
2655
2656
2658 TGX_INLINE inline void _updateActiveDirectionalLightInorms()
2659 {
2660 for (int i = 0; i < _directionalLightCount; i++)
2661 {
2662 _r_light_inorm[i] = _r_light[i] * _r_inorm;
2663 _r_H_inorm[i] = _r_H[i] * _r_inorm;
2664 }
2665 }
2666
2667
2669 TGX_INLINE inline void _updateActiveDirectionalLightTransforms()
2670 {
2671 for (int i = 0; i < _directionalLightCount; i++)
2672 {
2673 _updateDirectionalLightTransform(i);
2674 }
2675 }
2676
2677
2679 TGX_INLINE inline void _setRuntimeMaterialLighting(float ambiantStrength, float diffuseStrength, float specularStrength)
2680 {
2681 _r_ambiantColor = _ambiantColor * ambiantStrength;
2682 for (int i = 0; i < _directionalLightCount; i++)
2683 {
2684 _r_diffuseColor[i] = _diffuseColor[i] * diffuseStrength;
2685 _r_specularColor[i] = _specularColor[i] * specularStrength;
2686 }
2687 }
2688
2689
2691 TGX_INLINE inline void _updateDirectionalLightColor(int index)
2692 {
2693 _r_diffuseColor[index] = _diffuseColor[index] * _diffuseStrength;
2694 _r_specularColor[index] = _specularColor[index] * _specularStrength;
2695 }
2696
2697
2698
2699 //
2700
2701
2703 template<bool TEXTURE> TGX_INLINE inline RGBf _shadeVertex(const float icu, const fVec3 & N) const
2704 {
2705 RGBf col = _r_ambiantColor;
2706 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2707 {
2708 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light_inorm[0]), 0.0f);
2709 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H_inorm[0]));
2710 }
2711 else
2712 {
2713 for (int i = 0; i < _directionalLightCount; i++)
2714 {
2715 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light_inorm[i]), 0.0f);
2716 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H_inorm[i]));
2717 }
2718 }
2719 if (!(TEXTURE)) col *= _r_objectColor;
2720 col.clamp();
2721 return col;
2722 }
2723
2724
2726 TGX_INLINE inline RGBf _shadeVertex(const float icu, const fVec3 & N, const RGBf & color) const
2727 {
2728 RGBf col = _r_ambiantColor;
2729 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2730 {
2731 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light_inorm[0]), 0.0f);
2732 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H_inorm[0]));
2733 }
2734 else
2735 {
2736 for (int i = 0; i < _directionalLightCount; i++)
2737 {
2738 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light_inorm[i]), 0.0f);
2739 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H_inorm[i]));
2740 }
2741 }
2742
2743 col *= color;
2744 col.clamp();
2745 return col;
2746 }
2747
2748
2750 template<bool TEXTURE> TGX_INLINE inline RGBf _shadeFace(const float icu, const fVec3 & N) const
2751 {
2752 RGBf col = _r_ambiantColor;
2753 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2754 {
2755 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light[0]), 0.0f);
2756 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H[0]));
2757 }
2758 else
2759 {
2760 for (int i = 0; i < _directionalLightCount; i++)
2761 {
2762 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light[i]), 0.0f);
2763 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H[i]));
2764 }
2765 }
2766 if (!(TEXTURE)) col *= _r_objectColor;
2767 col.clamp();
2768 return col;
2769 }
2770
2771
2773 TGX_INLINE inline void _setFlatOrUnlitFaceColor(int raster_type, bool texture, fVec3& faceN, float cu)
2774 {
2775 if constexpr (TGX_SHADER_HAS_UNLIT(ENABLED_SHADERS))
2776 {
2777 if (TGX_SHADER_HAS_UNLIT(raster_type))
2778 {
2779 _uni.facecolor = texture ? RGBf(1.0f, 1.0f, 1.0f) : _r_objectColor;
2780 return;
2781 }
2782 }
2783
2784 const float icu = ((cu > 0) ? -1.0f : 1.0f); // -1 if we need to reverse the face normal.
2785 faceN.normalize_fast();
2786 if (texture)
2787 _uni.facecolor = _shadeFace<true>(icu, faceN);
2788 else
2789 _uni.facecolor = _shadeFace<false>(icu, faceN);
2790 }
2791
2792
2793
2794 /***********************************************************
2795 * MEMBER VARIABLES
2796 ************************************************************/
2797
2798 // *** general parameters ***
2799
2800 int _lx, _ly; // viewport dimension
2801 float _ilx, _ily; // inverse viewport dimension
2802
2803 int _ox, _oy; // image offset w.r.t. the viewport
2804
2805 bool _ortho; // true to use orthographic projection and false for perspective projection
2806
2807 fMat4 _projM; // projection matrix
2808
2809 RasterizerParams<color_t, color_t,ZBUFFER_t> _uni; // rasterizer param (contain the image pointer and the zbuffer pointer).
2810
2811 float _culling_dir; // culling direction postive/negative or 0 to disable back face culling.
2812
2813 int _shaders; // the shaders to use.
2814 int _texture_wrap_mode; // wrapping mode (wrap_pow2 or clamp)
2815 int _texture_quality; // texturing quality (nearest or bilinear)
2816
2817 // *** scene parameters ***
2818
2819 fMat4 _viewM; // view transform matrix
2820
2821 fVec3 _light[MAX_DIRECTIONAL_LIGHTS]; // directional light directions
2822 RGBf _ambiantColor; // light ambiant color
2823 RGBf _diffuseColor[MAX_DIRECTIONAL_LIGHTS]; // directional light diffuse colors
2824 RGBf _specularColor[MAX_DIRECTIONAL_LIGHTS]; // directional light specular colors
2825 int _directionalLightCount; // number of active directional lights
2826
2827
2828 // *** model specific parameters ***
2829
2830 fMat4 _modelM; // model transform matrix
2831
2832 // material parameters
2833 RGBf _color; // model color (use when texturing is disabled)
2834 float _ambiantStrength; // ambient light reflection strength
2835 float _diffuseStrength; // diffuse light reflection strength
2836 float _specularStrength; // specular light reflection strength
2837 int _specularExponent; // specular exponent
2838
2839
2840 // *** pre-computed values ***
2841 fMat4 _r_modelViewM; // model-view matrix
2842 float _r_inorm; // Fast normal scaling for lighting. Assumes rotation/uniform scale;
2843 // Gouraud lighting is approximate with non-uniform model scaling.
2844 fVec3 _r_light[MAX_DIRECTIONAL_LIGHTS]; // light vectors in view space (inverted and normalized)
2845 fVec3 _r_light_inorm[MAX_DIRECTIONAL_LIGHTS]; // same as above but already multiplied by inorm
2846 fVec3 _r_H[MAX_DIRECTIONAL_LIGHTS]; // halfway vectors.
2847 fVec3 _r_H_inorm[MAX_DIRECTIONAL_LIGHTS]; // same as above but already multiplied by inorm
2848 RGBf _r_ambiantColor; // ambient color multiplied by object ambient strength
2849 RGBf _r_diffuseColor[MAX_DIRECTIONAL_LIGHTS]; // diffuse colors multiplied by object diffuse strength
2850 RGBf _r_specularColor[MAX_DIRECTIONAL_LIGHTS]; // specular colors multiplied by object specular strength
2851 RGBf _r_objectColor; // color to use for drawing the object (either _color or mesh->color).
2852
2853
2857 struct ExtVec4 : public RasterizerVec4
2858 {
2859 fVec4 P; // after model-view matrix multiplication
2860 fVec4 N; // normal vector after model-view matrix multiplication
2861 bool missedP; // true if the attributes should be computed
2862 int indn; // index for normal vector in array
2863 int indt; // index for texture vector in array
2864 };
2865
2866
2867 };
2868
2869
2870
2871}
2872
2873
2874
2875
2876#include "Renderer3D.inl"
2877
2878
2879#endif
2880
2881#endif
2882
2883
2D box class
3D box class
Color classes [RGB565, RGB24, RGB32, RGB64, RGBf, HSV].
Main image class.
4x4 matrix class.
Mat4< float > fMat4
4x4 matrix with single (float) precision
Definition: Mat4.h:54
3D model mesh class.
Compact meshlet-based 3D model mesh format with 16-bit quantization.
Utility/miscellaneous functions used throughout the library.
TGX_INLINE T max(T a, T b)
Don't know why but much faster than fmaxf() for floats.
Definition: Misc.h:153
3D triangle rasterizer function.
#define TGX_RASTERIZE_SUBPIXEL_BITS
Sub-pixel precision bits.
Definition: Rasterizer.h:46
Shader
List of shaders available for 3D graphics.
Definition: ShaderParams.h:44
@ SHADER_NOTEXTURE
disable texture mapping
Definition: ShaderParams.h:59
@ SHADER_TEXTURE
enable texture mapping
Definition: ShaderParams.h:60
Triangle shader functions.
2D vector.
TGX_INLINE T dotProduct(const Vec2< T > &U, const Vec2< T > &V)
Return the dot product U.V between two vectors.
Definition: Vec2.h:554
3D vector.
Vec3< float > fVec3
Floating point valued 3D vector with single (float) precision.
Definition: Vec3.h:52
4D vector.
Vec4< float > fVec4
Floating point valued 4D vector with single (float) precision.
Definition: Vec4.h:54
Image class [MAIN CLASS FOR THE 2D API].
Definition: Image.h:145
Class for drawing 3D objects onto a Image [MAIN CLASS FOR THE 3D API].
Definition: Renderer3D.h:115
void drawQuads(int nb_quads, const uint16_t *ind_vertices, const fVec3 *vertices, const uint16_t *ind_normals=nullptr, const fVec3 *normals=nullptr, const uint16_t *ind_texture=nullptr, const fVec2 *textures=nullptr, const Image< color_t > *texture_image=nullptr)
Draw a collection of quads.
void drawAdaptativeSphere(float quality=1.0f)
Draw a unit radius sphere centered at the origin S(0,1) in model space.
void setTextureQuality(Shader quality)
Set the texturing quality.
void drawWireFrameSphereAA(int nb_sectors, int nb_stacks)
Draw a wireframe unit radius sphere [antialiased] with the current material color.
void drawPixels(int nb_pixels, const fVec3 *pos_list, const int *colors_ind, const color_t *colors, const int *opacities_ind, const float *opacities)
Draw a list of pixels at given positions in model space with different colors and opacities.
void drawWireFrameMesh(const Mesh3Dv2< color_t > *mesh)
Draw a Mesh3Dv2 object in wireframe [fast].
void drawWireFrameLines(int nb_lines, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw a collection of wireframe line segments [fast].
void drawWireFrameTriangleAA(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3)
Draw a wireframe triangle [antialiased] with the current material color.
void drawWireFrameLineAA(const fVec3 &P1, const fVec3 &P2)
Draw a wireframe line segment [antialiased] with the current material color.
void setDirectionalLightAmbiant(const RGBf &color)
Set the global ambiant light shared by all directional lights.
void drawQuadWithVertexColor(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 &P4, const RGBf &col1, const RGBf &col2, const RGBf &col3, const RGBf &col4, const fVec3 *N1=nullptr, const fVec3 *N2=nullptr, const fVec3 *N3=nullptr, const fVec3 *N4=nullptr)
Draw a single quad with a given colors on each of its four vertices.
void setLookAt(const fVec3 eye, const fVec3 center, const fVec3 up)
Set the view matrix so that the camera is looking at a given direction.
void drawWireFrameAdaptativeSphere(float quality=1.0f)
Draw a wireframe unit radius sphere centered at the origin (in model space) [fast].
void drawWireFrameCubeAA()
Draw the wireframe cube [0,1]^3 [antialiased] with the current material color.
void drawAdaptativeSphere(const Image< color_t > *texture, float quality=1.0f)
Draw a textured unit radius sphere centered at the origin S(0,1) in model space.
void drawWireFrameLine(const fVec3 &P1, const fVec3 &P2, float thickness, color_t color, float opacity)
Draw a wireframe line segment [adjustable thickness + AA].
void setDirectionalLight(int index, const fVec3 &direction, const RGBf &diffuseColor, const RGBf &specularColor)
Configure one directional light at once.
void drawWireFrameTriangle(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3)
Draw a wireframe triangle [fast].
void setLightDiffuse(const RGBf &color)
Set the diffuse light color of the main directional light of the scene.
void drawCube(const Image< color_t > *texture_front, const Image< color_t > *texture_back, const Image< color_t > *texture_top, const Image< color_t > *texture_bottom, const Image< color_t > *texture_left, const Image< color_t > *texture_right)
draw a textured unit cube [-1,1]^3 (in model space)
void drawWireFrameMesh(const Mesh3D< color_t > *mesh, bool draw_chained_meshes=true)
Draw a mesh in wireframe [fast].
void setLightDirection(const fVec3 &direction)
Set the light source direction of the main directional light of the scene.
void setZbuffer(ZBUFFER_t *zbuffer)
Set the z-buffer.
void drawSkyBox(const fVec2 v_front_ABCD[4], const Image< color_t > *texture_front, const fVec2 v_back_EFGH[4], const Image< color_t > *texture_back, const fVec2 v_top_HADE[4], const Image< color_t > *texture_top, const fVec2 v_bottom_BGFC[4], const Image< color_t > *texture_bottom, const fVec2 v_left_HGBA[4], const Image< color_t > *texture_left, const fVec2 v_right_DCFE[4], const Image< color_t > *texture_right, float rot_angle_y=0.0f, float reference_height=0.0f, float skybox_radius=32768.0f, Shader texture_quality=SHADER_TEXTURE_NEAREST, Shader texture_mode=SHADER_TEXTURE_CLAMP)
Draw a textured sky-box around the current camera.
void drawPixels(int nb_pixels, const fVec3 *pos_list)
Draw a list of pixels at given positions in model space.
void drawWireFrameMeshAA(const Mesh3Dv2< color_t > *mesh)
Draw a Mesh3Dv2 object in wireframe [antialiased] with the current material color.
TGX_NOINLINE Renderer3D(const iVec2 &viewportSize={0, 0}, Image< color_t > *im=nullptr, ZBUFFER_t *zbuffer=nullptr)
Constructor.
void setProjectionMatrix(const fMat4 &M)
Set the projection matrix.
void drawCube()
Draw the unit cube [-1,1]^3 in model space.
fMat4 getProjectionMatrix() const
Return the current projection matrix.
void drawWireFrameCube(float thickness, color_t color, float opacity)
Draw the wireframe cube [0,1]^3 (in model space) [adjustable thickness + AA].
void drawMesh(const Mesh3Dv2< color_t > *mesh, bool use_mesh_material=true)
Draw a Mesh3Dv2 object.
void setDirectionalLightSpecular(int index, const RGBf &color)
Set the specular color of one directional light.
iVec2 modelToImage(fVec3 P)
Convert from model coordinates to the corresponding image pixel.
void setShaders(Shader shaders)
Set the shaders to use for subsequent drawing operations.
void drawPixel(const fVec3 &pos, color_t color, float opacity)
Draw a single pixel at a given position in model space.
iVec2 worldToImage(fVec3 P)
Convert from world coordinates to the corresponding image pixel.
void drawWireFrameQuad(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 &P4, float thickness, color_t color, float opacity)
Draw a wireframe quad [adjustable thickness + AA].
void setMaterialDiffuseStrength(float strenght=0.6f)
Set how much the object material reflects the diffuse light.
void drawWireFrameQuadsAA(int nb_quads, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw wireframe quads [antialiased] with the current material color.
void setLightAmbiant(const RGBf &color)
Set the scene ambiant light color.
void drawWireFrameAdaptativeSphereAA(float quality=1.0f)
Draw an adaptive wireframe sphere [antialiased] with the current material color.
void setImage(Image< color_t > *im)
Set the image that will be drawn onto.
void drawWireFrameCube()
Draw the wireframe cube [0,1]^3 (in model space) [fast].
void drawWireFrameTriangleStrip(int nb_indices, const uint16_t *ind_vertices, const fVec3 *vertices, float thickness, color_t color, float opacity)
Draw a triangle strip in wireframe [adjustable thickness + AA].
void drawWireFrameMesh(const Mesh3D< color_t > *mesh, bool draw_chained_meshes, float thickness, color_t color, float opacity)
Draw a mesh in wireframe [adjustable thickness + AA].
void setTextureWrappingMode(Shader wrap_mode)
Set the wrap mode when for texturing.
void setViewportSize(int lx, int ly)
Set the size of the viewport.
fMat4 getViewMatrix() const
Return the current view matrix.
void setDirectionalLightCount(int count)
Set the number of active directional lights.
void drawWireFrameTriangle(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, float thickness, color_t color, float opacity)
Draw a wireframe triangle [adjustable thickness + AA].
void setViewportSize(const iVec2 &viewport_dim)
Set the size of the viewport.
void setOrtho(float left, float right, float bottom, float top, float zNear, float zFar)
Set the projection matrix as an orthographic matrix.
void drawTriangleWithVertexColor(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const RGBf &col1, const RGBf &col2, const RGBf &col3, const fVec3 *N1=nullptr, const fVec3 *N2=nullptr, const fVec3 *N3=nullptr)
Draw a single triangle with a given colors on each of its vertices.
void drawWireFrameLines(int nb_lines, const uint16_t *ind_vertices, const fVec3 *vertices, float thickness, color_t color, float opacity)
Draw a collection of wireframe line segments [adjustable thickness + AA].
fMat4 getModelMatrix() const
Return the model transformation matrix.
void setMaterialSpecularStrength(float strenght=0.5f)
Set how much the object material reflects the specular light.
void drawSphere(int nb_sectors, int nb_stacks, const Image< color_t > *texture)
Draw a textured unit radius sphere centered at the origin S(0,1) in model space.
void setModelMatrix(const fMat4 &M)
Set the model transformation matrix.
void drawWireFrameMeshAA(const Mesh3D< color_t > *mesh, bool draw_chained_meshes=true)
Draw a mesh in wireframe [antialiased] with the current material color.
void drawSkyBox(const Image< color_t > *texture_front, const Image< color_t > *texture_back, const Image< color_t > *texture_top, const Image< color_t > *texture_bottom, const Image< color_t > *texture_left, const Image< color_t > *texture_right, float rot_angle_y=0.0f, float reference_height=0.0f, float skybox_radius=32768.0f, Shader texture_quality=SHADER_TEXTURE_NEAREST, Shader texture_mode=SHADER_TEXTURE_CLAMP)
Draw a textured sky-box using whole images for each face.
void drawDots(int nb_dots, const fVec3 *pos_list, const int *radius_ind, const int *radius, const int *colors_ind, const color_t *colors, const int *opacities_ind, const float *opacities)
Draw a list of dots/circles at given positions in model space.
void setFrustum(float left, float right, float bottom, float top, float zNear, float zFar)
Set the projection matrix as a perspective matrix.
void drawWireFrameSphere(int nb_sectors, int nb_stacks)
Draw a wireframe unit radius sphere centered at the origin (in model space) [fast].
void setOffset(const iVec2 &offset)
Set the offset of the image relative to the viewport.
void setPerspective(float fovy, float aspect, float zNear, float zFar)
Set the projection matrix as a perspective matrix.
void drawWireFrameLine(const fVec3 &P1, const fVec3 &P2)
Draw a wireframe line segment [fast].
void drawWireFrameQuad(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 &P4)
Draw a wireframe quad [fast].
void setOffset(int ox, int oy)
Set the offset of the image relative to the viewport.
void drawMesh(const Mesh3D< color_t > *mesh, bool use_mesh_material=true, bool draw_chained_meshes=true)
Draw a Mesh3D object.
void drawWireFrameTrianglesAA(int nb_triangles, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw wireframe triangles [antialiased] with the current material color.
void drawTriangle(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 *N1=nullptr, const fVec3 *N2=nullptr, const fVec3 *N3=nullptr, const fVec2 *T1=nullptr, const fVec2 *T2=nullptr, const fVec2 *T3=nullptr, const Image< color_t > *texture=nullptr)
Draw a single triangle.
void drawCube(const fVec2 v_front_ABCD[4], const Image< color_t > *texture_front, const fVec2 v_back_EFGH[4], const Image< color_t > *texture_back, const fVec2 v_top_HADE[4], const Image< color_t > *texture_top, const fVec2 v_bottom_BGFC[4], const Image< color_t > *texture_bottom, const fVec2 v_left_HGBA[4], const Image< color_t > *texture_left, const fVec2 v_right_DCFE[4], const Image< color_t > *texture_right)
Draw a textured unit cube [-1,1]^3 in model space.
void drawDot(const fVec3 &pos, int r, color_t color, float opacity)
Draw a dot/circle at a given position in model space.
void drawWireFrameTriangles(int nb_triangles, const uint16_t *ind_vertices, const fVec3 *vertices, float thickness, color_t color, float opacity)
Draw a collection of wireframe triangles [adjustable thickness + AA].
fVec4 modelToNDC(fVec3 P)
Convert from model coordinates to normalized device coordinates (NDC).
void drawQuad(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 &P4, const fVec3 *N1=nullptr, const fVec3 *N2=nullptr, const fVec3 *N3=nullptr, const fVec3 *N4=nullptr, const fVec2 *T1=nullptr, const fVec2 *T2=nullptr, const fVec2 *T3=nullptr, const fVec2 *T4=nullptr, const Image< color_t > *texture=nullptr)
Draw a single quad.
void usePerspectiveProjection()
Set projection mode to perspective (ie with z-divide).
void setMaterialAmbiantStrength(float strenght=0.1f)
Set how much the object material reflects the ambient light.
void setDirectionalLightDiffuse(int index, const RGBf &color)
Set the diffuse color of one directional light.
void setMaterialSpecularExponent(int exponent=16)
Set the object specular exponent.
void setModelPosScaleRot(const fVec3 &center=fVec3{ 0, 0, 0 }, const fVec3 &scale=fVec3(1, 1, 1), float rot_angle=0, const fVec3 &rot_dir=fVec3{ 0, 1, 0 })
Set the model transformation matrix to move an object to a given location, scale and rotation.
void setCulling(int w)
Set the face culling strategy.
void drawWireFrameLinesAA(int nb_lines, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw wireframe line segments [antialiased] with the current material color.
void useOrthographicProjection()
Set projection mode to orthographic (ie no z-divide).
void drawTriangleStrip(int nb_indices, const uint16_t *ind_vertices, const fVec3 *vertices, const uint16_t *ind_normals=nullptr, const fVec3 *normals=nullptr, const uint16_t *ind_texture=nullptr, const fVec2 *textures=nullptr, const Image< color_t > *texture_image=nullptr)
Draw a triangle strip.
void setDirectionalLightDirection(int index, const fVec3 &direction)
Set the direction of one directional light.
void setViewMatrix(const fMat4 &M)
Set the view transformation matrix.
void drawWireFrameTriangleStrip(int nb_indices, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw a triangle strip in wireframe [fast].
void clearZbuffer()
Clear the Zbuffer.
void setMaterialColor(RGBf color)
Set the object material color.
fVec4 worldToNDC(fVec3 P)
Convert from world coordinates to normalized device coordinates (NDC).
void drawPixel(const fVec3 &pos)
Draw a single pixel at a given position in model space.
void drawWireFrameTriangleStripAA(int nb_indices, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw a triangle strip in wireframe [antialiased] with the current material color.
void drawSphere(int nb_sectors, int nb_stacks)
Draw a unit radius sphere centered at the origin S(0,1) in model space.
void drawDot(const fVec3 &pos, int r)
Draw a dot/circle at a given position in model space.
void drawWireFrameQuads(int nb_quads, const uint16_t *ind_vertices, const fVec3 *vertices, float thickness, color_t color, float opacity)
Draw a collection of wireframe quads [adjustable thickness + AA].
void setLight(const fVec3 direction, const RGBf &ambiantColor, const RGBf &diffuseColor, const RGBf &specularColor)
Set all lighting parameters of the main directional light of the scene at once.
void drawWireFrameAdaptativeSphere(float quality, float thickness, color_t color, float opacity)
Draw a wireframe unit radius sphere centered at the origin (in model space) [adjustable thickness + A...
void setMaterial(RGBf color, float ambiantStrength, float diffuseStrength, float specularStrength, int specularExponent)
Set all the object material properties at once.
static constexpr int maxDirectionalLightCount()
Return the compile-time directional-light capacity.
Definition: Renderer3D.h:658
void setLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
Set the view matrix so that the camera is looking at a given direction.
void setLightSpecular(const RGBf &color)
Set the specular light color of the main directional light of the scene.
void drawWireFrameQuads(int nb_quads, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw a collection of wireframe quads [fast].
void drawWireFrameTriangles(int nb_triangles, const uint16_t *ind_vertices, const fVec3 *vertices)
Draw a collection of wireframe triangles [fast].
void drawWireFrameSphere(int nb_sectors, int nb_stacks, float thickness, color_t color, float opacity)
Draw a wireframe unit radius sphere centered at the origin (in model space) [adjustable thickness + A...
int directionalLightCount() const
Return the number of active directional lights.
void drawWireFrameMesh(const Mesh3Dv2< color_t > *mesh, float thickness, color_t color, float opacity)
Draw a Mesh3Dv2 object in wireframe [adjustable thickness + AA].
void drawWireFrameQuadAA(const fVec3 &P1, const fVec3 &P2, const fVec3 &P3, const fVec3 &P4)
Draw a wireframe quad [antialiased] with the current material color.
void drawTriangles(int nb_triangles, const uint16_t *ind_vertices, const fVec3 *vertices, const uint16_t *ind_normals=nullptr, const fVec3 *normals=nullptr, const uint16_t *ind_texture=nullptr, const fVec2 *textures=nullptr, const Image< color_t > *texture_image=nullptr)
Draw a collection of triangles.
void drawDots(int nb_dots, const fVec3 *pos_list, const int radius)
Draw a list of dots/circles at given positions in model space.
TGX_INLINE Vec4< T > mult1(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 1)
Definition: Mat4.h:578
TGX_INLINE Vec4< T > mult0(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 0).
Definition: Mat4.h:557
3D mesh data structure.
Definition: Mesh3D.h:157
Compact meshlet-based 3D mesh data structure.
Definition: Mesh3Dv2.h:239
Color in R,G,B float format.
Definition: Color.h:2405
TGX_INLINE void clamp()
Clamp all color channel to [0.0f,1.0f].
Definition: Color.h:2645
Generic 2D vector [specializations iVec2, fVec2, dVec2].
Definition: Vec2.h:64
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
T y
'y' coordinate (second dimension)
Definition: Vec2.h:73
T z
'z' coordinate (third dimension)
Definition: Vec3.h:83
void normalize()
Normalise the vector so that its norm is 1 (do nothing if the vector is 0).
Definition: Vec3.h:382
T w
'w' coordinate (fourth dimension)
Definition: Vec4.h:85
TGX_INLINE_ZDIVIDE void zdivide()
Performs the 'z-divide' operation.
Definition: Vec4.h:478