FlatShader.cpp
Go to the documentation of this file.
1 #include "FlatShader.hpp"
2 #include "ColorTransform.hpp"
3 #include "../Defs.hpp"
4 #include <ivorium_config.hpp>
5 
6 #include <glm/glm.hpp>
7 #include <glm/ext.hpp>
8 
9 namespace iv
10 {
11 
12 static constexpr char const * FlatShader_Filepath = "/ivorium_graphics/shaders/FlatShader";
13 
14 //-------------- FlatShader_Resource ---------------------------------------------------------------------
16  SingularResource< FlatShader >( inst, FlatShader_Filepath ),
17  cm( inst, this, "FlatShader_Resource" )
18 {
20 }
21 
22 //-------------- StringIO ---------------------------------------------------------------------
24 {
26 };
27 
29 {
33 };
34 
36 {
37  { FlatShader::ResizeStage::Scale, "Scale" },
38  { FlatShader::ResizeStage::Fixed, "Fixed" },
39  { FlatShader::ResizeStage::Repeat, "Repeat" },
41 };
42 
44 {
47  { FlatShader::FilteringStage::AlphaThreshold, "AlphaThreshold" },
48  { FlatShader::FilteringStage::AlphaThresholdWidth, "AlphaThresholdWidth" },
49  { FlatShader::FilteringStage::AlphaThresholdWidthSmooth, "AlphaThresholdWidthSmooth" },
50 };
51 
52 //-------------- FlatShader_Subprovider ---------------------------------------------------------------------
54  cm( inst, this, "FlatShader_Subprovider" ),
55  inst( inst )
56 {
57 }
58 
60 {
61  return this->inst;
62 }
63 
64 void FlatShader_Subprovider::each_resource( std::function< void( ResourcePath const & ) > const & f ) const
65 {
66  f( ResourcePath( FlatShader_Filepath ) );
67 }
68 
70 {
71  return path == FlatShader_Filepath;
72 }
73 
74 //-------------- FlatShader ---------------------------------------------------------------------
76  GlListener( inst ),
77  cm( inst, this, "FlatShader" ),
78  _shader( inst, path )
79 {
80  this->cm.owns( this->_shader.cm );
81 
82  // load shader params
83  if( this->GlIsEnabled() )
84  this->GlEnable();
85 }
86 
87 GLuint FlatShader::program_id() const
88 {
89  return this->_shader.gl_program()->program_id();
90 }
91 
92 void FlatShader::GlEnable()
93 {
94  // load shader
95  this->_shader.LoadProgram();
96  this->_shader.BindAttribute( GlMesh::AttributeLoc_Position, "position" );
97  this->_shader.BindAttribute( GlMesh::AttributeLoc_Texcoord, "texcoord" );
98  this->_shader.PositionAttributeName( "gl_Position" );
99  this->_shader.LinkProgram();
100 
101  // read uniform positions
102  this->mesh_resize = this->_shader.GetUniformLocation( "mesh_resize" );
103  this->mesh_texcoord_density = this->_shader.GetUniformLocation( "mesh_texcoord_density" );
104  this->tex0 = this->_shader.GetUniformLocation( "tex0" );
105  this->tex0_size = this->_shader.GetUniformLocation( "tex0_size" );
106  this->tex0_density_rel = this->_shader.GetUniformLocation( "tex0_density_rel" );
107  this->tex0_color_space = this->_shader.GetUniformLocation( "tex0_color_space" );
108  this->translucent = this->_shader.GetUniformLocation( "translucent" );
109  this->preblend = this->_shader.GetUniformLocation( "preblend" );
110  this->projection_view_model = this->_shader.GetUniformLocation( "projection_view_model" );
111  this->local_to_pixel_space = this->_shader.GetUniformLocation( "local_to_pixel_space" );
112  this->pixel_to_local_space = this->_shader.GetUniformLocation( "pixel_to_local_space" );
113  this->depth_override = this->_shader.GetUniformLocation( "depth_override" );
114  this->depth_override_enabled = this->_shader.GetUniformLocation( "depth_override_enabled" );
115  this->scissor_enabled = this->_shader.GetUniformLocation( "scissor_enabled" );
116  this->local_to_scissor_space = this->_shader.GetUniformLocation( "local_to_scissor_space" );
117  this->scissor_size = this->_shader.GetUniformLocation( "scissor_size" );
118  this->fitting_stage = this->_shader.GetUniformLocation( "fitting_stage" );
119  this->pixelize_stage = this->_shader.GetUniformLocation( "pixelize_stage" );
120  this->pixelize_size = this->_shader.GetUniformLocation( "pixelize_size" );
121  this->pixelize_offset = this->_shader.GetUniformLocation( "pixelize_offset" );
122  this->resize_stage = this->_shader.GetUniformLocation( "resize_stage" );
123  this->resize_anchor = this->_shader.GetUniformLocation( "resize_anchor" );
124  this->filtering_stage = this->_shader.GetUniformLocation( "filtering_stage" );
125  this->filtering_msdf_pixel_range = this->_shader.GetUniformLocation( "filtering_msdf_pixel_range" );
126  this->filtering_alpha_threshold = this->_shader.GetUniformLocation( "filtering_alpha_threshold" );
127  this->filtering_alpha_width = this->_shader.GetUniformLocation( "filtering_alpha_width" );
128  this->color_transform = this->_shader.GetUniformLocation( "color_transform" );
129  this->alpha = this->_shader.GetUniformLocation( "alpha" );
130  this->framebuffer_color_space = this->_shader.GetUniformLocation( "framebuffer_color_space" );
131 }
132 
133 void FlatShader::GlDisable()
134 {
135  this->_shader.UnloadProgram();
136 }
137 
138 void FlatShader::GlDrop()
139 {
140  this->_shader.DropProgram();
141 }
142 
144  ClientMarker const & log_target,
145 
146  // Renderable
147  CameraState const & camera,
148  std::optional< float > depth_override,
149 
150  // Elem
151  float4x4 const & model,
152  ShaderScissor const & scissor,
153 
154  // Translucent
155  float4 preblend,
156  bool translucent,
157 
158  // mesh
159  GlMesh const * mesh,
160  float3 mesh_resize,
161  float2 mesh_texcoord_density,
162 
163  // texture
164  GlTexture const * texture,
165  float texture_density_rel,
166  float texture_msdf_pixelRange,
167 
168  // parametrization
169  Params const & params
170  ) const
171 {
172  RenderTarget * target = GlInfo( this->instance() ).render_target();
173 
174  // texture not loaded yet?
175  if( texture->texture_id() == 0 )
176  {
177  log_target.log( SRC_INFO, Defs::Log::Render, "Texture not loaded, skipping." );
178  return;
179  }
180 
181  //==================== bind states ======================================
182  target->bind_texture( 0, texture->texture_id() );
183  target->bind_shader( this->_shader.gl_program()->program_id() );
184 
185  //==================== set uniforms =====================================
186  // mesh
187  glUniform3f( this->mesh_resize, mesh_resize.x, mesh_resize.y, mesh_resize.z );
188  glUniform2f( this->mesh_texcoord_density, mesh_texcoord_density.x, mesh_texcoord_density.y );
189 
190  // texture
191  glUniform1i( this->tex0, 0 );
192  glUniform2f( this->tex0_size, texture->size().x, texture->size().y );
193  glUniform1f( this->tex0_density_rel, texture_density_rel );
194  glUniform1i( this->tex0_color_space, (int)texture->gpu_color_space() );
195 
196  // translucency
197  float4 preblend_linear = ColorTransform::sRGB_to_linearRGB( preblend );
198  glUniform1i( this->translucent, translucent );
199  glUniform4f( this->preblend, preblend_linear.r, preblend_linear.g, preblend_linear.b, preblend.a );
200 
201  // space transform
202  float4x4 projection_view_model = camera.projection * camera.view * model;
203  glUniformMatrix4fv( this->projection_view_model, 1, GL_FALSE, glm::value_ptr( projection_view_model ) );
204 
205  float4x4 local_to_pixel_space = glm::inverse( camera.pixelizing_projection ) * projection_view_model;
206  glUniformMatrix4fv( this->local_to_pixel_space, 1, GL_FALSE, glm::value_ptr( local_to_pixel_space ) );
207  float4x4 pixel_to_local_space = glm::inverse( local_to_pixel_space );
208  glUniformMatrix4fv( this->pixel_to_local_space, 1, GL_FALSE, glm::value_ptr( pixel_to_local_space ) );
209 
210  glUniform1i( this->depth_override_enabled, depth_override.has_value() );
211  glUniform1f( this->depth_override, depth_override.value() );
212 
213  // scissor
214  glUniform1i( this->scissor_enabled, scissor.enabled );
215  float4x4 local_to_scissor_space = glm::inverse( scissor.model ) * model;
216  glUniformMatrix4fv( this->local_to_scissor_space, 1, GL_FALSE, glm::value_ptr( local_to_scissor_space ) );
217  glUniform3f( this->scissor_size, scissor.size.x, scissor.size.y, scissor.size.z );
218 
219  // fitting
220  /*
221  Pixel fitting -
222  screen_space_position = inv( orthogonal_projection ) * projection * view * model * vertex_position
223  - pozice vertexu na displeji, jedna jednotka je jeden pixel
224  - jak tuto informaci využít k fittování?
225  -> W normalizace pozice
226  -> zaokrouhlení pozice
227  transformace zpátky:
228  result_vertex_position = orthogonal_projection * vec4( adjusted_screen_space_position, 1 )
229  */
230  glUniform1i( this->fitting_stage, (int)params.fittingStage );
231 
232  // shader params
233  glUniform1i( this->pixelize_stage, (int)params.pixelizeStage );
234  glUniform2f( this->pixelize_size, params.pixelizeSize.Get().x, params.pixelizeSize.Get().y );
235  glUniform2f( this->pixelize_offset, params.pixelizeOffset.Get().x, params.pixelizeOffset.Get().y );
236 
237  glUniform1i( this->resize_stage, (int)params.resizeStage );
238  glUniform2f( this->resize_anchor, params.resizeAnchor.Get().x, params.resizeAnchor.Get().y );
239 
240  glUniform1i( this->filtering_stage, (int)params.filteringStage );
241  glUniform1f( this->filtering_msdf_pixel_range, texture_msdf_pixelRange );
242  glUniform1f( this->filtering_alpha_threshold, params.filteringAlphaThreshold.Get() );
243  glUniform1f( this->filtering_alpha_width, params.filteringAlphaWidth.Get() );
244 
245  glUniformMatrix4fv( this->color_transform, 1, GL_FALSE, glm::value_ptr( params.colorTransform.Get() ) );
246 
247  glUniform1f( this->alpha, params.alpha.Get() );
248 
249  #if IV_GLPLATFORM_GLFW
250  ColorSpace fb_colorspace = ColorSpace::Linear;
251  #elif IV_GLPLATFORM_GLFM
252  ColorSpace fb_colorspace = ColorSpace::sRGB;
253  #else
254  #error "Unimplemented framebuffer color space detection for this GL platform."
255  #endif
256  glUniform1i( this->framebuffer_color_space, (int)fb_colorspace );
257 
258  //======================= log =========================================
259  log_target.log( SRC_INFO, Defs::Log::Render,
260  "\n",
261 
262  // Renderable
263  " camera.projection ", camera.projection, Context::Endl(),
264  " camera.view ", camera.view, Context::Endl(),
265  " camera.pixelizing_projection ", camera.pixelizing_projection, Context::Endl(),
266  " depth_override ", depth_override, Context::Endl(),
267 
268  // Elem
269  " model ", model, Context::Endl(),
270  " scissor ", scissor.enabled, " ", scissor.size, " ", scissor.model, Context::Endl(),
271 
272  // Translucent
273  " translucent ", translucent, Context::Endl(),
274  " preblend ", preblend, Context::Endl(),
275 
276  // mesh
277  " mesh->indices_cnt ", mesh->indices_cnt(), Context::Endl(),
278  " mesh_resize ", mesh_resize, Context::Endl(),
279  " mesh_texcoord_density ", mesh_texcoord_density, Context::Endl(),
280 
281  // texture
282  " texture->size ", texture->size(), Context::Endl(),
283  " texture_density_rel ", texture_density_rel, Context::Endl(),
284  " texture_msdf_pixelRange ", texture_msdf_pixelRange, Context::Endl(),
285  " texture_color_space ", texture->gpu_color_space(), Context::Endl(),
286  " framebuffer_color_space ", fb_colorspace, Context::Endl(),
287 
288  // params
289  " params.fittingStage ", params.fittingStage, Context::Endl(),
290 
291  " params.pixelizeStage ", params.pixelizeStage, Context::Endl(),
292  " params.pixelizeSize ", params.pixelizeSize.Get(), Context::Endl(),
293  " params.pixelizeOffset ", params.pixelizeOffset.Get(), Context::Endl(),
294 
295  " params.resizeStage ", params.resizeStage, Context::Endl(),
296  " params.resizeAnchor ", params.resizeAnchor.Get(), Context::Endl(),
297 
298  " params.filteringStage ", params.filteringStage, Context::Endl(),
299  " params.filteringAlphaThreshold ", params.filteringAlphaThreshold.Get(), Context::Endl(),
300  " params.filteringAlphaWidth ", params.filteringAlphaWidth.Get(), Context::Endl(),
301 
302  " params.alpha ", params.alpha.Get(), Context::Endl(),
303 
304  " params.colorTransform ", params.colorTransform.Get()
305  );
306 
307  //==================== render call ======================================
308  mesh->DrawElements( &log_target );
309 }
310 
311 }