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