From 21706e8518b4cb91af2c1e5135064ddb29be96f6 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Fri, 1 Apr 2016 18:24:47 +0300 Subject: [PATCH] added ambient light actors --- data/scripts/maps/map01.dacs | 4 ++ data/scripts/misc/ambientlight.dacs | 43 ++++++++++++++++++ data/shaders/srlight_ambient.frag | 34 +++++++++++++++ glutils.d | 8 ++-- render.d | 87 ++++++++++++++++++++++++++++++++++--- 5 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 data/scripts/misc/ambientlight.dacs create mode 100644 data/shaders/srlight_ambient.frag diff --git a/data/scripts/maps/map01.dacs b/data/scripts/maps/map01.dacs index 5617b44..5302f18 100644 --- a/data/scripts/maps/map01.dacs +++ b/data/scripts/maps/map01.dacs @@ -2,6 +2,7 @@ module mapsMap01 is "map" "map01"; import apiActor; import miscLevellight; +import miscAmbientlight; import stdlib; @@ -23,6 +24,9 @@ void putStaticLights () { // red light miscLevellight.spawn(24*8+4, (24+18)*8-2+LYOfs, 150, 0, 0, 128); + + //miscAmbientlight.spawn(10, 10, 550, 150, 255); + miscAmbientlight.spawn(10, 10, 550, 350, 128, 0, 0); } diff --git a/data/scripts/misc/ambientlight.dacs b/data/scripts/misc/ambientlight.dacs new file mode 100644 index 0000000..6d6b623 --- /dev/null +++ b/data/scripts/misc/ambientlight.dacs @@ -0,0 +1,43 @@ +// this actor is used in "press other switch" switch types +module miscAmbientlight is "light" "Ambient"; + +import apiActor; +import apiMap; +import apiSwitch; +import stdlib; + + +// setup actor properties +public void initialize (Actor me) { + //me.radius = 1; + //me.height = 1; + me.flags = AF_NOCOLLISION|AF_NOGRAVITY|AF_NOONTOUCH|AF_NODRAW|/*AF_NOLIGHT|*/AF_NOANIMATE; + /* + // add attached light + me.attLightXOfs = 0; + me.attLightYOfs = -8; + me.attachedLightRGBX(255, 0, 255, 124); + writeln("*** PRESSACTOR SPAWNED *** x=", me.x, "; y=", me.y); + */ +} + + +// thinker +//public void think (Actor me) {} + + +public Actor spawn (int x, int y, int w, int h, int r, int g, int b) { + auto lt = actorSpawn("light", "Ambient", x, y, ACTOR_DIR_LEFT); + lt.radius = w; + lt.height = h; + lt.attachedLightRGBX(r, g, b, 255); + return lt; +} + +public Actor spawn (int x, int y, int w, int h, int intens) { + auto lt = actorSpawn("light", "Ambient", x, y, ACTOR_DIR_LEFT); + lt.radius = w; + lt.height = h; + lt.attachedLightColorless(intens, 255); + return lt; +} diff --git a/data/shaders/srlight_ambient.frag b/data/shaders/srlight_ambient.frag new file mode 100644 index 0000000..6b0c569 --- /dev/null +++ b/data/shaders/srlight_ambient.frag @@ -0,0 +1,34 @@ +#version 130 + +#define PI 3.1415926 + +uniform sampler2D texBg; // background +uniform sampler2D texOcc; // occluders +uniform vec2 mapPixSize; +uniform vec4 lightColor; +//uniform vec2 lightPos; + + +//gl_FragCoord: [0..lightTexSize) + +#define lit (1.0) + + +void main (void) { + vec2 btxy = gl_FragCoord.xy; + //btxy.y = mapPixSize.y-btxy.y-1.0; + //vec2 ocxy = vec2(btxy.x, mapPixSize.y-btxy.y)/mapPixSize; + vec4 color; + + // has some light here + vec4 bcolor = texture2D(texBg, btxy/mapPixSize); + if (lightColor.r+lightColor.g+lightColor.b == 0.0) { + color = bcolor*vec4(vec3(lightColor.a), lit); + } else { + color = lightColor*lit; + color += bcolor*lit; + color.a = lit/2.0; + } + + gl_FragColor = color; +} diff --git a/glutils.d b/glutils.d index 977bf65..dbd0c6a 100644 --- a/glutils.d +++ b/glutils.d @@ -471,12 +471,12 @@ private: // ////////////////////////////////////////////////////////////////////////// // public struct SVec2I { int x, y; } -public struct SVec3I { int x, y, z; } -public struct SVec4I { int x, y, z, w; } +public struct SVec3I { int x, y, z; alias r = x; alias g = y; alias b = z; } +public struct SVec4I { int x, y, z, w; alias r = x; alias g = y; alias b = z; alias a = w; } public struct SVec2F { float x, y; } -public struct SVec3F { float x, y, z; } -public struct SVec4F { float x, y, z, w; } +public struct SVec3F { float x, y, z; alias r = x; alias g = y; alias b = z; } +public struct SVec4F { float x, y, z, w; alias r = x; alias g = y; alias b = z; alias a = w; } public final class Shader : OpenGLObject { diff --git a/render.d b/render.d index 605c671..768ec47 100644 --- a/render.d +++ b/render.d @@ -92,7 +92,13 @@ __gshared bool frameInterpolation = true; // ////////////////////////////////////////////////////////////////////////// // // attached lights struct AttachedLightInfo { + enum Type { + Point, + Ambient, + } + Type type; int x, y; + int w, h; // for ambient lights float r, g, b; bool uncolored; int radius; @@ -109,7 +115,7 @@ enum MaxLightRadius = 255; // ////////////////////////////////////////////////////////////////////////// // // for light __gshared FBO[MaxLightRadius+1] fboOccluders, fboDistMap; -__gshared Shader shadToPolar, shadBlur, shadBlurOcc; +__gshared Shader shadToPolar, shadBlur, shadBlurOcc, shadAmbient; __gshared FBO fboLevel, fboLevelLight, fboOrigBack; __gshared Shader shadScanlines; @@ -160,6 +166,12 @@ public void initOpenGL () { shad["texOcc"] = 2; }); + shadAmbient = new Shader("light_ambient", loadTextFile("shaders/srlight_ambient.frag")); + shadAmbient.exec((Shader shad) { + shad["texBg"] = 1; + shad["texOcc"] = 2; + }); + //TODO: this sux! foreach (int sz; 2..MaxLightRadius+1) { fboOccluders[sz] = new FBO(sz*2, sz*2, Texture.Option.Clamp, Texture.Option.Linear); // create occluders FBO @@ -201,6 +213,7 @@ void loadMap (string mapname) { shadToPolar.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*8-1, map.height*8-1); }); shadBlur.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*8, map.height*8); }); shadBlurOcc.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*8, map.height*8); }); + shadAmbient.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*8, map.height*8); }); glActiveTexture(GL_TEXTURE0+0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -356,6 +369,8 @@ mixin(Actor.FieldGetMixin!("classtype", StrId)); // fget_classtype mixin(Actor.FieldGetMixin!("classname", StrId)); // fget_classname mixin(Actor.FieldGetMixin!("x", int)); mixin(Actor.FieldGetMixin!("y", int)); +mixin(Actor.FieldGetMixin!("radius", int)); +mixin(Actor.FieldGetMixin!("height", int)); mixin(Actor.FieldGetMixin!("flags", uint)); mixin(Actor.FieldGetMixin!("zAnimstate", StrId)); mixin(Actor.FieldGetMixin!("zAnimidx", int)); @@ -381,6 +396,48 @@ mixin(Actor.FieldGetPtrMixin!("y", int)); __gshared int vportX0, vportY0, vportX1, vportY1; +// ////////////////////////////////////////////////////////////////////////// // +void renderLightAmbient() (int lightX, int lightY, int lightW, int lightH, in auto ref SVec4F lcol) { + //conwriteln("!!!000: (", lightX, ",", lightY, ")-(", lightW, ",", lightH, "): r=", cast(uint)(255.0f*lcol.r), "; g=", cast(uint)(255.0f*lcol.g), "; b=", cast(uint)(255.0f*lcol.b), "; a=", cast(uint)(255.0f*lcol.a)); + if (lightW < 1 || lightH < 1) return; + int lightX1 = lightX+lightW-1; + int lightY1 = lightY+lightH-1; + // clip light to viewport + if (lightX < vportX0) lightX = vportX0; + if (lightY < vportY0) lightY = vportY0; + if (lightX1 > vportX1) lightX1 = vportX1; + if (lightY1 > vportY1) lightY1 = vportY1; + // is this light visible? + //conwriteln("!!!001: (", lightX, ",", lightY, ")-(", lightX1, ",", lightY1, "): r=", cast(uint)(255.0f*lcol.r), "; g=", cast(uint)(255.0f*lcol.g), "; b=", cast(uint)(255.0f*lcol.b), "; a=", cast(uint)(255.0f*lcol.a)); + if (lightX1 < lightX || lightY1 < lightY || lightX > vportX1 || lightY > vportY1 || lightX1 < vportX0 || lightY1 < vportY0) return; + //conwriteln("!!!002: (", lightX, ",", lightY, ")-(", lightX1, ",", lightY1, "): r=", cast(uint)(255.0f*lcol.r), "; g=", cast(uint)(255.0f*lcol.g), "; b=", cast(uint)(255.0f*lcol.b), "; a=", cast(uint)(255.0f*lcol.a)); + + fboLevelLight.exec({ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + //glDisable(GL_BLEND); + orthoCamera(map.width*8, map.height*8); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + shadAmbient.exec((Shader shad) { + shad["lightColor"] = SVec4F(lcol.x, lcol.y, lcol.z, lcol.w); + //shad["lightPos"] = SVec2F(lightX, lightY); + glRectf(lightX, lightY, lightX1, lightY1); + }); + /+ + if (lcol.r == 0 && lcol.g == 0 && lcol.b == 0) { + //conwriteln("ambient: (", lightX, ",", lightY, ")-(", lightX1, ",", lightY1, "): intens=", cast(uint)(255.0f*lcol.a)); + glColor4f(lcol.a, lcol.a, lcol.a, lcol.a); + } else { + //conwriteln("ambient: (", lightX, ",", lightY, ")-(", lightX1, ",", lightY1, "): r=", cast(uint)(255.0f*lcol.r), "; g=", cast(uint)(255.0f*lcol.g), "; b=", cast(uint)(255.0f*lcol.b), "; a=", cast(uint)(255.0f*lcol.a)); + glColor4f(lcol.r, lcol.g, lcol.b, 1.0f); + } + glRectf(lightX, lightY, lightX1, lightY1); + +/ + }); +} + + +// ////////////////////////////////////////////////////////////////////////// // void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightRadius) { if (lightRadius < 2) return; if (lightRadius > MaxLightRadius) lightRadius = MaxLightRadius; @@ -582,10 +639,13 @@ void renderScene (MonoTime curtime) { // process attached lights if ((me.fget_flags&AF_NOLIGHT) == 0) { uint alr = me.fget_attLightRGBX; - if ((alr&0xff) >= 4) { + bool isambient = (me.fget_classtype.get == "light" && me.fget_classname.get == "Ambient"); + if ((alr&0xff) >= 4 || (isambient && me.fget_radius >= 1 && me.fget_height >= 1)) { + //if (isambient) conwriteln("isambient: ", isambient, "; x=", me.fget_x, "; y=", me.fget_y, "; w=", me.fget_radius, "; h=", me.fget_height); // yep, add it auto li = attachedLights.ptr+attachedLightCount; ++attachedLightCount; + li.type = (!isambient ? AttachedLightInfo.Type.Point : AttachedLightInfo.Type.Ambient); li.x = actorX+me.fget_attLightXOfs; li.y = actorY+me.fget_attLightYOfs; li.r = ((alr>>24)&0xff)/255.0f; // red or intensity @@ -598,6 +658,10 @@ void renderScene (MonoTime curtime) { } li.radius = (alr&0xff); if (li.radius > MaxLightRadius) li.radius = MaxLightRadius; + if (isambient) { + li.w = me.fget_radius; + li.h = me.fget_height; + } } } } else { @@ -695,10 +759,21 @@ void renderScene (MonoTime curtime) { // attached lights foreach (ref li; attachedLights[0..attachedLightCount]) { - if (li.uncolored) { - renderLight(li.x, li.y, SVec4F(0.0f, 0.0f, 0.0f, li.r), li.radius); - } else { - renderLight(li.x, li.y, SVec4F(li.r, li.g, li.b, 1.0f), li.radius); + if (li.type == AttachedLightInfo.Type.Ambient) { + //conwriteln("ambient: x=", li.x, "; y=", li.y, "; w=", li.w, "; h=", li.h); + // ambient light + if (li.uncolored) { + renderLightAmbient(li.x, li.y, li.w, li.h, SVec4F(0.0f, 0.0f, 0.0f, li.r)); + } else { + renderLightAmbient(li.x, li.y, li.w, li.h, SVec4F(li.r, li.g, li.b, 1.0f)); + } + } else if (li.type == AttachedLightInfo.Type.Point) { + // point light + if (li.uncolored) { + renderLight(li.x, li.y, SVec4F(0.0f, 0.0f, 0.0f, li.r), li.radius); + } else { + renderLight(li.x, li.y, SVec4F(li.r, li.g, li.b, 1.0f), li.radius); + } } } -- 2.11.4.GIT