dungeon_crawler

view prototype/src/light.cc @ 70:f55ddab0f3a4

"fixed" the disappearing lights issue
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 09 Oct 2012 02:54:01 +0300
parents aa86119e3295
children d89b403f630b
line source
1 #include <stdlib.h>
2 #include "opengl.h"
3 #include "light.h"
4 #include "renderer.h"
5 #include "timer.h"
7 unsigned int PointLight::sph_vbo = 0;
9 Light::Light(const Color &col)
10 : color(col)
11 {
12 intensity = 1.0;
13 vbo = 0;
14 num_faces = 0;
16 flicker_offset = 2.0 * (float)rand() / (float)RAND_MAX;
17 }
19 Light::~Light() {}
21 void Light::set_intensity(float val)
22 {
23 intensity = val;
24 }
26 void Light::set_color(const Color &col)
27 {
28 color = col;
29 }
31 Color Light::get_color(bool with_intensity) const
32 {
33 return with_intensity ? color * intensity : color;
34 }
36 void Light::use(int id) const
37 {
38 glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, &color.x);
39 glLightfv(GL_LIGHT0 + id, GL_SPECULAR, &color.x);
40 }
42 void Light::draw() const
43 {
44 if(!vbo) {
45 if(!((Light*)this)->create_mesh()) {
46 return;
47 }
48 }
50 glEnableClientState(GL_VERTEX_ARRAY);
51 glBindBuffer(GL_ARRAY_BUFFER, vbo);
52 glVertexPointer(3, GL_FLOAT, 0, 0);
54 glDrawArrays(GL_TRIANGLES, 0, num_faces * 3);
56 glBindBuffer(GL_ARRAY_BUFFER, 0);
57 glDisableClientState(GL_VERTEX_ARRAY);
58 }
60 bool Light::create_mesh()
61 {
62 fprintf(stderr, "%s: undefined\n", __FUNCTION__);
63 return false;
64 }
67 PointLight::PointLight()
68 : Light(Color(1.0, 1.0, 1.0))
69 {
70 atten[0] = 1.0f;
71 atten[1] = 0.0f;
72 atten[2] = 0.0f;
73 radius = 1.0;
74 }
76 PointLight::PointLight(const Vector3 &pos, const Color &col)
77 : Light(col)
78 {
79 this->pos = pos;
80 atten[0] = 1.0f;
81 atten[1] = 0.0f;
82 atten[2] = 0.0f;
83 radius = 1.0;
84 }
86 void PointLight::set_position(const Vector3 &pos)
87 {
88 this->pos = pos;
89 }
91 const Vector3 &PointLight::get_position() const
92 {
93 return pos;
94 }
96 void PointLight::set_attenuation(float att_const, float att_lin, float att_quad)
97 {
98 atten[0] = att_const;
99 atten[1] = att_lin;
100 atten[2] = att_quad;
101 }
103 void PointLight::set_radius(float rad)
104 {
105 radius = rad;
106 }
108 float PointLight::get_radius() const
109 {
110 return radius;
111 }
113 void PointLight::use(int id) const
114 {
115 float lpos[] = {pos.x, pos.y, pos.z, 1.0f};
116 glLightfv(GL_LIGHT0 + id, GL_POSITION, lpos);
117 glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, atten[0]);
118 glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, atten[1]);
119 glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, atten[2]);
120 }
122 void PointLight::draw() const
123 {
124 unsigned int sdr = rend->get_current_program();
125 if(sdr) {
126 int loc;
127 if((loc = glGetUniformLocation(sdr, "light_radius")) != -1) {
128 glUniform1f(loc, radius);
129 }
130 if((loc = glGetUniformLocation(sdr, "light_color")) != -1) {
131 float t = get_time_msec() / 1000.0 + flicker_offset * 4.0;
132 float intens = fbm1(t * 2.0, 2) * 0.5 + 1.0;
133 glUniform3f(loc, color.x * intens, color.y * intens, color.z * intens);
134 }
135 }
137 glMatrixMode(GL_MODELVIEW);
138 glPushMatrix();
139 glTranslatef(pos.x, pos.y, pos.z);
140 glScalef(radius, radius, radius);
142 Light::draw();
144 glPopMatrix();
145 }
149 Vector3 sphvertex(float u, float v)
150 {
151 float theta = u * M_PI * 2.0;
152 float phi = v * M_PI;
154 Vector3 res;
155 res.x = sin(theta) * sin(phi);
156 res.y = cos(phi);
157 res.z = cos(theta) * sin(phi);
158 return res;
159 }
162 bool PointLight::create_mesh()
163 {
164 /*if(sph_vbo) {
165 vbo = sph_vbo;
166 return true;
167 }*/
169 printf("building sphere mesh for point light drawing\n");
171 const static int udiv = 8;
172 const static int vdiv = 4;
174 int nquads = udiv * vdiv;
175 num_faces = nquads * 2;
176 int nverts = num_faces * 3;
178 float du = 1.0 / (float)udiv;
179 float dv = 1.0 / (float)vdiv;
181 glGenBuffers(1, &sph_vbo);
182 glBindBuffer(GL_ARRAY_BUFFER, sph_vbo);
183 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(Vector3), 0, GL_STATIC_DRAW);
185 Vector3 *vptr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
187 for(int i=0; i<vdiv; i++) {
188 float v = (float)i / (float)vdiv;
189 for(int j=0; j<udiv; j++) {
190 float u = (float)j / (float)udiv;
192 *vptr++ = sphvertex(u, v + dv);
193 *vptr++ = sphvertex(u + du, v);
194 *vptr++ = sphvertex(u, v);
196 *vptr++ = sphvertex(u, v + dv);
197 *vptr++ = sphvertex(u + du, v + dv);
198 *vptr++ = sphvertex(u + du, v);
199 }
200 }
201 glUnmapBuffer(GL_ARRAY_BUFFER);
202 glBindBuffer(GL_ARRAY_BUFFER, 0);
204 vbo = sph_vbo;
205 return true;
206 }
208 void set_light(int id, const Light *lt)
209 {
210 if(lt) {
211 glDisable(GL_LIGHT0 + id);
212 } else {
213 glEnable(GL_LIGHT0 + id);
214 lt->use(id);
215 }
216 }