dungeon_crawler

view prototype/src/light.cc @ 38:862461b686f4

start work on particle systems
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 29 Aug 2012 03:22:36 +0300
parents 0357994effe2
children acfe0c0110fc
line source
1 #include <stdlib.h>
2 #include "opengl.h"
3 #include "light.h"
4 #include "renderer.h"
5 #include "timer.h"
7 Light::Light(const Color &col)
8 : color(col)
9 {
10 intensity = 1.0;
11 vbo = 0;
12 num_faces = 0;
14 flicker_offset = 2.0 * (float)rand() / (float)RAND_MAX;
15 }
17 Light::~Light() {}
19 void Light::set_intensity(float val)
20 {
21 intensity = val;
22 }
24 void Light::set_color(const Color &col)
25 {
26 color = col;
27 }
29 Color Light::get_color(bool with_intensity) const
30 {
31 return with_intensity ? color * intensity : color;
32 }
34 void Light::use(int id) const
35 {
36 glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, &color.x);
37 glLightfv(GL_LIGHT0 + id, GL_SPECULAR, &color.x);
38 }
40 void Light::draw() const
41 {
42 if(!vbo) {
43 if(!((Light*)this)->create_mesh()) {
44 return;
45 }
46 }
48 glEnableClientState(GL_VERTEX_ARRAY);
49 glBindBuffer(GL_ARRAY_BUFFER, vbo);
50 glVertexPointer(3, GL_FLOAT, 0, 0);
52 glDrawArrays(GL_TRIANGLES, 0, num_faces * 3);
54 glBindBuffer(GL_ARRAY_BUFFER, 0);
55 glDisableClientState(GL_VERTEX_ARRAY);
56 }
58 bool Light::create_mesh()
59 {
60 fprintf(stderr, "%s: undefined\n", __FUNCTION__);
61 return false;
62 }
65 PointLight::PointLight()
66 : Light(Color(1.0, 1.0, 1.0))
67 {
68 atten[0] = 1.0f;
69 atten[1] = 0.0f;
70 atten[2] = 0.0f;
71 radius = 1.0;
72 }
74 PointLight::PointLight(const Vector3 &pos, const Color &col)
75 : Light(col)
76 {
77 this->pos = pos;
78 atten[0] = 1.0f;
79 atten[1] = 0.0f;
80 atten[2] = 0.0f;
81 radius = 1.0;
82 }
84 void PointLight::set_position(const Vector3 &pos)
85 {
86 this->pos = pos;
87 }
89 void PointLight::set_attenuation(float att_const, float att_lin, float att_quad)
90 {
91 atten[0] = att_const;
92 atten[1] = att_lin;
93 atten[2] = att_quad;
94 }
96 void PointLight::set_radius(float rad)
97 {
98 radius = rad;
99 }
101 float PointLight::get_radius() const
102 {
103 return radius;
104 }
106 void PointLight::use(int id) const
107 {
108 float lpos[] = {pos.x, pos.y, pos.z, 1.0f};
109 glLightfv(GL_LIGHT0 + id, GL_POSITION, lpos);
110 glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, atten[0]);
111 glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, atten[1]);
112 glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, atten[2]);
113 }
115 void PointLight::draw() const
116 {
117 unsigned int sdr = get_deferred_shader();
118 if(sdr) {
119 int loc;
120 if((loc = glGetUniformLocation(sdr, "light_radius")) != -1) {
121 glUniform1f(loc, radius);
122 }
123 if((loc = glGetUniformLocation(sdr, "light_color")) != -1) {
124 float t = get_time_msec() / 1000.0 + flicker_offset * 4.0;
125 float intens = fbm1(t * 2.0, 2) * 0.5 + 1.0;
126 glUniform3f(loc, color.x * intens, color.y * intens, color.z * intens);
127 }
128 }
130 glMatrixMode(GL_MODELVIEW);
131 glPushMatrix();
132 glTranslatef(pos.x, pos.y, pos.z);
133 glScalef(radius, radius, radius);
135 Light::draw();
137 glPopMatrix();
138 }
142 Vector3 sphvertex(float u, float v)
143 {
144 float theta = u * M_PI * 2.0;
145 float phi = v * M_PI;
147 Vector3 res;
148 res.x = sin(theta) * sin(phi);
149 res.y = cos(phi);
150 res.z = cos(theta) * sin(phi);
151 return res;
152 }
155 bool PointLight::create_mesh()
156 {
157 const static int udiv = 8;
158 const static int vdiv = 4;
160 int nquads = udiv * vdiv;
161 num_faces = nquads * 2;
162 int nverts = num_faces * 3;
164 float du = 1.0 / (float)udiv;
165 float dv = 1.0 / (float)vdiv;
167 glGenBuffers(1, &vbo);
168 glBindBuffer(GL_ARRAY_BUFFER, vbo);
169 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(Vector3), 0, GL_STATIC_DRAW);
171 Vector3 *vptr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
173 for(int i=0; i<vdiv; i++) {
174 float v = (float)i / (float)vdiv;
175 for(int j=0; j<udiv; j++) {
176 float u = (float)j / (float)udiv;
178 *vptr++ = sphvertex(u, v + dv);
179 *vptr++ = sphvertex(u + du, v);
180 *vptr++ = sphvertex(u, v);
182 *vptr++ = sphvertex(u, v + dv);
183 *vptr++ = sphvertex(u + du, v + dv);
184 *vptr++ = sphvertex(u + du, v);
185 }
186 }
187 glUnmapBuffer(GL_ARRAY_BUFFER);
188 glBindBuffer(GL_ARRAY_BUFFER, 0);
189 return true;
190 }
192 void set_light(int id, const Light *lt)
193 {
194 if(lt) {
195 glDisable(GL_LIGHT0 + id);
196 } else {
197 glEnable(GL_LIGHT0 + id);
198 lt->use(id);
199 }
200 }