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