nuclear@38: #include nuclear@4: #include "opengl.h" nuclear@4: #include "light.h" nuclear@33: #include "renderer.h" nuclear@38: #include "timer.h" nuclear@4: nuclear@60: unsigned int PointLight::sph_vbo = 0; nuclear@60: nuclear@4: Light::Light(const Color &col) nuclear@4: : color(col) nuclear@4: { nuclear@4: intensity = 1.0; nuclear@23: vbo = 0; nuclear@23: num_faces = 0; nuclear@38: nuclear@38: flicker_offset = 2.0 * (float)rand() / (float)RAND_MAX; nuclear@4: } nuclear@4: nuclear@4: Light::~Light() {} nuclear@4: nuclear@4: void Light::set_intensity(float val) nuclear@4: { nuclear@4: intensity = val; nuclear@4: } nuclear@4: nuclear@4: void Light::set_color(const Color &col) nuclear@4: { nuclear@4: color = col; nuclear@4: } nuclear@4: nuclear@21: Color Light::get_color(bool with_intensity) const nuclear@21: { nuclear@21: return with_intensity ? color * intensity : color; nuclear@21: } nuclear@21: nuclear@4: void Light::use(int id) const nuclear@4: { nuclear@4: glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, &color.x); nuclear@4: glLightfv(GL_LIGHT0 + id, GL_SPECULAR, &color.x); nuclear@4: } nuclear@4: nuclear@23: void Light::draw() const nuclear@23: { nuclear@23: if(!vbo) { nuclear@23: if(!((Light*)this)->create_mesh()) { nuclear@23: return; nuclear@23: } nuclear@23: } nuclear@23: nuclear@23: glEnableClientState(GL_VERTEX_ARRAY); nuclear@23: glBindBuffer(GL_ARRAY_BUFFER, vbo); nuclear@23: glVertexPointer(3, GL_FLOAT, 0, 0); nuclear@23: nuclear@23: glDrawArrays(GL_TRIANGLES, 0, num_faces * 3); nuclear@23: nuclear@27: glBindBuffer(GL_ARRAY_BUFFER, 0); nuclear@23: glDisableClientState(GL_VERTEX_ARRAY); nuclear@23: } nuclear@23: nuclear@23: bool Light::create_mesh() nuclear@23: { nuclear@23: fprintf(stderr, "%s: undefined\n", __FUNCTION__); nuclear@23: return false; nuclear@23: } nuclear@23: nuclear@4: nuclear@4: PointLight::PointLight() nuclear@33: : Light(Color(1.0, 1.0, 1.0)) nuclear@4: { nuclear@4: atten[0] = 1.0f; nuclear@4: atten[1] = 0.0f; nuclear@4: atten[2] = 0.0f; nuclear@21: radius = 1.0; nuclear@4: } nuclear@4: nuclear@4: PointLight::PointLight(const Vector3 &pos, const Color &col) nuclear@4: : Light(col) nuclear@4: { nuclear@4: this->pos = pos; nuclear@4: atten[0] = 1.0f; nuclear@4: atten[1] = 0.0f; nuclear@4: atten[2] = 0.0f; nuclear@21: radius = 1.0; nuclear@4: } nuclear@4: nuclear@4: void PointLight::set_position(const Vector3 &pos) nuclear@4: { nuclear@4: this->pos = pos; nuclear@4: } nuclear@4: nuclear@46: const Vector3 &PointLight::get_position() const nuclear@46: { nuclear@46: return pos; nuclear@46: } nuclear@46: nuclear@4: void PointLight::set_attenuation(float att_const, float att_lin, float att_quad) nuclear@4: { nuclear@4: atten[0] = att_const; nuclear@4: atten[1] = att_lin; nuclear@4: atten[2] = att_quad; nuclear@4: } nuclear@4: nuclear@21: void PointLight::set_radius(float rad) nuclear@21: { nuclear@21: radius = rad; nuclear@21: } nuclear@21: nuclear@21: float PointLight::get_radius() const nuclear@21: { nuclear@21: return radius; nuclear@21: } nuclear@21: nuclear@4: void PointLight::use(int id) const nuclear@4: { nuclear@4: float lpos[] = {pos.x, pos.y, pos.z, 1.0f}; nuclear@4: glLightfv(GL_LIGHT0 + id, GL_POSITION, lpos); nuclear@4: glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, atten[0]); nuclear@4: glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, atten[1]); nuclear@4: glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, atten[2]); nuclear@4: } nuclear@4: nuclear@23: void PointLight::draw() const nuclear@23: { nuclear@41: unsigned int sdr = rend->get_current_program(); nuclear@33: if(sdr) { nuclear@33: int loc; nuclear@33: if((loc = glGetUniformLocation(sdr, "light_radius")) != -1) { nuclear@33: glUniform1f(loc, radius); nuclear@33: } nuclear@33: if((loc = glGetUniformLocation(sdr, "light_color")) != -1) { nuclear@38: float t = get_time_msec() / 1000.0 + flicker_offset * 4.0; nuclear@38: float intens = fbm1(t * 2.0, 2) * 0.5 + 1.0; nuclear@38: glUniform3f(loc, color.x * intens, color.y * intens, color.z * intens); nuclear@33: } nuclear@33: } nuclear@33: nuclear@29: glMatrixMode(GL_MODELVIEW); nuclear@29: glPushMatrix(); nuclear@29: glTranslatef(pos.x, pos.y, pos.z); nuclear@29: glScalef(radius, radius, radius); nuclear@23: nuclear@23: Light::draw(); nuclear@23: nuclear@29: glPopMatrix(); nuclear@23: } nuclear@23: nuclear@23: nuclear@23: nuclear@23: Vector3 sphvertex(float u, float v) nuclear@23: { nuclear@23: float theta = u * M_PI * 2.0; nuclear@23: float phi = v * M_PI; nuclear@23: nuclear@23: Vector3 res; nuclear@25: res.x = sin(theta) * sin(phi); nuclear@25: res.y = cos(phi); nuclear@25: res.z = cos(theta) * sin(phi); nuclear@23: return res; nuclear@23: } nuclear@23: nuclear@23: nuclear@23: bool PointLight::create_mesh() nuclear@23: { nuclear@60: if(sph_vbo) { nuclear@60: vbo = sph_vbo; nuclear@60: return true; nuclear@60: } nuclear@60: nuclear@60: printf("building sphere mesh for point light drawing\n"); nuclear@60: nuclear@23: const static int udiv = 8; nuclear@23: const static int vdiv = 4; nuclear@23: nuclear@23: int nquads = udiv * vdiv; nuclear@23: num_faces = nquads * 2; nuclear@23: int nverts = num_faces * 3; nuclear@23: nuclear@23: float du = 1.0 / (float)udiv; nuclear@23: float dv = 1.0 / (float)vdiv; nuclear@23: nuclear@60: glGenBuffers(1, &sph_vbo); nuclear@60: glBindBuffer(GL_ARRAY_BUFFER, sph_vbo); nuclear@23: glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(Vector3), 0, GL_STATIC_DRAW); nuclear@23: nuclear@23: Vector3 *vptr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); nuclear@23: nuclear@23: for(int i=0; iuse(id); nuclear@4: } nuclear@4: }