Ignore:
Timestamp:
04/15/15 15:37:04 (10 years ago)
Author:
epyon
Message:
  • separation of the graphics code from the gui code
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/gui_renderer.cc

    r351 r354  
    77#include "nv/gui/gui_renderer.hh"
    88
    9 #include <glm/gtc/matrix_transform.hpp>
    10 
    11 #include "nv/interface/device.hh"
    12 #include "nv/interface/context.hh"
    13 #include "nv/core/logging.hh"
    14 
    15 static const char *nv_gui_vertex_shader = R"(
    16 #version 120
    17 attribute vec2 nv_position;
    18 attribute vec2 nv_texcoord;
    19 attribute vec4 nv_color;
    20 varying vec4 v_color;
    21 varying vec2 v_texcoord;
    22 uniform mat4 nv_m_projection;
    23 void main(void)
    24 {
    25         gl_Position = nv_m_projection * vec4(nv_position.x, nv_position.y, 0.0, 1.0);
    26         v_texcoord  = nv_texcoord;
    27         v_color     = nv_color;
    28 }
    29 )";
    30 
    31 static const char *nv_gui_fragment_shader = R"(
    32 #version 120
    33 varying vec4 v_color;
    34 varying vec2 v_texcoord;
    35 uniform sampler2D nv_t_diffuse;
    36 void main(void)
    37 {
    38         vec4 tex_color = texture2D( nv_t_diffuse, v_texcoord );
    39         gl_FragColor   = v_color * tex_color;
    40 }
    41 )";
    42 
    43 
    44 using namespace nv;
    45 using namespace nv::gui;
    46 
    47 struct vertex
    48 {
    49         ivec2 position;
    50         vec2  texcoord;
    51         vec4  color;
    52         vertex() {}
    53         vertex( const nv::ivec2& cr, const nv::vec2& tc, const nv::vec4& c )
    54                 : position( cr ), texcoord( tc ), color( c )
    55         {
    56         }
    57 };
    58 
    59 const ivec2 atlas_size = ivec2( 1024, 1024 );
    60 
    61 struct gui_quad
    62 {
    63         vertex vtx[6];
    64         gui_quad( const nv::ivec2& coorda, const nv::ivec2& coordb, const nv::vec4& color )
    65         {
    66                 set_color( color );
    67                 vtx[0].position = coorda;
    68                 vtx[1].position = nv::ivec2( coorda.x, coordb.y );
    69                 vtx[2].position = coordb;
    70                 vtx[3].position = coordb;
    71                 vtx[4].position = nv::ivec2( coordb.x, coorda.y );
    72                 vtx[5].position = coorda;
    73         }
    74         gui_quad( const nv::ivec2& coorda, const nv::ivec2& coordb, const nv::vec4& color, const nv::vec2& tcoorda, const nv::vec2& tcoordb )
    75         {
    76                 set_color( color );
    77                 vtx[0].position = coorda;
    78                 vtx[1].position = nv::ivec2( coorda.x, coordb.y );
    79                 vtx[2].position = coordb;
    80                 vtx[3].position = coordb;
    81                 vtx[4].position = nv::ivec2( coordb.x, coorda.y );
    82                 vtx[5].position = coorda;
    83                 vtx[0].texcoord = tcoorda;
    84                 vtx[1].texcoord = nv::vec2( tcoorda.x, tcoordb.y );
    85                 vtx[2].texcoord = tcoordb;
    86                 vtx[3].texcoord = tcoordb;
    87                 vtx[4].texcoord = nv::vec2( tcoordb.x, tcoorda.y );
    88                 vtx[5].texcoord = tcoorda;
    89         }
    90         gui_quad( const nv::ivec2& coorda, const nv::ivec2& coordb, const nv::ivec2& coordc, const nv::ivec2& coordd, const nv::vec4& color )
    91         {
    92                 set_color( color );
    93                 vtx[0].position = coorda;
    94                 vtx[1].position = coordb;
    95                 vtx[2].position = coordc;
    96                 vtx[3].position = coordc;
    97                 vtx[4].position = coordd;
    98                 vtx[5].position = coorda;
    99         }
    100         inline void set_color( const nv::vec4& color )
    101         {
    102                 vtx[0].color = color; vtx[1].color = color;     vtx[2].color = color;
    103                 vtx[3].color = color; vtx[4].color = color;     vtx[5].color = color;
    104         }
    105 };
    106 
    107 
    108 class screen_render_data : public render_data
    109 {
    110 public:
    111         screen_render_data( context* actx, size_t initial_size )
    112                 : buffer( actx, VERTEX_BUFFER, DYNAMIC_DRAW, initial_size ), ctx( actx ), varray(), shader()
    113         {
    114 
    115         }
    116         ~screen_render_data()
    117         {
    118                 ctx->get_device()->release( shader );
    119                 ctx->release( varray );
    120         }
    121 
    122         nv::sliced_buffer<gui_quad> buffer;
    123         nv::context*      ctx;
    124         nv::texture       tex;
    125         nv::vertex_array  varray;
    126         nv::program       shader;
    127 };
    128 
    129 class element_render_data : public render_data
    130 {
    131 public:
    132         element_render_data( nv::sliced_buffer<gui_quad>* cbuffer )
    133                 : buffer( cbuffer ) {}
    134 
    135         nv::buffer_slice< gui_quad > buffer;
    136 };
    137 
    138 renderer::renderer( window* w )
    139         : m_window(w)
    140         , m_style()
    141         , m_atlas( atlas_size, 4 )
    142         , m_reupload( true )
    143 {
    144         NV_LOG( LOG_TRACE, "Creating GUI renderer..." );
    145         m_context = w->get_context();
    146         m_area.dim( dimension( w->get_width(), w->get_height() ) );
    147         region white = m_atlas.get_region( ivec2(3,3) );
    148         size_t wsize = m_atlas.get_depth()*4*4;
    149         uint8* wfill = new uint8[m_atlas.get_depth()*4*4];
    150         std::fill( wfill, wfill + wsize, 255 );
    151         white.pos = ivec2();
    152         m_atlas.set_region( white, wfill );
    153         delete[] wfill;
    154 
    155         NV_LOG( LOG_TRACE, "Creating render data..." );
    156         screen_render_data* sr = new screen_render_data( w->get_context(), 1024 );
    157         m_render_data = sr;
    158         sr->shader     = m_window->get_device()->create_program( nv_gui_vertex_shader, nv_gui_fragment_shader );
    159         m_scene_state.get_camera().set_ortho( 0.0f, float( m_window->get_width() ), float( m_window->get_height() ), 0.0f );
    160 
    161         sr->varray     = m_window->get_context()->create_vertex_array();
    162         buffer vb      = sr->buffer.get_buffer();
    163         m_window->get_context()->add_vertex_buffers< vertex >( sr->varray, vb );
    164 
    165         nv::sampler sampler( nv::sampler::LINEAR, nv::sampler::CLAMP_TO_EDGE );
    166         sr->tex = m_window->get_device()->create_texture( m_atlas.get_size(), image_format( nv::RGBA, nv::UBYTE ), sampler, nullptr );
    167 
    168         m_render_state.depth_test.enabled = false;
    169         m_render_state.culling.enabled    = false;
    170         m_render_state.blending.enabled   = true;
    171         m_render_state.blending.src_rgb_factor   = blending::SRC_ALPHA;
    172         m_render_state.blending.dst_rgb_factor   = blending::ONE_MINUS_SRC_ALPHA;
    173         m_render_state.blending.src_alpha_factor = blending::SRC_ALPHA;
    174         m_render_state.blending.dst_alpha_factor = blending::ONE_MINUS_SRC_ALPHA;
    175         NV_LOG( LOG_TRACE, "GUI Renderer created" );
    176 }
    177 
    178 texture_font* renderer::get_font( size_t name ) const
    179 {
    180         if ( name >= m_fonts.size() ) return nullptr;
    181         return m_fonts[ name ];
    182 }
    183 
    184 const image_info* renderer::get_image( size_t name ) const
    185 {
    186         if ( name >= m_images.size() ) return nullptr;
    187         return &m_images[ name ];
    188 }
    189 
    190 size_t renderer::load_font( const std::string& filename, size_t size )
    191 {
    192         std::string id_name( filename );
    193         id_name.append( to_string( size ) );
    194         auto i = m_font_names.find( id_name );
    195         if ( i != m_font_names.end() )
    196         {
    197                 return i->second;
    198         }
    199         size_t result = (size_t)m_fonts.size();
    200         texture_font* f = new texture_font( &m_atlas, filename.c_str(), (float)size );
    201         f->load_glyphs( "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ " );
    202         m_fonts.push_back( f );
    203         m_reupload = true;
    204         m_font_names[ id_name ] = result;
    205         return result;
    206 }
    207 
    208 size_t renderer::load_image( const std::string& filename )
    209 {
    210         auto i = m_image_names.find( filename );
    211         if ( i != m_image_names.end() )
    212         {
    213                 return i->second;
    214         }
    215         size_t result = m_images.size();
    216         image_data* data = m_window->get_device()->create_image_data( filename );
    217         // TODO: Repitching
    218         assert( data->get_depth() == 4 );
    219         region r = m_atlas.get_region( data->get_size() );
    220         m_atlas.set_region( r, data->get_data() );
    221         m_images.emplace_back( vec2( r.pos ) / vec2( atlas_size ), vec2( r.size + r.pos ) / vec2( atlas_size ), r.size );
    222         delete data;
    223         m_reupload = true;
    224         m_image_names[ filename ] = result;
    225         return result;
    226 }
    227 
    228 void renderer::load_style( const std::string& filename )
     9void nv::gui::renderer::load_style( const std::string& filename )
    22910{
    23011        m_style.load_style( filename );
    23112}
    232 
    233 void renderer::redraw( element* e, uint32 )
    234 {
    235         screen_render_data* sr = (screen_render_data*)m_render_data;
    236         if ( e->m_render_data == nullptr )
    237         {
    238                 e->m_render_data = new element_render_data( &sr->buffer );
    239         }
    240         element_render_data* er = (element_render_data*)(e->m_render_data);
    241         size_t size_before = er->buffer.data().size();
    242 
    243         std::vector< gui_quad >& qvec = er->buffer.lock();
    244 
    245         qvec.clear();
    246         rectangle abs = e->m_absolute;
    247         if ( e->m_absolute != m_area )
    248         {
    249                 int border = 0;
    250                 vec4 color;
    251                 std::string path;
    252                 std::string text;
    253                 const char* stext[] = { nullptr, "selected", "hover" };
    254                 const char* selector = stext[border];
    255                 if ( e->m_flags[HOVER] )    selector = stext[2];
    256                 if ( e->m_flags[SELECTED] ) selector = stext[1];
    257 
    258                 if ( m_style.get( e, "skin", selector, path ) )
    259                 {
    260                         size_t image_id = load_image( path );
    261                         const image_info* image  = get_image( image_id );
    262                         if ( image )
    263                         {
    264                                 color = vec4( 2, 2, 2, 1 );
    265                                 ivec2 isize3  = image->size / 3;
    266                                 ivec2 isize3x = ivec2( isize3.x, 0 );
    267                                 ivec2 isize3y = ivec2( 0, isize3.y );
    268                                 vec2 tsize    = ( image->t2 - image->t1 );
    269                                 vec2 tsize3   = ( image->t2 - image->t1 ) / 3.0f;
    270                                 vec2 tsize32  = ( image->t2 - image->t1 ) * ( 2.0f / 3.0f );
    271                                 vec2 tsizex   = vec2( tsize.x, 0.0f );
    272                                 vec2 tsizey   = vec2( 0.0f, tsize.y );
    273                                 vec2 tsize3x  = vec2( tsize3.x, 0.0f );
    274                                 vec2 tsize3y  = vec2( 0.0f, tsize3.y );
    275                                 vec2 tsize3x2 = vec2( tsize32.x, 0.0f );
    276                                 vec2 tsize3y2 = vec2( 0.0f, tsize32.y );
    277 
    278                                 rectangle inner = abs.shrinked( isize3 );
    279                                 qvec.emplace_back( abs.ul, inner.ul, color, image->t1, image->t1+tsize3 );
    280                                 qvec.emplace_back( abs.ul+isize3x, inner.ur(), color, image->t1+tsize3x, image->t1+tsize3x2+tsize3y);
    281                                 qvec.emplace_back( abs.ur()-isize3x, inner.ur()+isize3x, color, image->t1+tsize3x2, image->t1+tsizex+tsize3y );
    282 
    283                                 qvec.emplace_back( abs.ul+isize3y, inner.ll(), color, image->t1+tsize3y, image->t1+tsize3y2+tsize3x );
    284                                 qvec.emplace_back( inner.ul, inner.lr, color, image->t1+tsize3, image->t1+tsize32 );
    285                                 qvec.emplace_back( inner.ur(), inner.lr+isize3x, color, image->t1+tsize3+tsize3x, image->t1+tsize32+tsize3x );
    286 
    287 
    288                                 qvec.emplace_back( abs.ll()-isize3y, inner.ll()+isize3y, color, image->t1+tsize3y2, image->t1+tsize3y2+tsize3 );
    289                                 qvec.emplace_back( inner.ll(), abs.lr-isize3x, color, image->t1+tsize3y2+tsize3x, image->t1+tsize32+tsize3y );
    290                                 qvec.emplace_back( inner.lr, abs.lr, color, image->t1+tsize32, image->t1+tsize );
    291 
    292        
    293 //                              qvec.emplace_back( abs.ul, abs.ll(), inner.ll(), inner.ul, color );
    294 //                              qvec.emplace_back( inner.ur(), inner.lr, abs.lr, abs.ur(), color );
    295 //                              qvec.emplace_back( inner.ll(), abs.ll(), abs.lr, inner.lr, color );
    296                                 abs = inner;
    297 
    298                         }
    299 
    300                 }
    301                 else
    302                 {
    303 
    304                         if ( m_style.get( e, "border", selector, border ) && m_style.get( e, "border_color", selector, color ) )
    305                         {
    306                                 rectangle inner = abs.shrinked( border );
    307                                 qvec.emplace_back( abs.ul, inner.ul, inner.ur(), abs.ur(), color );
    308                                 qvec.emplace_back( abs.ul, abs.ll(), inner.ll(), inner.ul, color );
    309                                 qvec.emplace_back( inner.ur(), inner.lr, abs.lr, abs.ur(), color );
    310                                 qvec.emplace_back( inner.ll(), abs.ll(), abs.lr, inner.lr, color );
    311                                 abs = inner;
    312                         }
    313 
    314                         if ( m_style.get( e, "background_color", selector, color ) )
    315                         {
    316                                 qvec.emplace_back( abs.ul, abs.lr, color );
    317                         }
    318                 }
    319 
    320                 text = e->m_text;
    321                 if ( !text.empty() )
    322                 {
    323                         if ( m_style.get( e, "text_color", selector, color ) && m_style.get( e, "text_font", selector, path ) && m_style.get( e, "text_size", selector, border ) )
    324                         {
    325                                 size_t font_id = load_font( path, (uint16)border );
    326                                 texture_font* font = get_font( font_id );
    327                                 position p = abs.ul + position( 0, border );
    328                                 for ( char c : text )
    329                                 {
    330                                         const texture_glyph* g = font->get_glyph( static_cast<uint16>(c) );
    331                                         if (g)
    332                                         {
    333                                                 position gp = position( g->offset.x, -g->offset.y );
    334                                                 position p2 = p + g->size + gp;
    335                                                 qvec.emplace_back( p + gp, p2, color, g->tl, g->br );
    336                                                 p += g->advance;
    337                                         }
    338                                 }
    339                         }
    340                 }
    341         }
    342 
    343         if ( size_before != er->buffer.data().size() )
    344         {
    345                 sr->buffer.reset();
    346         }
    347 }
    348 
    349 void renderer::on_hover_change( element* e, bool hover )
    350 {
    351         // TODO: FIX
    352         NV_LOG( nv::LOG_DEBUG, "on_hover_change" );
    353         e->m_flags[DIRTY] = true;
    354 }
    355 
    356 void renderer::on_select_change( element* e, bool select )
    357 {
    358         // TODO: FIX
    359         NV_LOG( nv::LOG_DEBUG, "on_select_change" );
    360         e->m_flags[DIRTY] = true;
    361 }
    362 
    363 
    364 void renderer::draw( element* e )
    365 {
    366         element_render_data* er = (element_render_data*)(e->m_render_data);
    367         er->buffer.commit();
    368 }
    369 
    370 void renderer::draw()
    371 {
    372         screen_render_data* sr = (screen_render_data*)m_render_data;
    373 
    374         if ( m_reupload )
    375         {
    376                 m_context->update( sr->tex, (void*)m_atlas.get_data() );
    377                 m_reupload = false;
    378         }
    379 
    380         if ( sr->buffer.commit() )
    381         {
    382                 buffer vb = sr->buffer.get_buffer();
    383                 m_context->replace_vertex_buffer( sr->varray, vb, false );
    384         }
    385         m_context->bind( sr->tex, TEX_DIFFUSE );
    386         m_context->draw( TRIANGLES, m_render_state, m_scene_state, sr->shader, sr->varray, sr->buffer.get_size() * 6 );
    387 }
    388 
    389 renderer::~renderer()
    390 {
    391         for ( auto p : m_fonts )
    392         {
    393                 delete p;
    394         }
    395         if ( m_render_data )
    396         {
    397                 m_context->get_device()->release( ((screen_render_data*)m_render_data)->tex );
    398                 delete m_render_data;
    399         }
    400 }
Note: See TracChangeset for help on using the changeset viewer.