18c93bb4fa9755854aa28a53dae1520969b7d271
[demo] / src / renderer.cc
1 #include <GL/glew.h>
2
3 #include "global.h"
4 #include "gfxapi.h"
5
6 #include "camera.h"
7 #include "mesh.h"
8 #include "meshgen.h"
9 #include "object.h"
10 #include "renderer.h"
11 #include "scene.h"
12 #include "shader.h"
13 #include "shader_manager.h"
14 #include "texture.h"
15 #include "uniforms.h"
16
17 #undef DRAW_NORMALS
18
19 /* skybox */
20
21 static Mesh *skymesh; /* it will be used by many renderers => no destroy */
22 static ShaderProgram *skyprog;
23
24 Renderer::Renderer()
25 {
26         scene = 0;
27         camera = 0;
28         sprog = 0;
29
30         skytex = 0;
31         dskytex = 0;
32
33         fog_density = 0;
34
35         vbuf = fbuf = svbuf = 0;
36 }
37
38 Renderer::~Renderer()
39 {
40         delete vbuf;
41         delete fbuf;
42         delete svbuf;
43 }
44
45 bool Renderer::create()
46 {
47         //debug
48         // if(!(nprog = sdr_man->create_shader_program("debug.v.glsl", "debug.f.glsl"))) {
49         //      fprintf(stderr, "Failed to load debug shaders.\n");
50         // }
51
52         vbuf = gfx_create_uniform_buffer();
53         if(!vbuf->create(sizeof vu)) {
54                 fprintf(stderr, "Failed to create uniform buffer.\n");
55                 return false;
56         }
57
58         fbuf = gfx_create_uniform_buffer();
59         if(!fbuf->create(sizeof fu)) {
60                 fprintf(stderr, "Failed to create uniform buffer.\n");
61                 return false;
62         }
63
64         svbuf = gfx_create_uniform_buffer();
65         if(!svbuf->create(sizeof svu)) {
66                 fprintf(stderr, "Failed to create uniform buffer.\n");
67                 return false;
68         }
69
70         if(!(sprog = sdr_man->create_shader_program("default.v.glsl", "default.f.glsl"))) {
71                 return false;
72         }
73
74         return true;
75 }
76
77 void Renderer::draw()
78 {
79         if(!camera || !scene)
80                 return;
81
82         if(skytex) {
83                 draw_skybox();
84
85                 if(dskytex) {
86                         dskytex->bind(1);
87                 }
88         }
89
90         if(!sprog->link())
91                 return;
92
93         sprog->use();
94
95         for(size_t i=0; i<scene->objects.size(); i++) {
96                 draw_object(scene->objects[i]);
97         }
98 }
99
100 void Renderer::draw_object(Object *object)
101 {
102         Material *m = object->material;
103
104         /* setting uniforms for material */
105
106         fu.diffuse = Vec4(m->diffuse.x, m->diffuse.y, m->diffuse.z, 1.0);
107         fu.specular = Vec4(m->specular.x, m->specular.y, m->specular.z, 1.0);
108         fu.shininess = m->shininess;
109         fu.fog_density = fog_density;
110
111         fbuf->update(&fu);
112         fbuf->bind(SHADING_UNIFORMS);
113
114         /* texture */
115
116         if(m->dtex)
117                 m->dtex->bind(0);
118
119         /* setting uniforms for matrices */
120
121         vu.mview = object->transform * camera->get_view_matrix();
122         vu.mmviewproj = object->transform * camera->get_view_matrix() * mprojection;
123         vu.mmod = object->transform.upper3x3();
124
125         vbuf->update(&vu);
126         vbuf->bind(MATRIX_UNIFORMS);
127
128         object->mesh->draw();
129
130         // debug
131 #ifdef DRAW_NORMALS
132         if(nprog) {
133                 vu.mmviewproj = mmviewproj;
134                 vbuf->update(&vu);
135                 vbuf->bind(MATRIX_UNIFORMS);
136
137                 nprog->use();
138                 object->mesh->draw_normals(1.0);
139         }
140 #endif
141 }
142
143 void Renderer::set_sky_tex(Texture *stex)
144 {
145         if(!skymesh) {
146                 skymesh = gfx_create_mesh();
147                 gen_geosphere(skymesh, 1, 0);
148         }
149         if(!skyprog) {
150                 if(!(skyprog = sdr_man->create_shader_program("sky.v.glsl", "sky.f.glsl")))
151                         return;
152         }
153         skytex = stex;
154 }
155
156 void Renderer::set_diffuse_sky_tex(Texture *dstex)
157 {
158         dskytex = dstex;
159 }
160
161 void Renderer::draw_skybox()
162 {
163         if(!skymesh || !skytex)
164                 return;
165
166         gfx_zbuffer(false);
167         gfx_cull_face(GFX_CULL_NONE);
168
169         skytex->bind();
170         skyprog->use();
171
172         svu.mviewproj = camera->get_view_matrix().upper3x3() * mprojection;
173         svbuf->update(&svu);
174         svbuf->bind(SKY_MATRIX_UNIFORMS);
175
176         skymesh->draw();
177
178         gfx_cull_face(GFX_CULL_BACK);
179         gfx_zbuffer(true);
180 }