093b71e6efa83d5babd3a5208d3ef72a064b8802
[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->draw();
123
124         /* debug
125         if(nprog) {
126                 int loc = nprog->get_uniform_location("mmviewproj");
127                 if(loc != -1) {
128                         nprog->set_uniform_matrix(loc, mmviewproj);
129                 }
130                 nprog->use();
131                 object->mesh->draw_normals(1.0);
132         }*/
133
134         // if(m->dtex)
135         //      m->dtex->unbind();
136 }
137
138 void Renderer::set_sky_tex(Texture *stex)
139 {
140         if(!skymesh) {
141                 skymesh = gfx_create_mesh();
142                 gen_geosphere(skymesh, 1, 0);
143         }
144         if(!skyprog) {
145                 if(!(skyprog = sdr_man->create_shader_program("sky.v.glsl", "sky.f.glsl")))
146                         return;
147                 if((viewproj_loc = skyprog->get_uniform_location("mviewproj") == -1))
148                         return;
149         }
150         skytex = stex;
151 }
152
153 void Renderer::set_diffuse_sky_tex(Texture *dstex)
154 {
155         dskytex = dstex;
156 }
157
158 void Renderer::draw_skybox() const
159 {
160         if(!skymesh || !skytex)
161                 return;
162
163         gfx_zbuffer(false);
164         gfx_cull_face(GFX_CULL_NONE);
165
166         skytex->bind();
167         skyprog->use();
168
169         Mat4 mviewproj;
170         mviewproj = camera->get_view_matrix().upper3x3() * mprojection;
171         skyprog->set_uniform_matrix(viewproj_loc, mviewproj);
172
173         skymesh->draw();
174
175         gfx_cull_face(GFX_CULL_BACK);
176         gfx_zbuffer(true);
177 }