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
115 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>
117 {
118
119
120 static constexpr int MAXVIEWPORTDIMENSION = 2048 * (1 << ((8 - TGX_RASTERIZE_SUBPIXEL_BITS) >> 1));
121
122 static_assert(is_color<color_t>::value, "color_t must be one of the color types defined in color.h");
123 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");
124 static_assert(MAX_DIRECTIONAL_LIGHTS >= 1, "MAX_DIRECTIONAL_LIGHTS must be at least 1");
125 static_assert(MAX_SPOT_LIGHTS >= 0, "MAX_SPOT_LIGHTS must be non-negative");
126
127 // true if some kind of texturing may be used.
128 static constexpr int ENABLE_TEXTURING = (TGX_SHADER_HAS_ONE_FLAG(LOADED_SHADERS , (SHADER_TEXTURE | SHADER_TEXTURE_AFFINE | TGX_SHADER_MASK_TEXTURE_MODE | TGX_SHADER_MASK_TEXTURE_QUALITY)));
129 static constexpr int EXPLICIT_TEXTURE_MODE = (TGX_SHADER_HAS_TEXTURING_ENABLED(LOADED_SHADERS));
130 static constexpr Shader DEFAULT_TEXTURE_MODE = EXPLICIT_TEXTURE_MODE ? (Shader)0 : SHADER_TEXTURE;
131
132 static constexpr Shader ENABLED_SHADERS = LOADED_SHADERS | (ENABLE_TEXTURING ? DEFAULT_TEXTURE_MODE : SHADER_NOTEXTURE); // enable perspective texturing by default when only texturing options are set
133 // check that disabled shaders do not completely disable all drawing operations.
134 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");
135 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");
136 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");
137 static_assert(TGX_SHADER_HAS_ONE_FLAG(ENABLED_SHADERS,TGX_SHADER_MASK_TEXTURE), "At least one of the shaders SHADER_NOTEXTURE, SHADER_TEXTURE or SHADER_TEXTURE_AFFINE must be enabled");
138 static_assert((!TGX_SHADER_HAS_TEXTURING_ENABLED(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");
139 static_assert((!TGX_SHADER_HAS_TEXTURING_ENABLED(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");
140
141
142
143 public:
144
145
155 TGX_NOINLINE Renderer3D(const iVec2& viewportSize = {0,0}, Image<color_t> * im = nullptr, ZBUFFER_t * zbuffer = nullptr);
156
157
158
159
160 /*****************************************************************************************
161 *****************************************************************************************/
168 /*****************************************************************************************
169 ******************************************************************************************/
170
171
192 void setViewportSize(int lx, int ly);
193
194
202 void setViewportSize(const iVec2& viewport_dim);
203
204
217
218
237 void setOffset(int ox, int oy);
238
239
247 void setOffset(const iVec2& offset);
248
249
268
269
276
277
284
285
292
293
310 void setOrtho(float left, float right, float bottom, float top, float zNear, float zFar);
311
312
329 void setFrustum(float left, float right, float bottom, float top, float zNear, float zFar);
330
331
349 void setPerspective(float fovy, float aspect, float zNear, float zFar);
350
351
369 void setCulling(int w);
370
371
384 void setZbuffer(ZBUFFER_t* zbuffer);
385
386
396
397
445 void setShaders(Shader shaders);
446
447
456
457
466
467
468
470 /*****************************************************************************************
471 *****************************************************************************************/
478 /*****************************************************************************************
479 ******************************************************************************************/
480
481
482
499 void setViewMatrix(const fMat4& M);
500
501
510
511
523 void setLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
524
525
537 void setLookAt(const fVec3 eye, const fVec3 center, const fVec3 up);
538
539
553
554
567
568
569
581 void setLightAmbiant(const RGBf& color);
582
595 void setLightDirection(const fVec3& direction);
596
597
598
599
612 void setLightDiffuse(const RGBf& color);
613
614
627 void setLightSpecular(const RGBf& color);
628
629
645 void setLight(const fVec3 direction, const RGBf& ambiantColor, const RGBf& diffuseColor, const RGBf& specularColor);
646
647
660
661
666
667
671 static constexpr int maxDirectionalLightCount() { return MAX_DIRECTIONAL_LIGHTS; }
672
673
684
685
695 void setDirectionalLightDirection(int index, const fVec3& direction);
696
697
706 void setDirectionalLightDiffuse(int index, const RGBf& color);
707
708
717 void setDirectionalLightSpecular(int index, const RGBf& color);
718
719
731 void setDirectionalLight(int index, const fVec3& direction, const RGBf& diffuseColor, const RGBf& specularColor);
732
733
734
735
736
738 /*****************************************************************************************
739 *****************************************************************************************/
746 /*****************************************************************************************
747 ******************************************************************************************/
748
749
750
761 void setModelMatrix(const fMat4& M);
762
763
772
773
795 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 });
796
797
809
810
823
824
836
837
846 void setMaterialAmbiantStrength(float strenght = 0.1f);
847
848
857 void setMaterialDiffuseStrength(float strenght = 0.6f);
858
859
868 void setMaterialSpecularStrength(float strenght = 0.5f);
869
870
881 void setMaterialSpecularExponent(int exponent = 16);
882
883
896 void setMaterial(RGBf color, float ambiantStrength, float diffuseStrength, float specularStrength, int specularExponent);
897
898
899
900
901
902
903
904
906 /*****************************************************************************************
907 *****************************************************************************************/
921 /*****************************************************************************************
922 ******************************************************************************************/
923
924
925
942 void drawMesh(const Mesh3D<color_t>* mesh, bool use_mesh_material = true, bool draw_chained_meshes = true);
943
944
957 void drawMesh(const Mesh3Dv2<color_t>* mesh, bool use_mesh_material = true);
958
959
973 void drawTriangle(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3,
974 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr,
975 const fVec2 * T1 = nullptr, const fVec2 * T2 = nullptr, const fVec2 * T3 = nullptr,
976 const Image<color_t> * texture = nullptr);
977
978
991 void drawTriangleWithVertexColor(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3,
992 const RGBf & col1, const RGBf & col2, const RGBf & col3,
993 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr);
994
995
1014 void drawTriangles(int nb_triangles,
1015 const uint16_t * ind_vertices, const fVec3 * vertices,
1016 const uint16_t * ind_normals = nullptr, const fVec3* normals = nullptr,
1017 const uint16_t * ind_texture = nullptr, const fVec2* textures = nullptr,
1018 const Image<color_t> * texture_image = nullptr);
1019
1020
1043 void drawTriangleStrip(int nb_indices,
1044 const uint16_t* ind_vertices, const fVec3* vertices,
1045 const uint16_t* ind_normals = nullptr, const fVec3* normals = nullptr,
1046 const uint16_t* ind_texture = nullptr, const fVec2* textures = nullptr,
1047 const Image<color_t>* texture_image = nullptr);
1048
1049
1050
1066 void drawQuad(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3, const fVec3 & P4,
1067 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr, const fVec3 * N4 = nullptr,
1068 const fVec2 * T1 = nullptr, const fVec2 * T2 = nullptr, const fVec2 * T3 = nullptr, const fVec2 * T4 = nullptr,
1069 const Image<color_t>* texture = nullptr);
1070
1071
1072
1088 void drawQuadWithVertexColor(const fVec3 & P1, const fVec3 & P2, const fVec3 & P3, const fVec3 & P4,
1089 const RGBf & col1, const RGBf & col2, const RGBf & col3, const RGBf & col4,
1090 const fVec3 * N1 = nullptr, const fVec3 * N2 = nullptr, const fVec3 * N3 = nullptr, const fVec3 * N4 = nullptr);
1091
1092
1093
1094
1115 void drawQuads(int nb_quads,
1116 const uint16_t * ind_vertices, const fVec3 * vertices,
1117 const uint16_t * ind_normals = nullptr, const fVec3* normals = nullptr,
1118 const uint16_t * ind_texture = nullptr, const fVec2* textures = nullptr,
1119 const Image<color_t>* texture_image = nullptr);
1120
1121
1122
1123
1125 /*****************************************************************************************
1126 *****************************************************************************************/
1133 /*****************************************************************************************
1134 ******************************************************************************************/
1135
1136
1137
1144 void drawCube();
1145
1146
1188 const fVec2 v_front_ABCD[4] , const Image<color_t>* texture_front,
1189 const fVec2 v_back_EFGH[4] , const Image<color_t>* texture_back,
1190 const fVec2 v_top_HADE[4] , const Image<color_t>* texture_top,
1191 const fVec2 v_bottom_BGFC[4], const Image<color_t>* texture_bottom,
1192 const fVec2 v_left_HGBA[4] , const Image<color_t>* texture_left,
1193 const fVec2 v_right_DCFE[4] , const Image<color_t>* texture_right
1194 );
1195
1196
1232 const Image<color_t>* texture_front,
1233 const Image<color_t>* texture_back,
1234 const Image<color_t>* texture_top,
1235 const Image<color_t>* texture_bottom,
1236 const Image<color_t>* texture_left,
1237 const Image<color_t>* texture_right
1238 );
1239
1240
1300 const fVec2 v_front_ABCD[4] , const Image<color_t>* texture_front,
1301 const fVec2 v_back_EFGH[4] , const Image<color_t>* texture_back,
1302 const fVec2 v_top_HADE[4] , const Image<color_t>* texture_top,
1303 const fVec2 v_bottom_BGFC[4], const Image<color_t>* texture_bottom,
1304 const fVec2 v_left_HGBA[4] , const Image<color_t>* texture_left,
1305 const fVec2 v_right_DCFE[4] , const Image<color_t>* texture_right,
1306 float rot_angle_y = 0.0f,
1307 float reference_height = 0.0f,
1308 float skybox_radius = 32768.0f,
1309 Shader texture_quality = SHADER_TEXTURE_NEAREST,
1310 Shader texture_mode = SHADER_TEXTURE_CLAMP
1311 );
1312
1313
1320 const Image<color_t>* texture_front,
1321 const Image<color_t>* texture_back,
1322 const Image<color_t>* texture_top,
1323 const Image<color_t>* texture_bottom,
1324 const Image<color_t>* texture_left,
1325 const Image<color_t>* texture_right,
1326 float rot_angle_y = 0.0f,
1327 float reference_height = 0.0f,
1328 float skybox_radius = 32768.0f,
1329 Shader texture_quality = SHADER_TEXTURE_NEAREST,
1330 Shader texture_mode = SHADER_TEXTURE_CLAMP
1331 );
1332
1333
1334
1345 void drawSphere(int nb_sectors, int nb_stacks);
1346
1347
1360 void drawSphere(int nb_sectors, int nb_stacks, const Image<color_t>* texture);
1361
1362
1377 void drawAdaptativeSphere(float quality = 1.0f);
1378
1379
1397 void drawAdaptativeSphere(const Image<color_t>* texture, float quality = 1.0f);
1398
1399
1400
1401
1402
1403
1404
1405
1407 /*****************************************************************************************
1408 *****************************************************************************************/
1423 /*****************************************************************************************
1424 ******************************************************************************************/
1425
1426
1427
1439 void drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes = true);
1440
1441
1454
1455
1466 void drawWireFrameMeshAA(const Mesh3D<color_t>* mesh, bool draw_chained_meshes = true);
1467
1468
1479
1480
1497 void drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes, float thickness, color_t color, float opacity);
1498
1499
1516 void drawWireFrameMesh(const Mesh3Dv2<color_t>* mesh, float thickness, color_t color, float opacity);
1517
1518
1528 void drawWireFrameLine(const fVec3& P1, const fVec3& P2);
1529
1530
1540 void drawWireFrameLineAA(const fVec3& P1, const fVec3& P2);
1541
1542
1555 void drawWireFrameLine(const fVec3& P1, const fVec3& P2, float thickness, color_t color, float opacity);
1556
1557
1569 void drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices);
1570
1571
1583 void drawWireFrameLinesAA(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices);
1584
1585
1600 void drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1601
1602
1613 void drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3);
1614
1615
1625 void drawWireFrameTriangleAA(const fVec3& P1, const fVec3& P2, const fVec3& P3);
1626
1627
1642 void drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3, float thickness, color_t color, float opacity);
1643
1644
1657 void drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices);
1658
1659
1671 void drawWireFrameTrianglesAA(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices);
1672
1673
1690 void drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1691
1692
1707 void drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices);
1708
1709
1723 void drawWireFrameTriangleStripAA(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices);
1724
1725
1744 void drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1745
1746
1758 void drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4);
1759
1760
1770 void drawWireFrameQuadAA(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4);
1771
1772
1788 void drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4, float thickness, color_t color, float opacity);
1789
1790
1804 void drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices);
1805
1806
1818 void drawWireFrameQuadsAA(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices);
1819
1820
1838 void drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices, float thickness, color_t color, float opacity);
1839
1840
1841
1842
1844 /*****************************************************************************************
1845 *****************************************************************************************/
1860 /*****************************************************************************************
1861 ******************************************************************************************/
1862
1863
1872
1873
1882
1883
1897 void drawWireFrameCube(float thickness, color_t color, float opacity);
1898
1899
1911 void drawWireFrameSphere(int nb_sectors, int nb_stacks);
1912
1913
1924 void drawWireFrameSphereAA(int nb_sectors, int nb_stacks);
1925
1926
1943 void drawWireFrameSphere(int nb_sectors, int nb_stacks, float thickness, color_t color, float opacity);
1944
1945
1959 void drawWireFrameAdaptativeSphere(float quality = 1.0f);
1960
1961
1971 void drawWireFrameAdaptativeSphereAA(float quality = 1.0f);
1972
1973
1992 void drawWireFrameAdaptativeSphere(float quality, float thickness, color_t color, float opacity);
1993
1994
1995
1996
1997
1999 /*****************************************************************************************
2000 *****************************************************************************************/
2009 /*****************************************************************************************
2010 ******************************************************************************************/
2011
2012
2013
2023 void drawPixel(const fVec3& pos);
2024
2025
2037 void drawPixel(const fVec3& pos, color_t color, float opacity);
2038
2039
2050 void drawPixels(int nb_pixels, const fVec3* pos_list);
2051
2052
2067 void drawPixels(int nb_pixels, const fVec3* pos_list, const int* colors_ind, const color_t* colors, const int* opacities_ind, const float* opacities);
2068
2069
2080 void drawDot(const fVec3& pos, int r);
2081
2082
2083
2096 void drawDot(const fVec3& pos, int r, color_t color, float opacity);
2097
2098
2110 void drawDots(int nb_dots, const fVec3* pos_list, const int radius);
2111
2112
2130 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);
2131
2132
2133
2134
2135
2137
2138
2139
2140
2141
2142 private:
2143
2144
2145
2146 /*****************************************************************************************
2147 ******************************************************************************************
2148 *
2149 * BE CAREFUL PAST THIS POINT... FOR HERE BE DRAGONS !
2150 *
2151 ******************************************************************************************
2152 ******************************************************************************************/
2153
2154
2156 TGX_INLINE float _clipbound_xy() const
2157 {
2158 return (256 + 3*((MAXVIEWPORTDIMENSION * 256) / ((_lx > _ly) ? _lx : _ly))) / 1024.0f; // use integer computation up to the last divide
2159 //return (1.0f + 3.0f * (((float)MAXVIEWPORTDIMENSION) / ((_lx > _ly) ? _lx : _ly))) / 4.0f;
2160 }
2161
2162
2164 TGX_INLINE bool _validDraw() const
2165 {
2166 return ((_lx > 0) && (_ly > 0) && (_uni.im != nullptr) && (_uni.im->isValid()));
2167 }
2168
2169
2171 TGX_NOINLINE void _recompute_wa_wb();
2172
2173
2174 /***********************************************************
2175 * Making sure shader flags are coherent
2176 ************************************************************/
2177
2178 TGX_NOINLINE void _rectifyShaderOrtho();
2179
2180
2181 TGX_NOINLINE void _rectifyShaderZbuffer();
2182
2183
2184 TGX_NOINLINE void _rectifyShaderShading(Shader new_shaders);
2185
2186
2187 TGX_NOINLINE void _rectifyShaderTextureMode();
2188
2189
2190 TGX_NOINLINE void _rectifyShaderTextureWrapping();
2191
2192
2193 TGX_NOINLINE void _rectifyShaderTextureQuality();
2194
2195
2196 /***********************************************************
2197 * DRAWING STUFF
2198 ************************************************************/
2199
2200
2202 void _drawTriangleClipped(const int RASTER_TYPE,
2203 const fVec4* Q0, const fVec4* Q1, const fVec4* Q2,
2204 const fVec3* N0, const fVec3* N1, const fVec3* N2,
2205 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2206 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2);
2207
2208
2210 void _drawTriangleClippedSub(const int RASTER_TYPE, const int plane,
2211 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3);
2212
2213
2215 void _drawTriangle(const int RASTER_TYPE,
2216 const fVec3* P0, const fVec3* P1, const fVec3* P2,
2217 const fVec3* N0, const fVec3* N1, const fVec3* N2,
2218 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2219 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2);
2220
2221
2223 void _drawTriangleStrip(const int RASTER_TYPE, int nb_indices,
2224 const uint16_t* ind_vertices, const fVec3* vertices,
2225 const uint16_t* ind_normals, const fVec3* normals,
2226 const uint16_t* ind_texture, const fVec2* textures);
2227
2228
2230 void _drawQuad(const int RASTER_TYPE,
2231 const fVec3* P0, const fVec3* P1, const fVec3* P2, const fVec3* P3,
2232 const fVec3* N0, const fVec3* N1, const fVec3* N2, const fVec3* N3,
2233 const fVec2* T0, const fVec2* T1, const fVec2* T2, const fVec2* T3,
2234 const RGBf& Vcol0, const RGBf& Vcol1, const RGBf& Vcol2, const RGBf& Vcol3);
2235
2237 template<bool TEXTURE_BILINEAR, bool TEXTURE_WRAP>
2238 void _rasterizeSkyBoxTriangle(const RasterizerVec4& V0, const RasterizerVec4& V1, const RasterizerVec4& V2);
2239
2241 void _rasterizeSkyBoxTriangle(const RasterizerVec4& V0, const RasterizerVec4& V1, const RasterizerVec4& V2,
2242 Shader texture_quality, Shader texture_mode);
2243
2245 void _drawSkyBoxTriangleClippedSub(const int plane,
2246 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2247 Shader texture_quality, Shader texture_mode);
2248
2250 void _drawSkyBoxTriangleClipped(
2251 const fVec4* Q0, const fVec4* Q1, const fVec4* Q2,
2252 const fVec2* T0, const fVec2* T1, const fVec2* T2,
2253 Shader texture_quality, Shader texture_mode);
2254
2256 void _drawSkyBoxQuad(
2257 const fVec4* P0, const fVec4* P1, const fVec4* P2, const fVec4* P3,
2258 const fVec2* T0, const fVec2* T1, const fVec2* T2, const fVec2* T3,
2259 Shader texture_quality, Shader texture_mode);
2260
2262 void _drawSkyBoxFace(const fVec4 skybox_vertices[8], const uint16_t* face, const fVec2 texture_coords[4], const Image<color_t>* texture,
2263 Shader texture_quality, Shader texture_mode);
2264
2265
2267 void _drawMesh(const int RASTER_TYPE, const Mesh3D<color_t>* mesh);
2268
2270 void _drawMesh(const int RASTER_TYPE, const Mesh3Dv2<color_t>* mesh, bool use_mesh_material);
2271
2273 TGX_INLINE inline bool _discardMeshlet16b(const fVec3& sphere_center, float sphere_radius, const fVec3& cone_dir, float cone_cos) const
2274 {
2275 if (cone_cos <= -1.0f) return false;
2276
2277 const fVec4 D = _r_modelViewM.mult0(cone_dir);
2278 const float dd = D.x * D.x + D.y * D.y + D.z * D.z;
2279 if (dd <= 1.0e-20f) return false;
2280
2281 float dot;
2282 float len2;
2283 if (_ortho)
2284 {
2285 dot = D.z; // object-to-camera direction is +Z in view space.
2286 len2 = dd;
2287 }
2288 else
2289 {
2290 const fVec3 anchor = sphere_center - (cone_dir * sphere_radius);
2291 const fVec4 A = _r_modelViewM.mult1(anchor);
2292 dot = -(D.x * A.x + D.y * A.y + D.z * A.z);
2293 const float aa = A.x * A.x + A.y * A.y + A.z * A.z;
2294 if (aa <= 1.0e-20f) return false;
2295 len2 = dd * aa;
2296 }
2297
2298 const float c2len2 = cone_cos * cone_cos * len2;
2299 const float dot2 = dot * dot;
2300 return (cone_cos >= 0.0f) ? ((dot < 0.0f) || (dot2 < c2len2))
2301 : ((dot < 0.0f) && (dot2 > c2len2));
2302 }
2303
2304
2305
2306 /***********************************************************
2307 * Drawing wireframe
2308 ************************************************************/
2309
2310 inline void _drawWireFrameLineFast(iVec2 P0, iVec2 P1, color_t color);
2311
2312 template<bool CHECK_NEIGHBOR> inline void _drawWireFrameLineAAFast(const fVec2& P0, const fVec2& P1, color_t color, int32_t op);
2313
2314 template<int MODE> void _drawWireFrameMesh(const Mesh3D<color_t>* mesh, bool draw_chained_meshes, color_t color, float opacity, float thickness);
2315
2316 template<int MODE> void _drawWireFrameMesh(const Mesh3Dv2<color_t>* mesh, color_t color, float opacity, float thickness);
2317
2318 template<int MODE> void _drawWireFrameLine(const fVec3& P1, const fVec3& P2, color_t color, float opacity, float thickness);
2319
2320 template<int MODE> void _drawWireFrameLines(int nb_lines, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2321
2322 template<int MODE> void _drawWireFrameTriangle(const fVec3& P1, const fVec3& P2, const fVec3& P3, color_t color, float opacity, float thickness);
2323
2324 template<int MODE> void _drawWireFrameTriangles(int nb_triangles, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2325
2326 template<int MODE> void _drawWireFrameTriangleStrip(int nb_indices, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2327
2328 template<int MODE> void _drawWireFrameQuad(const fVec3& P1, const fVec3& P2, const fVec3& P3, const fVec3& P4, color_t color, float opacity, float thickness);
2329
2330 template<int MODE> void _drawWireFrameQuads(int nb_quads, const uint16_t* ind_vertices, const fVec3* vertices, color_t color, float opacity, float thickness);
2331
2332
2333
2334
2335 /***********************************************************
2336 * Simple geometric objects
2337 ************************************************************/
2338
2339
2340 template<bool USE_BLENDING> void _drawPixel(const fVec3& pos, color_t color, float opacity);
2341
2342
2343 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);
2344
2345
2346 template<bool USE_BLENDING> void _drawDot(const fVec3& pos, int r, color_t color, float opacity);
2347
2348
2349 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);
2350
2351
2352
2353 template<bool CHECKRANGE, bool USE_BLENDING> TGX_INLINE inline void drawPixelZbuf(int x, int y, color_t color, float opacity, float z)
2354 {
2355 if (CHECKRANGE && ((x < 0) || (x >= _uni.im->lx()) || (y < 0) || (y >= _uni.im->ly()))) return;
2356 ZBUFFER_t& W = _uni.zbuf[x + _uni.im->lx() * y];
2357 const ZBUFFER_t aa = (std::is_same<ZBUFFER_t, uint16_t>::value) ? ((ZBUFFER_t)(z * _uni.wa + _uni.wb)) : ((ZBUFFER_t)z);
2358 if (W < aa)
2359 {
2360 W = aa;
2361 if (USE_BLENDING) _uni.im->template drawPixel<false>({ x, y }, color, opacity); else _uni.im->template drawPixel<false>({ x, y }, color);
2362 }
2363 }
2364
2365
2366 template<bool CHECKRANGE, bool USE_BLENDING> TGX_INLINE inline void drawHLineZbuf(int x, int y, int w, color_t color, float opacity, float z)
2367 {
2368 if (CHECKRANGE) // optimized away at compile time
2369 {
2370 const int lx = _uni.im->lx();
2371 const int ly = _uni.im->ly();
2372 if ((y < 0) || (y >= ly) || (x >= lx)) return;
2373 if (x < 0) { w += x; x = 0; }
2374 if (x + w > lx) { w = lx - x; }
2375 if (w <= 0) return;
2376 }
2377 while(w--) drawPixelZbuf<CHECKRANGE, USE_BLENDING>(x++, y, color, opacity, z);
2378 }
2379
2380
2381 template<bool CHECKRANGE, bool USE_BLENDING> void _drawCircleZbuf(int xm, int ym, int r, color_t color, float opacity, float z);
2382
2383
2387 float _unitSphereScreenDiameter();
2388
2389
2390 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);
2391
2392
2393
2394 /***********************************************************
2395 * CLIPPING
2396 ************************************************************/
2397
2398
2400 TGX_INLINE inline void _clip(int & fl, const fVec4 & P, float bx, float Bx, float by, float By)
2401 {
2402 if (P.x >= bx) { fl &= (~(1)); }
2403 if (P.x <= Bx) { fl &= (~(2)); }
2404 if (P.y >= by) { fl &= (~(4)); }
2405 if (P.y <= By) { fl &= (~(8)); }
2406 if ((P.z >= -1.0f)&&(P.w > 0)) { fl &= (~(16)); }
2407 if (P.z <= +1.0f) { fl &= (~(32)); }
2408 }
2409
2410
2412 TGX_INLINE inline void _clip(int & fl, const fVec3 & P, float bx, float Bx, float by, float By, const fMat4 & M)
2413 {
2414 fVec4 S = M.mult1(P);
2415 if (!_ortho) S.zdivide();
2416 return _clip(fl, S, bx, Bx, by, By);
2417 }
2418
2419
2420 /* test if a box is outside the image and should be discarded.
2421 transform the box coords with M then z-divide. */
2422 bool _discardBox(const fBox3 & bb, const fMat4 & M)
2423 {
2424 if ((bb.minX == 0) && (bb.maxX == 0) && (bb.minY == 0) && (bb.maxY == 0) && (bb.minZ == 0) && (bb.maxZ == 0))
2425 return false; // do not discard if the bounding box is uninitialized.
2426
2427 const float bx = (_ox - 1) * _ilx - 1.0f;
2428 const float Bx = (_ox + _uni.im->width() + 1) * _ilx - 1.0f;
2429 const float by = (_oy - 1) * _ily - 1.0f;
2430 const float By = (_oy + _uni.im->height() + 1) * _ily - 1.0f;
2431
2432 int fl = 63; // every bit set
2433 _clip(fl, fVec3(bb.minX, bb.minY, bb.minZ), bx, Bx, by, By, M);
2434 if (fl == 0) return false;
2435 _clip(fl, fVec3(bb.minX, bb.minY, bb.maxZ), bx, Bx, by, By, M);
2436 if (fl == 0) return false;
2437 _clip(fl, fVec3(bb.minX, bb.maxY, bb.minZ), bx, Bx, by, By, M);
2438 if (fl == 0) return false;
2439 _clip(fl, fVec3(bb.minX, bb.maxY, bb.maxZ), bx, Bx, by, By, M);
2440 if (fl == 0) return false;
2441 _clip(fl, fVec3(bb.maxX, bb.minY, bb.minZ), bx, Bx, by, By, M);
2442 if (fl == 0) return false;
2443 _clip(fl, fVec3(bb.maxX, bb.minY, bb.maxZ), bx, Bx, by, By, M);
2444 if (fl == 0) return false;
2445 _clip(fl, fVec3(bb.maxX, bb.maxY, bb.minZ), bx, Bx, by, By, M);
2446 if (fl == 0) return false;
2447 _clip(fl, fVec3(bb.maxX, bb.maxY, bb.maxZ), bx, Bx, by, By, M);
2448 if (fl == 0) return false;
2449 return true;
2450 }
2451
2452
2453 /* test if a triangle is completely outside the image and should be discarded.
2454 * coords are given after z-divide. */
2455 bool _discardTriangle(const fVec4 & P1, const fVec4 & P2, const fVec4 & P3)
2456 {
2457 const float bx = (_ox - 1) * _ilx - 1.0f;
2458 const float Bx = (_ox + _uni.im->width() + 1) * _ilx - 1.0f;
2459 const float by = (_oy - 1) * _ily - 1.0f;
2460 const float By = (_oy + _uni.im->height() + 1) * _ily - 1.0f;
2461
2462 int fl = 63; // every bit set
2463 _clip(fl, P1, bx, Bx, by, By);
2464 if (fl == 0) return false;
2465 _clip(fl, P2, bx, Bx, by, By);
2466 if (fl == 0) return false;
2467 _clip(fl, P3, bx, Bx, by, By);
2468 if (fl == 0) return false;
2469 return true;
2470 }
2471
2472
2474 bool _clip2(float clipboundXY, const fVec3 & P, const fMat4 & M)
2475 {
2476 fVec4 S = M.mult1(P);
2477 if (!_ortho)
2478 {
2479 S.zdivide();
2480 if (S.w <= 0) S.z = -2;
2481 }
2482 return ((S.x <= -clipboundXY) || (S.x >= clipboundXY)
2483 || (S.y <= -clipboundXY) || (S.y >= clipboundXY)
2484 || (S.z <= -1) || (S.z >= 1));
2485 }
2486
2487
2489 bool _clipTestNeeded(float clipboundXY, const fBox3 & bb, const fMat4 & M)
2490 {
2491 return (_clip2(clipboundXY, fVec3(bb.minX, bb.minY, bb.minZ), M)
2492 || _clip2(clipboundXY, fVec3(bb.minX, bb.minY, bb.maxZ), M)
2493 || _clip2(clipboundXY, fVec3(bb.minX, bb.maxY, bb.minZ), M)
2494 || _clip2(clipboundXY, fVec3(bb.minX, bb.maxY, bb.maxZ), M)
2495 || _clip2(clipboundXY, fVec3(bb.maxX, bb.minY, bb.minZ), M)
2496 || _clip2(clipboundXY, fVec3(bb.maxX, bb.minY, bb.maxZ), M)
2497 || _clip2(clipboundXY, fVec3(bb.maxX, bb.maxY, bb.minZ), M)
2498 || _clip2(clipboundXY, fVec3(bb.maxX, bb.maxY, bb.maxZ), M));
2499 }
2500
2501
2503 bool _wireFrameAANeighborCheckNeeded(const fBox3& bb, const fMat4& proj_modelview)
2504 {
2505 if ((_uni.im == nullptr) || (_uni.im->lx() <= 2) || (_uni.im->ly() <= 2)) return true;
2506
2507 const float bx = (_ox + 1.0f) * _ilx - 1.0f;
2508 const float Bx = (_ox + (float)(_uni.im->lx() - 2)) * _ilx - 1.0f;
2509 const float by = (_oy + 1.0f) * _ily - 1.0f;
2510 const float By = (_oy + (float)(_uni.im->ly() - 2)) * _ily - 1.0f;
2511
2512 const fVec3 C[8] = {
2513 fVec3(bb.minX, bb.minY, bb.minZ),
2514 fVec3(bb.minX, bb.minY, bb.maxZ),
2515 fVec3(bb.minX, bb.maxY, bb.minZ),
2516 fVec3(bb.minX, bb.maxY, bb.maxZ),
2517 fVec3(bb.maxX, bb.minY, bb.minZ),
2518 fVec3(bb.maxX, bb.minY, bb.maxZ),
2519 fVec3(bb.maxX, bb.maxY, bb.minZ),
2520 fVec3(bb.maxX, bb.maxY, bb.maxZ)
2521 };
2522
2523 for (int i = 0; i < 8; i++)
2524 {
2525 fVec4 P = proj_modelview.mult1(C[i]);
2526 if (!_ortho)
2527 {
2528 if (P.w <= 0) return true;
2529 P.zdivide();
2530 }
2531 if ((P.z < -1.0f) || (P.z > 1.0f)) return true;
2532 if ((P.x < bx) || (P.x > Bx) || (P.y < by) || (P.y > By)) return true;
2533 }
2534 return false;
2535 }
2536
2537
2538#if TGX_MESHLET_SPHERE_CLIP
2540 TGX_INLINE inline void _meshletClipPlanes(float clipboundXY, const fMat4& M, fVec4* planes, float* plane_norms) const
2541 {
2542 const float cx = clipboundXY;
2543 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]);
2544 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]);
2545 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]);
2546 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]);
2547 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]);
2548 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]);
2549 for (int i = 0; i < 6; i++)
2550 {
2551 const fVec4& P = planes[i];
2552 plane_norms[i] = sqrtf(P.x * P.x + P.y * P.y + P.z * P.z);
2553 }
2554 }
2555
2556
2558 TGX_INLINE inline int _meshletSphereClip(const fVec3& center, float radius, const fVec4* planes, const float* plane_norms) const
2559 {
2560 bool intersects = false;
2561 for (int i = 0; i < 6; i++)
2562 {
2563 const fVec4& P = planes[i];
2564 const float d = P.x * center.x + P.y * center.y + P.z * center.z + P.w;
2565 const float r = radius * plane_norms[i];
2566 if (d < -r) return -1;
2567 if (d < r) intersects = true;
2568 }
2569 return intersects ? 1 : 0;
2570 }
2571#endif
2572
2573
2574
2575
2576 /***********************************************************
2577 * TRIANGLE CLIPPING AGAINST A CLIP-PLANE
2578 ************************************************************/
2579
2588 inline float _cpdist(const tgx::fVec4& CP, float off, const tgx::fVec4& P)
2589 {
2590 return (CP.x * P.x) + (CP.y * P.y) + (CP.z * P.z) + (CP.w * P.w) + off;
2591 }
2592
2603 inline float _cpfactor(const tgx::fVec4& CP, const float sdistA, const float sdistB)
2604 {
2605 return sdistA / (sdistA - sdistB);
2606 }
2607
2608
2610 void _triangleClip1in(int shader, tgx::fVec4 CP,
2611 float cp1, float cp2, float cp3,
2612 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2613 RasterizerVec4& nP1, RasterizerVec4& nP2, RasterizerVec4& nP3, RasterizerVec4& nP4);
2614
2615
2617 void _triangleClip2in(int shader, tgx::fVec4 CP,
2618 float cp1, float cp2, float cp3,
2619 const RasterizerVec4& P1, const RasterizerVec4& P2, const RasterizerVec4& P3,
2620 RasterizerVec4& nP1, RasterizerVec4& nP2, RasterizerVec4& nP3, RasterizerVec4& nP4);
2621
2622
2623 int _triangleClip(int shader, tgx::fVec4 CP, float off,
2624 const RasterizerVec4 & P1, const RasterizerVec4 & P2, const RasterizerVec4 & P3,
2625 RasterizerVec4 & nP1, RasterizerVec4 & nP2, RasterizerVec4 & nP3, RasterizerVec4 & nP4);
2626
2627
2628
2629 /***********************************************************
2630 * PHONG LIGHTNING
2631 ************************************************************/
2632
2633 static const int _POWTABSIZE = 32; // number of entries in the precomputed power table for specular exponent.
2634 int _currentpow; // exponent for the currently computed table (<0 if table not yet computed)
2635 float _powmax; // used to compute exponent
2636 float _fastpowtab[_POWTABSIZE]; // the precomputed power table.
2637
2639 TGX_INLINE inline void _precomputeSpecularTable(int exponent)
2640 {
2641 if (_currentpow == exponent) return;
2642 _precomputeSpecularTable2(exponent);
2643 }
2644
2645 TGX_NOINLINE void _precomputeSpecularTable2(int exponent);
2646
2647
2649 TGX_INLINE inline float _powSpecular(float x) const
2650 {
2651 const float indf = (_powmax - x) * _POWTABSIZE;
2652 const int indi = max(0,(int)indf);
2653 return (indi >= (_POWTABSIZE - 1)) ? 0.0f : (_fastpowtab[indi] + (indf - indi) * (_fastpowtab[indi + 1] - _fastpowtab[indi]));;
2654 }
2655
2656
2657
2658
2660 TGX_INLINE inline void _updateDirectionalLightTransform(int index)
2661 {
2662 _r_light[index] = _viewM.mult0(_light[index]);
2663 _r_light[index] = -_r_light[index];
2664 _r_light[index].normalize();
2665 _r_light_inorm[index] = _r_light[index] * _r_inorm;
2666 _r_H[index] = fVec3(0, 0, 1); // cheating: should use the normalized current vertex position (but this is faster with almost the same result)...
2667 _r_H[index] += _r_light[index];
2668 _r_H[index].normalize();
2669 _r_H_inorm[index] = _r_H[index] * _r_inorm;
2670 }
2671
2672
2674 TGX_INLINE inline void _updateActiveDirectionalLightInorms()
2675 {
2676 for (int i = 0; i < _directionalLightCount; i++)
2677 {
2678 _r_light_inorm[i] = _r_light[i] * _r_inorm;
2679 _r_H_inorm[i] = _r_H[i] * _r_inorm;
2680 }
2681 }
2682
2683
2685 TGX_INLINE inline void _updateActiveDirectionalLightTransforms()
2686 {
2687 for (int i = 0; i < _directionalLightCount; i++)
2688 {
2689 _updateDirectionalLightTransform(i);
2690 }
2691 }
2692
2693
2695 TGX_INLINE inline void _setRuntimeMaterialLighting(float ambiantStrength, float diffuseStrength, float specularStrength)
2696 {
2697 _r_ambiantColor = _ambiantColor * ambiantStrength;
2698 for (int i = 0; i < _directionalLightCount; i++)
2699 {
2700 _r_diffuseColor[i] = _diffuseColor[i] * diffuseStrength;
2701 _r_specularColor[i] = _specularColor[i] * specularStrength;
2702 }
2703 }
2704
2705
2707 TGX_INLINE inline void _updateDirectionalLightColor(int index)
2708 {
2709 _r_diffuseColor[index] = _diffuseColor[index] * _diffuseStrength;
2710 _r_specularColor[index] = _specularColor[index] * _specularStrength;
2711 }
2712
2713
2714
2715 //
2716
2717
2719 template<bool TEXTURE> TGX_INLINE inline RGBf _shadeVertex(const float icu, const fVec3 & N) const
2720 {
2721 RGBf col = _r_ambiantColor;
2722 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2723 {
2724 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light_inorm[0]), 0.0f);
2725 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H_inorm[0]));
2726 }
2727 else
2728 {
2729 for (int i = 0; i < _directionalLightCount; i++)
2730 {
2731 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light_inorm[i]), 0.0f);
2732 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H_inorm[i]));
2733 }
2734 }
2735 if (!(TEXTURE)) col *= _r_objectColor;
2736 col.clamp();
2737 return col;
2738 }
2739
2740
2742 TGX_INLINE inline RGBf _shadeVertex(const float icu, const fVec3 & N, const RGBf & color) const
2743 {
2744 RGBf col = _r_ambiantColor;
2745 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2746 {
2747 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light_inorm[0]), 0.0f);
2748 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H_inorm[0]));
2749 }
2750 else
2751 {
2752 for (int i = 0; i < _directionalLightCount; i++)
2753 {
2754 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light_inorm[i]), 0.0f);
2755 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H_inorm[i]));
2756 }
2757 }
2758
2759 col *= color;
2760 col.clamp();
2761 return col;
2762 }
2763
2764
2766 template<bool TEXTURE> TGX_INLINE inline RGBf _shadeFace(const float icu, const fVec3 & N) const
2767 {
2768 RGBf col = _r_ambiantColor;
2769 if constexpr (MAX_DIRECTIONAL_LIGHTS == 1)
2770 {
2771 col += _r_diffuseColor[0] * max(icu * dotProduct(N, _r_light[0]), 0.0f);
2772 col += _r_specularColor[0] * _powSpecular(icu * dotProduct(N, _r_H[0]));
2773 }
2774 else
2775 {
2776 for (int i = 0; i < _directionalLightCount; i++)
2777 {
2778 col += _r_diffuseColor[i] * max(icu * dotProduct(N, _r_light[i]), 0.0f);
2779 col += _r_specularColor[i] * _powSpecular(icu * dotProduct(N, _r_H[i]));
2780 }
2781 }
2782 if (!(TEXTURE)) col *= _r_objectColor;
2783 col.clamp();
2784 return col;
2785 }
2786
2787
2789 TGX_INLINE inline void _setFlatOrUnlitFaceColor(int raster_type, bool texture, fVec3& faceN, float cu)
2790 {
2791 if constexpr (TGX_SHADER_HAS_UNLIT(ENABLED_SHADERS))
2792 {
2793 if (TGX_SHADER_HAS_UNLIT(raster_type))
2794 {
2795 _uni.facecolor = texture ? RGBf(1.0f, 1.0f, 1.0f) : _r_objectColor;
2796 return;
2797 }
2798 }
2799
2800 const float icu = ((cu > 0) ? -1.0f : 1.0f); // -1 if we need to reverse the face normal.
2801 faceN.normalize_fast();
2802 if (texture)
2803 _uni.facecolor = _shadeFace<true>(icu, faceN);
2804 else
2805 _uni.facecolor = _shadeFace<false>(icu, faceN);
2806 }
2807
2808
2809
2810 /***********************************************************
2811 * MEMBER VARIABLES
2812 ************************************************************/
2813
2814 // *** general parameters ***
2815
2816 int _lx, _ly; // viewport dimension
2817 float _ilx, _ily; // inverse viewport dimension
2818
2819 int _ox, _oy; // image offset w.r.t. the viewport
2820
2821 bool _ortho; // true to use orthographic projection and false for perspective projection
2822
2823 fMat4 _projM; // projection matrix
2824
2825 RasterizerParams<color_t, color_t,ZBUFFER_t> _uni; // rasterizer param (contain the image pointer and the zbuffer pointer).
2826
2827 float _culling_dir; // culling direction postive/negative or 0 to disable back face culling.
2828
2829 int _shaders; // the shaders to use.
2830 int _texture_mode; // texture mapping mode (perspective-correct or affine)
2831 int _texture_wrap_mode; // wrapping mode (wrap_pow2 or clamp)
2832 int _texture_quality; // texturing quality (nearest or bilinear)
2833
2834 // *** scene parameters ***
2835
2836 fMat4 _viewM; // view transform matrix
2837
2838 fVec3 _light[MAX_DIRECTIONAL_LIGHTS]; // directional light directions
2839 RGBf _ambiantColor; // light ambiant color
2840 RGBf _diffuseColor[MAX_DIRECTIONAL_LIGHTS]; // directional light diffuse colors
2841 RGBf _specularColor[MAX_DIRECTIONAL_LIGHTS]; // directional light specular colors
2842 int _directionalLightCount; // number of active directional lights
2843
2844
2845 // *** model specific parameters ***
2846
2847 fMat4 _modelM; // model transform matrix
2848
2849 // material parameters
2850 RGBf _color; // model color (use when texturing is disabled)
2851 float _ambiantStrength; // ambient light reflection strength
2852 float _diffuseStrength; // diffuse light reflection strength
2853 float _specularStrength; // specular light reflection strength
2854 int _specularExponent; // specular exponent
2855
2856
2857 // *** pre-computed values ***
2858 fMat4 _r_modelViewM; // model-view matrix
2859 float _r_inorm; // Fast normal scaling for lighting. Assumes rotation/uniform scale;
2860 // Gouraud lighting is approximate with non-uniform model scaling.
2861 fVec3 _r_light[MAX_DIRECTIONAL_LIGHTS]; // light vectors in view space (inverted and normalized)
2862 fVec3 _r_light_inorm[MAX_DIRECTIONAL_LIGHTS]; // same as above but already multiplied by inorm
2863 fVec3 _r_H[MAX_DIRECTIONAL_LIGHTS]; // halfway vectors.
2864 fVec3 _r_H_inorm[MAX_DIRECTIONAL_LIGHTS]; // same as above but already multiplied by inorm
2865 RGBf _r_ambiantColor; // ambient color multiplied by object ambient strength
2866 RGBf _r_diffuseColor[MAX_DIRECTIONAL_LIGHTS]; // diffuse colors multiplied by object diffuse strength
2867 RGBf _r_specularColor[MAX_DIRECTIONAL_LIGHTS]; // specular colors multiplied by object specular strength
2868 RGBf _r_objectColor; // color to use for drawing the object (either _color or mesh->color).
2869
2870
2874 struct ExtVec4 : public RasterizerVec4
2875 {
2876 fVec4 P; // after model-view matrix multiplication
2877 fVec4 N; // normal vector after model-view matrix multiplication
2878 bool missedP; // true if the attributes should be computed
2879 int indn; // index for normal vector in array
2880 int indt; // index for texture vector in array
2881 };
2882
2883
2884 };
2885
2886
2887
2888}
2889
2890
2891
2892
2893#include "Renderer3D.inl"
2894
2895
2896#endif
2897
2898#endif
2899
2900
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_AFFINE
enable affine (non perspective-correct) texture mapping
Definition: ShaderParams.h:61
@ SHADER_TEXTURE
enable perspective-correct 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:117
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:671
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