source: trunk/src/engine/renderer.cc

Last change on this file was 522, checked in by epyon, 9 years ago
  • updates lol
File size: 5.6 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        render_state rs( pass.rstate );
120        m_context->bind( pass.fbuffer, FRAMEBUFFER );
121        m_context->set_draw_buffers( pass.output_count, pass.output );
122        m_context->set_viewport( ss.get_viewport() );
123
124
125        if ( pass.cstate.buffers != buffer_mask::NO_BUFFER )
126                m_context->clear( pass.cstate );
127
128        for ( uint32 i = 0; i < size( pass.binds ); ++i )
129                if ( pass.binds[i] )
130                        m_context->bind( pass.binds[i], texture_slot( i ) );
131
132        resource_id current_mat;
133        resource_id current_prog;
134
135        mat4 model = ss.get_model();
136        for ( uint32 index = 0; index < elements.size(); ++index )
137        {
138                const renderer_direct_element& element = elements[index];
139                if ( match( element.flags, pass ) )
140                {
141                        ss.set_model( model * element.model.extract() );
142                        if ( element.count > 0 )
143                        {
144                                if ( auto program = element.programs[program_idx].lock() )
145                                {
146                                        if ( element.material.id() != current_mat )
147                                        {
148                                                if ( auto mat = element.material.lock() )
149                                                {
150                                                        for ( uint32 i = 0; i < 8; ++i )
151                                                                if ( mat->textures[i] && !pass.binds[i] )
152                                                                        m_context->bind( mat->textures[i], nv::texture_slot( i ) );
153                                                        current_mat = element.material.id();
154                                                }
155                                        }
156
157                                        m_context->get_device()->set_opt_uniform( *program, "nv_flags", unsigned( *element.flags.data() ) );
158                                        m_context->get_device()->set_opt_uniform( *program, "nv_index", unsigned( index ) );
159                                        m_context->apply_engine_uniforms( *program, ss );
160                                        if ( rs.blending != element.blending )
161                                                rs.blending = element.blending;
162
163                                        if ( element.instances > 0 )
164                                                m_context->draw_instanced( TRIANGLES, rs, *program, element.instances, element.va, element.count, element.first );
165                                        else
166                                                m_context->draw( TRIANGLES, rs, *program, element.va, element.count, element.first );
167
168                                        m_statistics[TRIANGLE_COUNT] += ( element.count / 3 ) * max< uint32 >( element.instances, 1 );
169                                        m_statistics[DRAW_CALL]++;
170                                }
171                        }
172                }
173        }
174        m_context->bind( pass.fbuffer, FRAMEBUFFER );
175}
Note: See TracBrowser for help on using the repository browser.