Loading [MathJax]/jax/output/HTML-CSS/config.js
Radium Engine  1.5.28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
texture.cpp
1#include "Engine/Data/Texture.hpp"
2
3#include <catch2/catch_test_macros.hpp>
4
5#include <Core/CoreMacros.hpp>
6#include <Engine/Data/BlinnPhongMaterial.hpp>
7#include <Engine/Data/LambertianMaterial.hpp>
8#include <Engine/Data/PlainMaterial.hpp>
9#include <Engine/Data/VolumetricMaterial.hpp>
10#include <Engine/OpenGL.hpp>
11#include <Engine/RadiumEngine.hpp>
12
13#include <Headless/CLIViewer.hpp>
14#include <glbinding/gl/enum.h>
15#include <globjects/Texture.h>
16#include <memory>
17#ifdef HEADLESS_HAS_EGL
18# include <Headless/OpenGLContext/EglOpenGLContext.hpp>
19#else
20# include <Headless/OpenGLContext/GlfwOpenGLContext.hpp>
21#endif
22
23using namespace Ra::Headless;
24using namespace Ra::Engine::Data;
25using namespace Ra::Core::Utils;
26using namespace gl;
27using namespace gl45core;
28
29TEST_CASE( "Engine/Data/Texture", "[unittests][Engine][Engine/Data][Textures]" ) {
30 // Get the Engine and materials initialized
31 glbinding::Version glVersion { 4, 4 };
32#ifdef HEADLESS_HAS_EGL
33 CLIViewer viewer { std::make_unique<EglOpenGLContext>( glVersion ) };
34#else
35 CLIViewer viewer { std::make_unique<GlfwOpenGLContext>( glVersion ) };
36#endif
37 auto dummy_name = "unittest_textures";
38 auto code = viewer.init( 1, &dummy_name );
39 viewer.setCamera();
40
41 SECTION( "Texture Init Now" ) {
42 REQUIRE( code == 0 );
43 viewer.bindOpenGLContext( true );
44 GLuint id1, id2;
45 TextureParameters params = { {}, {} };
46 {
47 Texture texture1( params );
48 Texture texture2( params );
49
50 texture1.initializeNow();
51 texture2.initializeNow();
52
53 auto gpuTexture1 = texture1.getGpuTexture();
54 auto gpuTexture2 = texture2.getGpuTexture();
55
56 REQUIRE( gpuTexture1 != nullptr );
57 REQUIRE( gpuTexture2 != nullptr );
58
59 id1 = gpuTexture1->id();
60 id2 = gpuTexture2->id();
61
62 REQUIRE( id1 != id2 );
63
64 REQUIRE( glIsTexture( id1 ) );
65 REQUIRE( glIsTexture( id2 ) );
66
67 texture1.destroyNow();
68
69 REQUIRE( !glIsTexture( id1 ) );
70 REQUIRE( texture1.getGpuTexture() == nullptr );
71 REQUIRE( glIsTexture( id2 ) );
72 REQUIRE( texture2.getGpuTexture() == gpuTexture2 );
73 }
74
75 viewer.bindOpenGLContext( true );
76 viewer.oneFrame();
77
78 REQUIRE( !glIsTexture( id1 ) );
79 REQUIRE( !glIsTexture( id2 ) );
80 }
81
82 SECTION( "Texture Init Delayed" ) {
83 REQUIRE( code == 0 );
84 viewer.bindOpenGLContext( true );
85 GLuint id1, id2;
86 TextureParameters params = { {}, {} };
87 {
88 Texture texture1( params );
89 Texture texture2( params );
90
91 texture1.initialize();
92 texture2.initialize();
93
94 auto gpuTexture1 = texture1.getGpuTexture();
95 auto gpuTexture2 = texture2.getGpuTexture();
96
97 REQUIRE( gpuTexture1 == nullptr );
98 REQUIRE( gpuTexture2 == nullptr );
99
100 viewer.oneFrame();
101
102 gpuTexture1 = texture1.getGpuTexture();
103 gpuTexture2 = texture2.getGpuTexture();
104
105 REQUIRE( gpuTexture1 != nullptr );
106 REQUIRE( gpuTexture2 != nullptr );
107
108 id1 = gpuTexture1->id();
109 id2 = gpuTexture2->id();
110
111 REQUIRE( id1 != id2 );
112
113 REQUIRE( glIsTexture( id1 ) );
114 REQUIRE( glIsTexture( id2 ) );
115
116 texture1.destroy();
117
118 // id1 is still texture
119 REQUIRE( glIsTexture( id1 ) );
120 // while gpuTexture ptr directly reset
121 REQUIRE( texture1.getGpuTexture() == nullptr );
122
123 viewer.oneFrame();
124
125 REQUIRE( !glIsTexture( id1 ) );
126 REQUIRE( texture1.getGpuTexture() == nullptr );
127
128 REQUIRE( glIsTexture( id2 ) );
129 REQUIRE( texture2.getGpuTexture() == gpuTexture2 );
130 // this will register delayed update tasks, that will be removed in dtor
131 texture2.setParameters( { {}, {} } );
132 }
133
134 viewer.bindOpenGLContext( true );
135 viewer.oneFrame();
136
137 REQUIRE( !glIsTexture( id1 ) );
138 REQUIRE( !glIsTexture( id2 ) );
139 }
140
141 SECTION( "Texture Update and Resize" ) {
142 REQUIRE( code == 0 );
143
144 auto data1 = std::shared_ptr<uchar[]>( new uchar[3] );
145
146 data1[0] = 0;
147 data1[1] = 1;
148 data1[2] = 2;
149
151 { std::shared_ptr<uchar[]>( new uchar[3] ),
152 std::shared_ptr<uchar[]>( new uchar[3] ),
153 std::shared_ptr<uchar[]>( new uchar[3] ),
154 std::shared_ptr<uchar[]>( new uchar[3] ),
155 std::shared_ptr<uchar[]>( new uchar[3] ),
156 std::shared_ptr<uchar[]>( new uchar[3] ) } };
158 { data2[0], data2[1], data2[2], data2[3], data2[4], data2[5] } };
159
160 TextureParameters params1 = { {}, {} };
161 TextureParameters params2 = { {}, {} };
162
163 params1.image.texels = data1;
164 params2.image.target = GL_TEXTURE_CUBE_MAP;
165 params2.image.texels = data2void;
166
167 Texture texture1( params1 );
168 Texture texture2( params2 );
169
170 texture1.initialize();
171 texture2.initialize();
172 viewer.bindOpenGLContext( true );
173 viewer.oneFrame();
174
175 REQUIRE( texture1.getParameters().image.isTexelOfType<ImageParameters::ImageType>() );
176 REQUIRE( texture1.getTexels() != nullptr );
177 REQUIRE( static_cast<const uchar*>( texture1.getTexels() )[0] == 0 );
178 REQUIRE( static_cast<const uchar*>( texture1.getTexels() )[1] == 1 );
179 REQUIRE( static_cast<const uchar*>( texture1.getTexels() )[2] == 2 );
180
181 auto gpuTexture1 = texture1.getGpuTexture();
182 REQUIRE( gpuTexture1 != nullptr );
183 auto id1 = gpuTexture1->id();
184
185 REQUIRE( glIsTexture( id1 ) );
186
187 auto readData1 = gpuTexture1->getImage( 0, params1.image.format, params1.image.type );
188
189 REQUIRE( readData1[0] == data1[0] );
190 REQUIRE( readData1[1] == data1[1] );
191 REQUIRE( readData1[2] == data1[2] );
192
193 data1[0] = 4;
194 data1[1] = 5;
195 data1[2] = 6;
196
197 texture1.updateData( data1 );
198 // update data is dalayed
199 readData1 = gpuTexture1->getImage( 0, params1.image.format, params1.image.type );
200
201 REQUIRE( readData1[0] == 0 );
202 REQUIRE( readData1[1] == 1 );
203 REQUIRE( readData1[2] == 2 );
204
205 // one frame will update data
206 viewer.oneFrame();
207 readData1 = gpuTexture1->getImage( 0, params1.image.format, params1.image.type );
208
209 REQUIRE( readData1[0] == data1[0] );
210 REQUIRE( readData1[1] == data1[1] );
211 REQUIRE( readData1[2] == data1[2] );
212
213 // resize send data immediately
214 auto data1Resized = std::shared_ptr<uchar[]>( new uchar[3 * 4] );
215 for ( uchar i = 0; i < 3 * 4; ++i )
216 data1Resized[i] = i;
217 texture1.resize( 2, 2, 1, data1Resized );
218 readData1 = gpuTexture1->getImage( 0, params1.image.format, params1.image.type );
219 // see GL_PACK_ROW_LENGTH
220 // https://registry.khronos.org/OpenGL-Refpages/gl4/html/glPixelStore.xhtml
221 int a;
222 glGetIntegerv( GL_PACK_ALIGNMENT, &a );
223 const int n = 3;
224 const int l = 2;
225 const int s = 1;
226 int k = s >= a ? n * l : a / s * (int)std::ceil( float( s * n * l ) / a );
227 // 2 x 2 pixels, with 3 components each
228 for ( size_t i = 0; i < 2; ++i ) {
229 for ( size_t j = 0; j < l; ++j ) {
230 for ( size_t c = 0; c < n; ++c ) {
231 size_t readIndex = i * k + j * n + c;
232 size_t dataIndex = i * ( l * n ) + j * n + c;
233 REQUIRE( readData1[readIndex] == data1Resized[dataIndex] );
234 }
235 }
236 }
237 }
238}
T ceil(T... args)
Represent a Texture of the engine.
Definition Texture.hpp:120
(GPU) Data representation, along with manager
Describes the sampler and image of a texture.
Definition Texture.hpp:99