Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Johannes Braun
glare
Commits
5f0fe266
Commit
5f0fe266
authored
Aug 05, 2017
by
Johannes Braun
Browse files
Removed crappy Polymorph RayGenerator by a proper enum switch based one
parent
2f449113
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/executables/pathtracing/main.cpp
View file @
5f0fe266
...
...
@@ -14,12 +14,6 @@
using
namespace
glare
;
enum
class
RayGeneratorMode
{
eGBuffer
=
0
,
eDefault
=
1
};
enum
class
RenderMode
{
eLines
=
0
,
...
...
@@ -42,7 +36,6 @@ std::unique_ptr<raytrace::Pathtracer> pathtracer = nullptr;
// Some Application states
fs
::
path
current_scene_root
=
startup_scene_path
.
parent_path
();
RenderMode
render_mode
=
RenderMode
::
eGBuffer
;
RayGeneratorMode
ray_generator_mode
=
RayGeneratorMode
::
eDefault
;
// All functions used in here
void
keyPress
(
controls
::
Key
key
,
controls
::
KeyMods
mods
);
...
...
@@ -201,21 +194,10 @@ void drawDebugGui()
if
(
ImGui
::
CollapsingHeader
(
"Sampling and Performance"
))
{
ImGui
::
BeginNamedGroup
(
"Ray Generator"
);
int
raygenstate
=
int
(
ray_g
enerator
_mode
);
int
raygenstate
=
int
(
pathtracer
->
getG
enerator
()
);
ImGui
::
PushItemWidth
(
ImGui
::
GetContentRegionAvailWidth
());
if
(
ImGui
::
Combo
(
""
,
&
raygenstate
,
{
"GBuffer"
,
"Default (BVH)"
}))
{
ray_generator_mode
=
RayGeneratorMode
(
raygenstate
);
switch
(
ray_generator_mode
)
{
case
RayGeneratorMode
::
eDefault
:
pathtracer
->
setGenerator
(
std
::
make_shared
<
raytrace
::
RayGeneratorDefault
>
());
break
;
case
RayGeneratorMode
::
eGBuffer
:
pathtracer
->
setGenerator
(
std
::
make_shared
<
raytrace
::
RayGeneratorGBuffer
>
());
break
;
default:
break
;
}
if
(
ImGui
::
Combo
(
""
,
&
raygenstate
,
{
"Trace [default]"
,
"OpenGL GBuffer"
}))
{
pathtracer
->
setGenerator
(
raytrace
::
RayGeneratorType
(
raygenstate
));
}
ImGui
::
PopItemWidth
();
ImGui
::
EndNamedGroup
();
...
...
src/libraries/core/state.cpp
View file @
5f0fe266
...
...
@@ -30,11 +30,11 @@ namespace glare
// BASIC CONFIG
const
auto
config_child
=
preferences_file
.
child
(
"settings"
).
find_child_by_attribute
(
"group"
,
"name"
,
"config"
);
unsigned
window_width
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_size_x"
).
attribute
(
"value"
).
as_uint
(
1280
);
unsigned
window_height
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_size_y"
).
attribute
(
"value"
).
as_uint
(
720
);
unsigned
samples
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"msaa"
).
attribute
(
"value"
).
as_uint
(
4
);
std
::
string
window_title
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_title"
).
attribute
(
"value"
).
as_string
(
"GLARE"
);
std
::
string
splash_preferences
=
preferences_file
.
child
(
"settings"
).
find_child_by_attribute
(
"item"
,
"name"
,
"splash_screen"
).
attribute
(
"value"
).
as_string
();
const
unsigned
window_width
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_size_x"
).
attribute
(
"value"
).
as_uint
(
1280
);
const
unsigned
window_height
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_size_y"
).
attribute
(
"value"
).
as_uint
(
720
);
const
unsigned
samples
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"msaa"
).
attribute
(
"value"
).
as_uint
(
4
);
const
std
::
string
window_title
=
config_child
.
find_child_by_attribute
(
"item"
,
"name"
,
"window_title"
).
attribute
(
"value"
).
as_string
(
"GLARE"
);
const
std
::
string
splash_preferences
=
preferences_file
.
child
(
"settings"
).
find_child_by_attribute
(
"item"
,
"name"
,
"splash_screen"
).
attribute
(
"value"
).
as_string
();
initialize
(
window_width
,
window_height
,
samples
,
window_title
);
...
...
src/libraries/raytrace/tracer/pathtracer.cpp
View file @
5f0fe266
...
...
@@ -12,7 +12,7 @@ namespace glare
namespace
raytrace
{
Pathtracer
::
Pathtracer
()
:
Pathtracer
(
std
::
make_shared
<
RayGeneratorDefault
>
()
)
:
Pathtracer
(
RayGeneratorType
::
eTrace
)
{
}
...
...
@@ -23,23 +23,23 @@ namespace glare
}
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
,
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
)
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
,
RayGenerator
Type
ray_generator
)
:
Pathtracer
(
std
::
make_shared
<
SceneCollector
>
(
graph_root
),
ray_generator
)
{
}
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
)
Pathtracer
::
Pathtracer
(
RayGenerator
Type
ray_generator
)
:
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
(
nullptr
),
ray_generator
)
{
}
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
)
:
Pathtracer
(
collector
,
std
::
make_shared
<
RayGeneratorDefault
>
()
)
:
Pathtracer
(
collector
,
RayGeneratorType
::
eTrace
)
{
}
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
,
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
)
Pathtracer
::
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
,
RayGenerator
Type
ray_generator
)
{
m_bounce_count_thresholds
[
unsigned
(
EffectType
::
eDiffuse
)]
=
4
;
m_bounce_count_thresholds
[
unsigned
(
EffectType
::
eTranslucent
)]
=
6
;
...
...
@@ -59,7 +59,7 @@ namespace glare
m_render_config
.
bounces
=
16
;
Log_Hint
<<
"Pathtracing Shader will now be compiled. This might take a couple of seconds."
;
m_render_shader
=
std
::
make_unique
<
core
::
Program
>
(
files
::
shader
(
"/raytracer/pathtracer.comp"
));
m_
ray_
generator
=
ray_generator
;
m_generator
_type
=
ray_generator
;
m_trace_buffer
=
std
::
make_unique
<
core
::
Buffer
<
gl
::
BufferType
::
eShaderStorage
>>
();
registerForMessage
(
tags
::
scene
);
...
...
@@ -181,8 +181,8 @@ namespace glare
if
(
m_render_config
.
current_sample
>=
m_render_config
.
max_samples
)
return
*
m_render_target
;
m_ray_g
enerator
-
>
generat
e
(
*
this
);
//return *m_r
en
d
er
_target
;
const
static
std
::
unique_ptr
<
RayG
enerator
>
ray_
generat
or
=
std
::
make_unique
<
RayGenerator
>
(
);
ray_generator
->
g
ener
ate
(
*
this
)
;
m_render_shader
->
use
();
m_render_shader
->
uniform
(
"u_render_config.current_sample"
,
m_render_config
.
current_sample
);
...
...
@@ -205,12 +205,17 @@ namespace glare
core
::
textures
::
saveTexture
(
target
,
*
m_render_target
);
}
void
Pathtracer
::
setGenerator
(
std
::
shared_ptr
<
RayGenerator
Base
>
generator
)
void
Pathtracer
::
setGenerator
(
RayGenerator
Type
generator
)
{
m_
ray_
generator
=
generator
;
m_generator
_type
=
generator
;
reset
();
}
RayGeneratorType
Pathtracer
::
getGenerator
()
const
{
return
m_generator_type
;
}
void
Pathtracer
::
initialize
(
std
::
shared_ptr
<
SceneCollector
>
collector
)
{
m_collector
=
collector
;
...
...
src/libraries/raytrace/tracer/pathtracer.h
View file @
5f0fe266
...
...
@@ -35,10 +35,10 @@ namespace glare
public:
Pathtracer
();
Pathtracer
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
);
Pathtracer
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
,
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
);
Pathtracer
(
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
);
Pathtracer
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
,
RayGenerator
Type
ray_generator
);
Pathtracer
(
RayGenerator
Type
ray_generator
);
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
);
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
,
std
::
shared_ptr
<
RayGenerator
Base
>
ray_generator
);
Pathtracer
(
std
::
shared_ptr
<
SceneCollector
>
collector
,
RayGenerator
Type
ray_generator
);
~
Pathtracer
();
void
loadSettings
(
const
fs
::
path
&
xml_file
);
...
...
@@ -48,7 +48,8 @@ namespace glare
void
saveRender
(
fs
::
path
target
)
const
;
//template<typename DataStruct>
void
setGenerator
(
std
::
shared_ptr
<
RayGeneratorBase
>
generator
);
void
setGenerator
(
RayGeneratorType
generator
);
RayGeneratorType
getGenerator
()
const
;
void
initialize
(
std
::
shared_ptr
<
SceneCollector
>
collector
);
void
reload
(
std
::
shared_ptr
<
core
::
GraphNode
>
graph_root
);
...
...
@@ -119,9 +120,7 @@ namespace glare
}
m_linespace_config
;
std
::
array
<
uint8_t
,
8
>
m_bounce_count_thresholds
;
std
::
array
<
uint8_t
,
8
>
m_ls_bounce_count_thresholds
;
std
::
vector
<
unsigned
>
m_subroutines
;
std
::
array
<
uint8_t
,
8
>
m_ls_bounce_count_thresholds
;
std
::
shared_ptr
<
SceneCollector
>
m_collector
;
std
::
unique_ptr
<
core
::
TextureRGBA_32F
>
m_render_target
;
...
...
@@ -130,7 +129,7 @@ namespace glare
std
::
unique_ptr
<
core
::
Buffer
<
gl
::
BufferType
::
eShaderStorage
>>
m_trace_buffer
;
std
::
shared_ptr
<
core
::
Skybox
>
m_skybox
;
std
::
shared_ptr
<
RayGeneratorBase
>
m_ray_generator
;
RayGeneratorType
m_generator_type
=
RayGeneratorType
::
eTrace
;
};
}
}
...
...
src/libraries/raytrace/tracer/raygenerator.cpp
View file @
5f0fe266
...
...
@@ -10,7 +10,7 @@ namespace glare
{
namespace
raytrace
{
uint32_t
RayGenerator
Base
::
randomSeed
()
uint32_t
RayGenerator
::
randomSeed
()
{
static
std
::
random_device
rd
;
static
std
::
mt19937
gen
(
rd
());
...
...
@@ -19,69 +19,59 @@ namespace glare
return
dist
(
gen
);
}
void
RayGenerator
Base
::
generate
(
Pathtracer
&
pathtracer
)
void
RayGenerator
::
generate
(
Pathtracer
&
pathtracer
)
{
m_
updated_size
=
false
;
bool
updated_size
=
false
;
if
(
pathtracer
.
width
()
!=
m_last_width
||
pathtracer
.
height
()
!=
m_last_height
)
{
m_last_width
=
pathtracer
.
width
();
m_last_height
=
pathtracer
.
height
();
m_
updated_size
=
true
;
updated_size
=
true
;
}
}
RayGeneratorDefault
::
RayGeneratorDefault
()
{
m_generator_shader_default
=
std
::
make_unique
<
core
::
Program
>
(
files
::
shader
(
"/raytracer/generators/bvh/bvh_raygenerator.comp"
));
switch
(
pathtracer
.
getGenerator
())
{
default:
case
RayGeneratorType
::
eTrace
:
generateTrace
(
pathtracer
,
updated_size
);
break
;
case
RayGeneratorType
::
eOpenGL
:
generateOpenGL
(
pathtracer
,
updated_size
);
break
;
}
}
void
RayGenerator
Default
::
generate
(
Pathtracer
&
pathtracer
)
void
RayGenerator
::
generate
Trace
(
Pathtracer
&
pathtracer
,
bool
updated_size
)
{
if
(
!
m_generator_shader_default
)
return
;
RayGeneratorBase
::
generate
(
pathtracer
);
m_generator_shader_default
->
use
();
//m_generator_shader_default->updateUniformImageRGBA32F("u_render_target", pathtracer.renderTarget(), gl::Access::eReadWrite);
m_generator_shader_default
->
uniform
(
"u_render_target"
,
pathtracer
.
renderTarget
().
makeImageResident
(
gl
::
Access
::
eReadWrite
));
m_generator_shader_default
->
storageBuffer
(
"trace_buffer"
,
pathtracer
.
traceBuffer
());
m_generator_shader_default
->
uniform
(
"random_seed"
,
int
(
randomSeed
()));
pathtracer
.
collector
()
->
apply
(
*
m_generator_shader_default
);
m_generator_shader_default
->
dispatch2d
(
m_last_width
,
12
,
m_last_height
,
12
);
const
static
auto
generator_program
=
std
::
make_unique
<
core
::
Program
>
(
files
::
shader
(
"/raytracer/generators/bvh/bvh_raygenerator.comp"
));
generator_program
->
use
();
generator_program
->
uniform
(
"u_render_target"
,
pathtracer
.
renderTarget
().
makeImageResident
(
gl
::
Access
::
eReadWrite
));
generator_program
->
storageBuffer
(
"trace_buffer"
,
pathtracer
.
traceBuffer
());
generator_program
->
uniform
(
"random_seed"
,
int
(
randomSeed
()));
pathtracer
.
collector
()
->
apply
(
*
generator_program
);
generator_program
->
dispatch2d
(
m_last_width
,
12
,
m_last_height
,
12
);
}
RayGenerator
GBuffer
::
RayGeneratorGBuffer
(
)
void
RayGenerator
::
generateOpenGL
(
Pathtracer
&
pathtracer
,
bool
updated_size
)
{
std
::
vector
<
std
::
shared_ptr
<
glare
::
core
::
Shader
>>
shaders
=
{
// Initialize Variables uniquely.
const
static
auto
generator_program
=
std
::
make_unique
<
core
::
Program
>
(
std
::
vector
<
std
::
shared_ptr
<
glare
::
core
::
Shader
>>
{
std
::
make_shared
<
glare
::
core
::
Shader
>
(
gl
::
ShaderType
::
eVertex
,
files
::
shader
(
"raytracer/generators/gbuffer/gbuffer.vert"
)),
std
::
make_shared
<
glare
::
core
::
Shader
>
(
gl
::
ShaderType
::
eGeometry
,
files
::
shader
(
"raytracer/generators/gbuffer/gbuffer.geom"
)),
std
::
make_shared
<
glare
::
core
::
Shader
>
(
gl
::
ShaderType
::
eFragment
,
files
::
shader
(
"raytracer/generators/gbuffer/gbuffer.frag"
))
};
m_generator_shader_gbuffer
=
std
::
make_unique
<
core
::
Program
>
(
shaders
);
m_buffer_depthtest
=
std
::
make_unique
<
core
::
Program
>
(
files
::
shader
(
"raytracer/generators/gbuffer/depthtest.comp"
));
m_vertex_array
=
std
::
make_unique
<
core
::
VertexArray
>
();
}
void
RayGeneratorGBuffer
::
generate
(
Pathtracer
&
pathtracer
)
{
if
(
pathtracer
.
width
()
!=
m_last_width
||
pathtracer
.
height
()
!=
m_last_height
)
{
m_last_width
=
pathtracer
.
width
();
m_last_height
=
pathtracer
.
height
();
m_framebuffer
=
std
::
make_unique
<
core
::
Framebuffer
<
core
::
TextureMultisampled
>>
(
pathtracer
.
width
(),
pathtracer
.
height
(),
8
);
m_framebuffer
->
attach
(
gl
::
Attachment
::
eColor0
);
m_framebuffer
->
attach
(
gl
::
Attachment
::
eDepthStencil
);
std
::
make_shared
<
glare
::
core
::
Shader
>
(
gl
::
ShaderType
::
eGeometry
,
files
::
shader
(
"raytracer/generators/gbuffer/gbuffer.geom"
)),
std
::
make_shared
<
glare
::
core
::
Shader
>
(
gl
::
ShaderType
::
eFragment
,
files
::
shader
(
"raytracer/generators/gbuffer/gbuffer.frag"
))
});
const
static
auto
depthtest_program
=
std
::
make_unique
<
core
::
Program
>
(
files
::
shader
(
"raytracer/generators/gbuffer/depthtest.comp"
));
const
static
auto
vertex_array
=
std
::
make_unique
<
core
::
VertexArray
>
();
static
std
::
unique_ptr
<
core
::
Framebuffer
<
core
::
TextureMultisampled
>>
framebuffer
;
if
(
updated_size
)
{
framebuffer
=
std
::
make_unique
<
core
::
Framebuffer
<
core
::
TextureMultisampled
>>
(
pathtracer
.
width
(),
pathtracer
.
height
(),
8
);
framebuffer
->
attach
(
gl
::
Attachment
::
eColor0
);
framebuffer
->
attach
(
gl
::
Attachment
::
eDepthStencil
);
}
m_
generator_
shader_gbuffer
->
use
();
generator_
program
->
use
();
//m_generator_shader_gbuffer->updateStorageBuffer("mesh_buffer", pathtracer.collector()->meshBuffer());
pathtracer
.
collector
()
->
apply
(
*
m_
generator_
shader_gbuffer
);
pathtracer
.
collector
()
->
apply
(
*
generator_
program
);
core
::
OpenGLState
::
capture
();
m_
framebuffer
->
activate
();
framebuffer
->
activate
();
gl
::
setEnabled
(
gl
::
EnableParameter
::
eBlend
,
false
);
gl
::
setEnabled
(
gl
::
EnableParameter
::
eDepthTest
,
true
);
gl
::
setEnabled
(
gl
::
EnableParameter
::
eCullFace
,
false
);
...
...
@@ -91,28 +81,27 @@ namespace glare
const
auto
&
mesh_unit
=
pathtracer
.
collector
()
->
getUnit
<
MeshCollector
>
(
"mesh_collector"
);
for
(
auto
&&
pair
:
mesh_unit
.
localCollectors
())
{
auto
id
=
mesh_unit
.
idMapping
().
at
(
pair
.
first
);
m_
generator_
shader_gbuffer
->
uniform
(
"u_mesh_id"
,
unsigned
(
id
));
m_
generator_
shader_gbuffer
->
uniform
(
"u_mvp"
,
core
::
state
::
camera
->
getViewProjection
()
*
pair
.
second
->
transform
());
generator_
program
->
uniform
(
"u_mesh_id"
,
unsigned
(
id
));
generator_
program
->
uniform
(
"u_mvp"
,
core
::
state
::
camera
->
getViewProjection
()
*
pair
.
second
->
transform
());
m_
vertex_array
->
bind
();
vertex_array
->
bind
();
gl
::
drawArrays
(
gl
::
PrimitiveType
::
ePoints
,
0
,
pair
.
second
->
triangles
().
size
());
m_vertex_array
->
unbind
();
vertex_array
->
unbind
();
}
gl
::
memoryBarrier
(
gl
::
MemoryBarrierBit
::
eAll
);
m_
framebuffer
->
deactivate
();
framebuffer
->
deactivate
();
core
::
OpenGLState
::
reset
();
m_buffer_
depthtest
->
use
();
m_buffer_
depthtest
->
uniform
(
"u_gbuffer_texture_01"
,
m_
framebuffer
->
colorAttachment
(
gl
::
Attachment
::
eColor0
).
makeImageResident
(
gl
::
Access
::
eReadOnly
));
m_buffer_
depthtest
->
uniform
(
"u_render_target"
,
pathtracer
.
renderTarget
().
makeImageResident
(
gl
::
Access
::
eReadWrite
));
depthtest
_program
->
use
();
depthtest
_program
->
uniform
(
"u_gbuffer_texture_01"
,
framebuffer
->
colorAttachment
(
gl
::
Attachment
::
eColor0
).
makeImageResident
(
gl
::
Access
::
eReadOnly
));
depthtest
_program
->
uniform
(
"u_render_target"
,
pathtracer
.
renderTarget
().
makeImageResident
(
gl
::
Access
::
eReadWrite
));
m_buffer_
depthtest
->
storageBuffer
(
"trace_buffer"
,
pathtracer
.
traceBuffer
());
pathtracer
.
collector
()
->
apply
(
*
m_buffer_
depthtest
);
m_buffer_
depthtest
->
uniform
(
"random_seed"
,
int
(
randomSeed
()));
m_buffer_
depthtest
->
dispatch1d
(
m_last_width
*
m_last_height
,
1024
);
depthtest
_program
->
storageBuffer
(
"trace_buffer"
,
pathtracer
.
traceBuffer
());
pathtracer
.
collector
()
->
apply
(
*
depthtest
_program
);
depthtest
_program
->
uniform
(
"random_seed"
,
int
(
randomSeed
()));
depthtest
_program
->
dispatch1d
(
m_last_width
*
m_last_height
,
1024
);
}
}
...
...
src/libraries/raytrace/tracer/raygenerator.h
View file @
5f0fe266
...
...
@@ -29,46 +29,25 @@ namespace glare
}
properties
;
};
class
RayGenerator
Bas
e
enum
class
RayGenerator
Typ
e
{
public:
RayGeneratorBase
()
{}
RayGeneratorBase
(
RayGeneratorBase
&
other
)
=
delete
;
virtual
~
RayGeneratorBase
()
=
default
;
virtual
void
generate
(
Pathtracer
&
raytracer
);
static
uint32_t
randomSeed
();
protected:
bool
m_updated_size
=
false
;
unsigned
m_last_width
=
0
;
unsigned
m_last_height
=
0
;
eTrace
=
0
,
eOpenGL
=
1
};
class
RayGenerator
Default
:
public
RayGeneratorBase
class
RayGenerator
{
public:
RayGeneratorDefault
();
~
RayGeneratorDefault
()
{};
void
generate
(
Pathtracer
&
raytracer
)
override
;
private:
std
::
unique_ptr
<
core
::
Program
>
m_generator_shader_default
;
};
void
generate
(
Pathtracer
&
pathtracer
);
class
RayGeneratorGBuffer
:
public
RayGeneratorBase
{
public:
RayGeneratorGBuffer
();
~
RayGeneratorGBuffer
()
{};
void
generate
(
Pathtracer
&
raytracer
)
override
;
protected:
void
generateTrace
(
Pathtracer
&
pathtracer
,
bool
updated_size
);
void
generateOpenGL
(
Pathtracer
&
pathtracer
,
bool
updated_size
);
private:
std
::
unique_ptr
<
core
::
Program
>
m_generator_shader_gbuffer
;
std
::
unique_ptr
<
core
::
Program
>
m_buffer_depthtest
;
std
::
unique_ptr
<
core
::
VertexArray
>
m_vertex_array
;
std
::
unique_ptr
<
core
::
Framebuffer
<
core
::
TextureMultisampled
>>
m_framebuffer
;
static
uint32_t
randomSeed
();
bool
m_updated_size
=
false
;
unsigned
m_last_width
=
0
;
unsigned
m_last_height
=
0
;
};
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment