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