dungeon_crawler

annotate prototype/src/light.cc @ 77:d89b403f630b

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