source: trunk/src/engine/renderer.cc @ 520

Last change on this file since 520 was 518, checked in by epyon, 9 years ago
  • refactoring of the particle_engine
  • particle_manager added
  • cleanups
File size: 5.5 KB
Line 
1// Copyright (C) 2016-2016 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/engine/renderer.hh"
8
9#include "nv/core/profiler.hh"
10
11using namespace nv;
12
13renderer::renderer( context* ctx )
14        : m_context( ctx )
15{
16        for ( auto& i : m_statistics ) i = 0;
17
18        struct qvtx
19        {
20                nv::vec2 position;
21                nv::vec2 texcoord;
22        };
23
24        qvtx quad[] = {
25                qvtx{ vec2( -1.0f,-1.0f ), vec2( 0.0f, 0.0f ) },
26                qvtx{ vec2( 1.0f,-1.0f ),  vec2( 1.0f, 0.0f ) },
27                qvtx{ vec2( 1.0f,1.0f ),   vec2( 1.0f, 1.0f ) },
28                qvtx{ vec2( 1.0f,1.0f ),   vec2( 1.0f, 1.0f ) },
29                qvtx{ vec2( -1.0f,1.0f ),  vec2( 0.0f, 1.0f ) },
30                qvtx{ vec2( -1.0f,-1.0f ), vec2( 0.0f, 0.0f ) },
31        };
32        m_quad = m_context->create_vertex_array( quad, 6, STATIC_DRAW );
33}
34
35void renderer::sort()
36{
37        stable_sort( m_elements.begin(), m_elements.end(), renderer_element_compare() );
38}
39
40
41void renderer::render( const scene_state& s, const render_pass& pass )
42{
43        scene_state ss( s );
44        m_context->bind( pass.fbuffer, FRAMEBUFFER );
45        m_context->set_draw_buffers( pass.output_count, pass.output );
46        m_context->set_viewport( ss.get_viewport() );
47
48        if ( pass.cstate.buffers != buffer_mask::NO_BUFFER )
49                m_context->clear( pass.cstate );
50
51        for ( uint32 i = 0; i < size( pass.binds ); ++i )
52                if ( pass.binds[i] )
53                        m_context->bind( pass.binds[i], texture_slot( i ) );
54
55        resource_id current_mat;
56        mat4 model = ss.get_model();
57        for ( const renderer_element& element : m_elements )
58                if ( match( element.flags, pass ) )
59                {
60                        ss.set_model( model * element.model.extract() );
61                        if ( auto mesh = element.mesh.lock() )
62                                if ( mesh->count > 0 )
63                                        if ( auto program = pass.programs[mesh->shader].lock() )
64                                        {
65                                                if ( element.mat.id() != current_mat )
66                                                {
67                                                        if ( auto mat = element.mat.lock() )
68                                                        {
69                                                                for ( uint32 i = 0; i < 8; ++i )
70                                                                        if ( mat->textures[i] && !pass.binds[i] )
71                                                                                m_context->bind( mat->textures[i], nv::texture_slot( i ) );
72                                                                current_mat = element.mat.id();
73                                                        }
74                                                }
75
76                                                m_context->get_device()->set_opt_uniform( *program, "nv_bone_offset", element.bone_offset );
77                                                m_context->get_device()->set_opt_uniform( *program, "nv_flags", unsigned( *element.flags.data() ) );
78
79                                                m_context->apply_engine_uniforms( *program, ss );
80                                                m_context->draw( TRIANGLES, pass.rstate, *program, mesh->va, mesh->count );
81
82                                                m_statistics[TRIANGLE_COUNT] += mesh->count / 3;
83                                                m_statistics[DRAW_CALL]++;
84                                        }
85                }
86
87        m_context->bind( pass.fbuffer, FRAMEBUFFER );
88}
89
90void renderer::render( const scene_state& ss, const render_pass& pass, vertex_array va, uint32 va_count, uint32 program_idx )
91{
92        m_context->bind( pass.fbuffer, FRAMEBUFFER );
93        m_context->set_draw_buffers( pass.output_count, pass.output );
94        m_context->set_viewport( ss.get_viewport() );
95
96        if ( pass.cstate.buffers != buffer_mask::NO_BUFFER )
97                m_context->clear( pass.cstate );
98
99        for ( uint32 i = 0; i < size( pass.binds ); ++i )
100                if ( pass.binds[i] )
101                        m_context->bind( pass.binds[i], texture_slot(i) );
102
103        if ( auto program = pass.programs[program_idx].lock() )
104        {
105                m_context->apply_engine_uniforms( *program, ss );
106                m_context->draw( TRIANGLES, pass.rstate, *program, va, va_count );
107                m_statistics[ TRIANGLE_COUNT ] += 2;
108                m_statistics[ DRAW_CALL ]++;
109        }
110
111        m_context->bind( pass.fbuffer, FRAMEBUFFER );
112}
113
114void nv::renderer::render_direct( const scene_state& s, const render_pass& pass, const nv::array_view< renderer_direct_element >& elements, uint32 program_idx )
115{
116        if ( m_elements.size() == 0 ) return;
117
118        scene_state ss( s );
119        m_context->bind( pass.fbuffer, FRAMEBUFFER );
120        m_context->set_draw_buffers( pass.output_count, pass.output );
121        m_context->set_viewport( ss.get_viewport() );
122
123
124        if ( pass.cstate.buffers != buffer_mask::NO_BUFFER )
125                m_context->clear( pass.cstate );
126
127        for ( uint32 i = 0; i < size( pass.binds ); ++i )
128                if ( pass.binds[i] )
129                        m_context->bind( pass.binds[i], texture_slot( i ) );
130
131        resource_id current_mat;
132        resource_id current_prog;
133
134        mat4 model = ss.get_model();
135        for ( uint32 index = 0; index < elements.size(); ++index )
136        {
137                const renderer_direct_element& element = elements[index];
138                if ( match( element.flags, pass ) )
139                {
140                        ss.set_model( model * element.model.extract() );
141                        if ( element.count > 0 )
142                        {
143                                if ( auto program = element.programs[program_idx].lock() )
144                                {
145                                        if ( element.material.id() != current_mat )
146                                        {
147                                                if ( auto mat = element.material.lock() )
148                                                {
149                                                        for ( uint32 i = 0; i < 8; ++i )
150                                                                if ( mat->textures[i] && !pass.binds[i] )
151                                                                        m_context->bind( mat->textures[i], nv::texture_slot( i ) );
152                                                        current_mat = element.material.id();
153                                                }
154                                        }
155
156                                        m_context->get_device()->set_opt_uniform( *program, "nv_flags", unsigned( *element.flags.data() ) );
157                                        m_context->get_device()->set_opt_uniform( *program, "nv_index", unsigned( index ) );
158                                        m_context->apply_engine_uniforms( *program, ss );
159
160                                        if ( element.instances > 0 )
161                                                m_context->draw_instanced( TRIANGLES, pass.rstate, *program, element.instances, element.va, element.count, element.first );
162                                        else
163                                                m_context->draw( TRIANGLES, pass.rstate, *program, element.va, element.count, element.first );
164
165                                        m_statistics[TRIANGLE_COUNT] += ( element.count / 3 ) * max< uint32 >( element.instances, 1 );
166                                        m_statistics[DRAW_CALL]++;
167                                }
168                        }
169                }
170        }
171        m_context->bind( pass.fbuffer, FRAMEBUFFER );
172}
Note: See TracBrowser for help on using the repository browser.