//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include GLLenseFlare *GLLenseFlare::instance_ = 0; GLLenseFlare *GLLenseFlare::instance() { if (!instance_) { instance_ = new GLLenseFlare; } return instance_; } GLLenseFlare::GLLenseFlare() : shineTic_(0) { } GLLenseFlare::~GLLenseFlare() { } void GLLenseFlare::setFlare(int index, int type, float scale, float loc, Vector &color1, Vector &color2, Vector &color3, Vector &color4, float colorScale) { if (index > 2) loc *= 500; flare_[index].type = type; flare_[index].loc = loc; flare_[index].scale = scale; flare_[index].color1 = color1 * colorScale; flare_[index].color2 = color2 * colorScale; flare_[index].color3 = color3 * colorScale; flare_[index].color4 = color4 * colorScale; } void GLLenseFlare::init(ProgressCounter *counter) { if (counter) counter->setNewOp("Lens Flares"); Vector red1(1.0f, 0.0f, 0.0f); Vector green1(0.0f, 1.0f, 0.0f); Vector blue1(0.0f, 0.0f, 1.0f); Vector red2(1.0f, 0.0f, 0.0f); Vector green2(0.5f, 1.0f, 0.0f); Vector blue2(0.5f, 0.0f, 1.0f); Vector red3(1.0f, 0.5f, 0.0f); Vector green3(0.0f, 1.0f, 0.0f); Vector blue3(0.0f, 0.5f, 1.0f); Vector red4(1.0f, 0.0f, 0.5f); Vector green4(0.0f, 1.0f, 0.5f); Vector blue4(0.0f, 0.0f, 1.0f); setFlare(0, -1, 1.0f, 0.3f, blue1, blue2, blue3, blue4, 1.0f); setFlare(1, -1, 1.0f, 0.2f, green1, green2, green3, green4, 1.f); setFlare(2, -1, 1.0f, 0.25f, red1, red2, red3, red4, 1.0f); /* Flares, ordered to eliminate redundant texture binds */ setFlare(3, 1, 0.5f, 0.2f, red1, red2, red3, red4, 0.3f); setFlare(4, 2, 1.3f, 0.04f, red1, red2, red3, red4, 0.6f); setFlare(5, 3, 1.0f, 0.1f, red1, red2, red3, red4, 0.4f); setFlare(6, 3, 0.2f, 0.05f, red1, red2, red3, red4, 0.3f); setFlare(7, 0, 0.0f, 0.04f, red1, red2, red3, red4, 0.3f); setFlare(8, 5, -0.25f, 0.07f, red1, red2, red3, red4, 0.5f); setFlare(9, 5, -0.4f, 0.02f, red1, red2, red3, red4, 0.6f); setFlare(10, 5, -0.6f, 0.04f, red1, red2, red3, red4, 0.4f); setFlare(11, 5, -1.0f, 0.03f, red1, red2, red3, red4, 0.2f); int i; for (i = 0; i < 10; i++) { if (counter) counter->setNewPercentage(float (i) / 16.0f * 100.0f); GLLuminance bitmap(getDataFile(formatString("data/textures/lensflare/shine%d.bw", i))); shines_[i].create(bitmap, GL_LUMINANCE); } for (i = 0; i < 6; i++) { if (counter) counter->setNewPercentage(float (i+10) / 16.0f * 100.0f); GLLuminance bitmap(getDataFile(formatString("data/textures/lensflare/flare%d.bw", i))); flares_[i].create(bitmap, GL_LUMINANCE); } } void GLLenseFlare::draw(Vector &flarePos, bool fullFlare, int colorNo, float size, float alpha) { if (GLCameraFrustum::instance()->sphereInFrustum(flarePos, 5)) { Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos(); Vector &cameraAt = GLCamera::getCurrentCamera()->getLookAt(); Vector view_dir = flarePos - cameraPos; Vector centre = cameraPos + view_dir.Normalize() * 20.0f; Vector axis = (cameraAt - flarePos).Normalize(); Vector dx = axis.Normalize(); Vector dy = (dx * view_dir).Normalize(); dx = -(dy * view_dir).Normalize(); dx *= 2.0f * size; dy *= 2.0f * size; glDepthMask(GL_FALSE); GLState currentState(GLState::BLEND_ON); glBlendFunc(GL_ONE, GL_ONE); GLState *afterThreeState = 0; int endTexture = 12; if (!fullFlare) endTexture = 3; for (int i=0; isphereInFrustum(flarePos, 5)) { return; } Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos(); Vector &cameraAt = GLCamera::getCurrentCamera()->getLookAt(); Vector flare_dir = flareDir;// .Normalize(); // Should already be normalized Vector view_dir = (flarePos - cameraPos).Normalize(); float dotP = (float) flare_dir.dotP(view_dir); if (dotP <= 0.2f) return; Vector centre = cameraPos + view_dir * 20.0f; Vector axis = (cameraAt - flarePos).Normalize(); Vector dx = axis.Normalize(); Vector dy = (dx * view_dir).Normalize(); dx = -(dy * view_dir).Normalize(); dx *= 2.0f * (dotP - 0.2f); dy *= 2.0f * (dotP - 0.2f); glDepthMask(GL_FALSE); GLState currentState(GLState::BLEND_ON | GLState::TEXTURE_ON); glBlendFunc(GL_ONE, GL_ONE); for (int i=0; i<3; i++) { switch(colorNo) { case 0: glColor3fv(flare_[i].color1); break; case 1: glColor3fv(flare_[i].color2); break; case 2: glColor3fv(flare_[i].color3); break; case 3: glColor3fv(flare_[i].color4); break; } shines_[shineTic_].draw(); shineTic_ = (shineTic_ + 1) % 10; Vector position = flarePos + (axis * flare_[i].loc); Vector sx = dx * flare_[i].scale; Vector sy = dy * flare_[i].scale; glBegin(GL_QUADS); static Vector tmp; tmp = position + sx + sy; glTexCoord2f(0.0, 0.0); glVertex3fv(tmp); tmp = (position - sx) + sy; glTexCoord2f(1.0, 0.0); glVertex3fv(tmp); tmp = (position - sx) - sy; glTexCoord2f(1.0, 1.0); glVertex3fv(tmp); tmp = (position + sx) - sy; glTexCoord2f(0.0, 1.0); glVertex3fv(tmp); glEnd(); } glDepthMask(GL_TRUE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }