X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2F3dengfx%2Fsrc%2Fdsys%2Ffx.cpp;fp=src%2F3dengfx%2Fsrc%2Fdsys%2Ffx.cpp;h=c089bd381c5d07f27f25b2d06a1795123b1f1980;hb=6e23259dbabaeb1711a2a5ca25b9cb421f693759;hp=0000000000000000000000000000000000000000;hpb=fe068fa879814784c45e0cb2e65dac489e8f5594;p=summerhack diff --git a/src/3dengfx/src/dsys/fx.cpp b/src/3dengfx/src/dsys/fx.cpp new file mode 100644 index 0000000..c089bd3 --- /dev/null +++ b/src/3dengfx/src/dsys/fx.cpp @@ -0,0 +1,513 @@ +/* +This file is part of the 3dengfx demo system. + +Copyright (c) 2004, 2005 John Tsiombikas + +This program 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. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "3dengfx_config.h" + +#include +#include +#include "fx.hpp" +#include "dsys.hpp" +#include "script.h" +#include "3dengfx/3dengfx.hpp" +#include "common/err_msg.h" + + +static bool str_to_color(const char *str, Color *col); + + +void dsys::radial_blur(Texture *tex, float ammount, const Vector2 &origin, bool additive) { + Vector2 c1(0.0f, 0.0f), c2(1.0f, 1.0f); + + set_alpha_blending(true); + if(additive) { + set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE); + } else { + set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + } + + ammount += 1.0f; + int quad_count = (int)(ammount * 20.0f); + float dscale = (ammount - 1.0f) / (float)quad_count; + float scale = 1.0f; + for(int i=0; i= start && (long)time < end) { + scalar_t t = (scalar_t)time / 1000.0; + scalar_t dt = (scalar_t)dur / 1000.0; + scalar_t wt = (scalar_t)when / 1000.0; + scalar_t half_dt = dt / 2.0; + + scalar_t alpha = cos(pi * (t - wt) / half_dt); + + dsys::overlay(0, Vector3(0,0), Vector3(1,1), Color(col.r, col.g, col.b, alpha)); + } +} + + + +// ------------- Image Effect manager -------------- + +using std::list; +using namespace dsys; + +static list fx_list; + +void dsys::add_image_fx(ImageFx *fx) { + fx_list.push_back(fx); +} + +void dsys::remove_image_fx(ImageFx *fx) { + fx_list.erase(find(fx_list.begin(), fx_list.end(), fx)); +} + +void dsys::apply_image_fx(unsigned long time) { + list::iterator iter = fx_list.begin(); + + while(iter != fx_list.end()) { + (*iter++)->apply(time); + } +} + + +// -------------- Image Effect class -------------- + +ImageFx::ImageFx() { + time = 0; + duration = 0; +} + +ImageFx::~ImageFx() {} + +bool ImageFx::parse_script_args(const char **args) { + long t, d; + + if(!args[0] || (t = str_to_time(args[0])) == -1) { + return false; + } + + if(!args[1] || (d = str_to_time(args[1])) == -1) { + return false; + } + + time = t; + duration = d; + return true; +} + +void ImageFx::set_time(unsigned long time) { + this->time = time; +} + +void ImageFx::set_duration(unsigned long dur) { + duration = dur; +} + + +// ------------- Negative (inverse video) effect --------------- + +FxNegative::~FxNegative() {} + +void FxNegative::apply(unsigned long time) { + if(time < this->time || time > this->time + duration) return; + + negative(); +} + +// ------------ Screen Flash ------------- + +FxFlash::~FxFlash() {} + +FxFlash::FxFlash() { + color = Color(1.0, 1.0, 1.0); +} + +bool FxFlash::parse_script_args(const char **args) { + if(!ImageFx::parse_script_args(args)) { + return false; + } + + if(args[2]) { + if(!str_to_color(args[2], &color)) return false; + } + + return true; +} + +void FxFlash::set_color(const Color &col) { + color = col; +} + +void FxFlash::apply(unsigned long time) { + flash(time, this->time, duration, color); +} + + +// ------------- Fade in/out ------------- + +FxFade::FxFade() { + color1 = Color(0.0, 0.0, 0.0); + color2 = Color(1.0, 1.0, 1.0); + tex1 = tex2 = 0; +} + +FxFade::~FxFade() {} + +bool FxFade::parse_script_args(const char **args) { + if(!ImageFx::parse_script_args(args)) { + return false; + } + + if(args[2]) { + if(!str_to_color(args[2], &color1)) return false; + } + + if(args[3] && !(args[3][0] == '0' && args[3][1] == 0)) { + // texture register? (t0, t1, t2, t3) + if(args[3][0] == 't' && isdigit(args[3][1]) && !args[3][2]) { + int reg = args[3][1] - '0'; + if(reg > 3) return false; + tex1 = dsys::tex[reg]; + } else { // or a texture from file? + if(!(tex1 = get_texture(args[3]))) { + return false; + } + } + } + + if(args[4]) { + if(!str_to_color(args[4], &color2)) return false; + } + + if(args[5] && !(args[5][0] == '0' && args[5][1] == 0)) { + // texture register? (t0, t1, t2, t3) + if(args[5][0] == 't' && isdigit(args[5][1]) && !args[5][2]) { + int reg = args[5][1] - '0'; + if(reg > 3) return false; + tex2 = dsys::tex[reg]; + } else { // or a texture from file? + if(!(tex2 = get_texture(args[5]))) { + return false; + } + } + } + + return true; +} + +void FxFade::apply(unsigned long time) { + if(time >= this->time && time < this->time + duration) { + float fsec = (float)(time - this->time) / 1000.0; + float t = fsec / ((float)duration / 1000.0); + + if(tex1) { + set_texture(0, tex1); + enable_texture_unit(0); + } + + if(tex2) { + set_texture(1, tex2); + enable_texture_unit(1); + + set_texture_constant(1, t); + set_texture_unit_color(1, TOP_LERP, TARG_PREV, TARG_TEXTURE, TARG_CONSTANT); + } + + set_alpha_blending(true); + set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); + set_lighting(false); + + Color col = color1 + (color2 - color1) * t; + col.a = color1.a + (color2.a - color1.a) * t; + + draw_scr_quad(Vector2(0, 0), Vector2(1, 1), col); + + set_lighting(true); + set_alpha_blending(false); + + if(tex1) disable_texture_unit(0); + if(tex2) disable_texture_unit(1); + } +} + +// ------------ Image Overlay ------------ + + +FxOverlay::FxOverlay() { + tex = 0; + shader = 0; +} + +FxOverlay::~FxOverlay() { + delete shader; +} + +bool FxOverlay::parse_script_args(const char **args) { + if(!ImageFx::parse_script_args(args)) { + return false; + } + if(!args[2]) return false; + + // texture register? (t0, t1, t2, t3) + if(args[2][0] == 't' && isdigit(args[2][1]) && !args[2][2]) { + int reg = args[2][1] - '0'; + if(reg > 3) return false; + tex = dsys::tex[reg]; + } else { // or a texture from file? + if(!(tex = get_texture(args[2]))) { + return false; + } + } + + // check if a shader is specified + if(args[3]) { + Shader sdr = get_shader(args[3], PROG_PIXEL); + if(!sdr) { + error("failed loading shader %s", args[3]); + return false; + } + + shader = new GfxProg(0, sdr); + shader->link(); + } + return true; +} + +void FxOverlay::set_texture(Texture *tex) { + this->tex = tex; +} + +void FxOverlay::set_shader(GfxProg *sdr) { + shader = sdr; +} + +void FxOverlay::apply(unsigned long time) { + if(time >= this->time && time < this->time + duration) { + if(shader) { + float fsec = (float)(time - this->time) / 1000.0; + shader->set_parameter("time", fsec); + + float t = fsec / ((float)duration / 1000.0f); + shader->set_parameter("t", t); + + float ease = (t < 0.25 || t >= 0.75) ? fabs(sin(t * 2.0 * pi)) : 1.0; + shader->set_parameter("ease", ease); + + float ease_sin = sin(t * pi); + shader->set_parameter("ease_sin", ease_sin); + } + overlay(tex, Vector2(0, 0), Vector2(1, 1), Color(1, 1, 1), shader); + } +} + + + +// just a little helper function to get a color out of an string +static bool str_to_color(const char *str, Color *col) { + // get red + if(*str++ != '<') return false; + if(!isdigit(*str) && *str != '.') return false; + col->r = atof(str); + + while(isdigit(*str) || *str == '.') str++; + if(*str++ != ',') return false; + + // get green + if(!isdigit(*str) && *str != '.') return false; + col->g = atof(str); + + while(isdigit(*str) || *str == '.') str++; + if(*str++ != ',') return false; + + // get blue + if(!isdigit(*str) && *str != '.') return false; + col->b = atof(str); + + while(isdigit(*str) || *str == '.') str++; + if(*str != ',') { + col->a = 1.0; + return *str == '>' ? true : false; + } + + // get alpha + if(!isdigit(*++str) && *str != '.') return false; + col->a = atof(str); + + while(isdigit(*str) || *str == '.') str++; + return *str == '>' ? true : false; +}