skybox working
[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         if(!(sprog = sdr_man->create_shader_program("default.v.glsl", "default.f.glsl"))) {
40                 return false;
41         }
42
43         /* getting material uniform locations: diffuse, specular, specular exponent (strength) */
44
45         if((diff_loc = sprog->get_uniform_location("diffuse")) == -1) {
46                 fprintf(stderr, "Invalid uniform location: can't find \"diffuse\".\n");
47                 return false;
48         }
49
50         if((spec_loc = sprog->get_uniform_location("specular")) == -1) {
51                 fprintf(stderr, "Invalid uniform location: can't find \"specular\".\n");
52                 return false;
53         }
54
55         if((shin_loc = sprog->get_uniform_location("shininess")) == -1) {
56                 fprintf(stderr, "Invalid uniform location: can't find \"shininess\".\n");
57                 return false;
58         }
59
60         /* uniform locations for matrices */
61
62         if((mmviewproj_loc = sprog->get_uniform_location("mmviewproj")) == -1) {
63                 fprintf(stderr, "Invalid uniform location: can't find \"mmviewproj\".\n");
64                 return false;
65         }
66
67         if((mview_loc = sprog->get_uniform_location("mview")) == -1) {
68                 fprintf(stderr, "Invalid uniform location: can't find \"mview\".\n");
69                 return false;
70         }
71
72         return true;
73 }
74
75 void Renderer::draw() const
76 {
77         if(!camera || !scene)
78                 return;
79
80         if(skytex) {
81                 draw_skybox();
82         }
83
84         if(!sprog->link())
85                 return;
86
87         sprog->use();
88
89         for(size_t i=0; i<scene->objects.size(); i++) {
90                 draw_object(scene->objects[i]);
91         }
92 }
93
94 void Renderer::draw_object(Object *object) const
95 {
96         Material *m = object->material;
97
98         /* setting uniforms for material */
99
100         sprog->set_uniformf(diff_loc, m->diffuse.x, m->diffuse.y, m->diffuse.z, 1);
101         sprog->set_uniformf(spec_loc, m->specular.x, m->specular.y, m->specular.z, 1);
102         sprog->set_uniformf(shin_loc, m->shininess);
103
104         /* texture */
105
106         if(m->dtex)
107                 m->dtex->bind();
108
109         /* setting uniforms for matrices */
110
111         Mat4 mmviewproj = object->transform * camera->get_view_matrix() * mprojection;
112         sprog->set_uniform_matrix(mmviewproj_loc, mmviewproj);
113
114         Mat4 mview = object->transform * camera->get_view_matrix();
115         sprog->set_uniform_matrix(mview_loc, mview);
116
117         object->mesh->update_vertex_data();
118         object->mesh->draw();
119 }
120
121 void Renderer::set_sky_tex(Texture *stex)
122 {
123         if(!skymesh) {
124                 skymesh = gfx_create_mesh();
125                 gen_geosphere(skymesh, 1, 0);
126         }
127         if(!skyprog) {
128                 if(!(skyprog = sdr_man->create_shader_program("sky.v.glsl", "sky.f.glsl")))
129                         return;
130                 if((viewproj_loc = skyprog->get_uniform_location("mviewproj") == -1))
131                         return;
132         }
133         skytex = stex;
134 }
135
136 void Renderer::set_diffuse_sky_tex(Texture *dstex)
137 {
138         dskytex = dstex;
139 }
140
141 void Renderer::draw_skybox() const
142 {
143         if(!skymesh || !skytex)
144                 return;
145
146         gfx_zbuffer(false);
147         gfx_cull_face(GFX_CULL_NONE);
148
149         skytex->bind();
150         skyprog->use();
151
152         Mat4 mviewproj;
153         mviewproj = camera->get_view_matrix().upper3x3() * mprojection;
154         skyprog->set_uniform_matrix(viewproj_loc, mviewproj);
155
156         skymesh->draw();
157
158         gfx_cull_face(GFX_CULL_BACK);
159         gfx_zbuffer(true);
160 }