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