From 07659f32595caf0bb38119f5b70be8bf739acf51 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Fri, 29 Apr 2016 17:09:34 +0300 Subject: [PATCH] using `texelFetch()` instead of `texture2D()` in most shaders --- data/shaders/srlight_ambient.frag | 4 +- data/shaders/srlight_blur.frag | 34 +---- data/shaders/srlight_geom.frag | 271 +++++++++++++++++-------------------- data/shaders/srlight_trace.frag | 61 ++++----- data/shaders/srliquid_distort.frag | 2 +- render.d | 139 +++++++++++++------ 6 files changed, 258 insertions(+), 253 deletions(-) rewrite data/shaders/srlight_geom.frag (60%) diff --git a/data/shaders/srlight_ambient.frag b/data/shaders/srlight_ambient.frag index 4b24006..9922220 100644 --- a/data/shaders/srlight_ambient.frag +++ b/data/shaders/srlight_ambient.frag @@ -22,7 +22,7 @@ uniform sampler2D texBg; // background uniform sampler2D texOcc; // occluders uniform sampler2D texOccSmall; // occluders, small map -uniform vec2 mapPixSize; +//uniform vec2 mapPixSize; uniform vec4 lightColor; //uniform vec2 lightPos; @@ -39,7 +39,7 @@ void main (void) { vec4 color; // has some light here - vec4 bcolor = texture2D(texBg, btxy/mapPixSize); + vec4 bcolor = texelFetch(texBg, ivec2(int(btxy.x), int(btxy.y)), 0); if (lightColor.r+lightColor.g+lightColor.b == 0.0) { color = bcolor*vec4(vec3(lightColor.a), lit); } else { diff --git a/data/shaders/srlight_blur.frag b/data/shaders/srlight_blur.frag index 00076ac..efa11ca 100644 --- a/data/shaders/srlight_blur.frag +++ b/data/shaders/srlight_blur.frag @@ -17,8 +17,8 @@ */ #version 130 -//#define DEBUG_RECT -//#define DEBUG_RECT1 +// alpha threshold for our occlusion map +#define THRESHOLD (0.75) #define PI 3.1415926 @@ -44,13 +44,12 @@ uniform vec2 lightPos; // lefttop void main (void) { vec2 vTexCoord0 = gl_TexCoord[0].xy; // don't even ask me! - vec2 btxy = vec2(lightPos.x+gl_FragCoord.x, lightPos.y+gl_TexCoord[0].y*lightTexSize.x); - btxy.y = mapPixSize.y-btxy.y; - btxy /= mapPixSize; - vec2 ocxy = vec2(btxy.x, 1.0-btxy.y); + vec2 tctxy = vec2(lightPos.x+gl_FragCoord.x, lightPos.y+gl_TexCoord[0].y*lightTexSize.x); + ivec2 iocxy = ivec2(int(tctxy.x), int(tctxy.y)); + ivec2 ibtxy = ivec2(iocxy.x, int(mapPixSize.y-tctxy.y)); vec4 color; - if (texture2D(texOccFull, ocxy).a > 0.75) { + if (texelFetch(texOccFull, iocxy, 0).a > THRESHOLD) { // occluder hit, this will take care of lighted walls (we'll fix wall in next pass) color = vec4(0.0, 0.0, 0.0, 0.0); } else { @@ -94,21 +93,10 @@ void main (void) { lit = lit*smoothstep(1.0, 0.0, r); if (lit == 0.0) { -#ifdef DEBUG_RECT - color = texture2D(texBg, btxy); - color.b = 1.0; - color.a = 0.4; -#else color = vec4(0.0, 0.0, 0.0, 0.0); -#endif } else { // has some light here - vec4 bcolor = texture2D(texBg, btxy); -#ifdef DEBUG_RECT - color = bcolor; - color.b = 1.0; - color.a = 0.4; -#else + vec4 bcolor = texelFetch(texBg, ibtxy, 0); if (lightColor.r+lightColor.g+lightColor.b == 0.0) { color = bcolor*vec4(vec3(lightColor.a), lit); } else { @@ -116,16 +104,8 @@ void main (void) { color += bcolor*lit; color.a = lit/2.0; } -#endif } } - /* - //color.r = (1.0/lightTexSize.x)*gl_FragCoord.y; - color.r = gl_TexCoord[0].y; - color.g = 0; - color.b = 0; - color.a = 1; - */ gl_FragColor = color; } diff --git a/data/shaders/srlight_geom.frag b/data/shaders/srlight_geom.frag dissimilarity index 60% index 060d8eb..dec5b0c 100644 --- a/data/shaders/srlight_geom.frag +++ b/data/shaders/srlight_geom.frag @@ -1,147 +1,124 @@ -/* DooM2D: Midnight on the Firing Line - * coded by Ketmar // Invisible Vector - * Understanding is not required. Only obedience. - * - * 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 3 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, see . - */ -// this shader will light level geometry -#version 130 - -//#define DEBUG_RECT - -#define PI 3.1415926 - -#define SEARCH_RADIUS (4) -#define MIN_ALPHA (0.05) - -uniform sampler2D texLMap; // light texture of lightTexSize -uniform sampler2D texBg; // background -uniform sampler2D texOccFull; // occluders -uniform sampler2D texOccSmall; // occluders, small map -uniform vec2 lightTexSize; // x: lightSize; y: size of this texture -uniform vec2 mapPixSize; -uniform vec4 lightColor; -uniform vec2 lightPos; - - -bool hasLight (in vec2 txo, in float pixelStep) { - /* - vec2 txc = txo; - for (int dy = SEARCH_RADIUS*2; dy > 0; --dy) { - for (int dx = SEARCH_RADIUS*2; dx > 0; --dx) { - if (texture2D(texLMap, txc).a > MIN_ALPHA) return true; - txc.x += pixelStep; - } - txc.x = txo.x; - txc.y += pixelStep; - } - return false; - */ - float pxs = pixelStep*(SEARCH_RADIUS*2); - vec2 txclu = txo-pxs; - vec2 txcld = vec2(txo.x-pxs, txo.y+pxs); - vec2 txcru = vec2(txo.x+pxs, txo.y-pxs); - vec2 txcrd = txo+pxs; - vec2 txcu = vec2(txo.x, txo.y-pxs); - vec2 txcd = vec2(txo.x, txo.y+pxs); - vec2 txcl = vec2(txo.x-pxs, txo.y); - vec2 txcr = vec2(txo.x+pxs, txo.y); - vec2 txcrStep = vec2(pixelStep, -pixelStep); - float pst2 = pixelStep*2; - for (int d = SEARCH_RADIUS; d > 0; --d) { - if (texture2D(texLMap, txclu).a > MIN_ALPHA) return true; - txclu += pst2; - if (texture2D(texLMap, txcld).a > MIN_ALPHA) return true; - txcld.x += pst2; - txcld.y -= pst2; - - if (texture2D(texLMap, txcru).a > MIN_ALPHA) return true; - txcru.x -= pst2; - txcru.y += pst2; - if (texture2D(texLMap, txcrd).a > MIN_ALPHA) return true; - txcrd -= pst2; - - if (texture2D(texLMap, txcu).a > MIN_ALPHA) return true; - txcu.y += pst2; - if (texture2D(texLMap, txcd).a > MIN_ALPHA) return true; - txcd.y -= pst2; - - if (texture2D(texLMap, txcl).a > MIN_ALPHA) return true; - txcl.x += pst2; - if (texture2D(texLMap, txcr).a > MIN_ALPHA) return true; - txcr.x -= pst2; - } - return false; -} - - -//gl_FragCoord: in background - -void main (void) { - vec2 vTexCoord0 = gl_TexCoord[0].xy; // in light texture (texLMap) - //vec2 btxy = gl_FragCoord.xy/mapPixSize; - // don't even ask me! - vec2 btxy = vec2(/*lightPos.x+*/gl_FragCoord.x, /*lightPos.y+gl_TexCoord[0].y*lightTexSize.x*/gl_FragCoord.y); - //btxy.y = mapPixSize.y-btxy.y; - btxy /= mapPixSize; - vec2 ocxy = vec2(btxy.x, 1.0-btxy.y); - vec4 color; - -#ifdef DEBUG_RECT - vec4 bcolor = texture2D(texBg, btxy); - color = bcolor; - color.b = 1.0; - color.a = 0.4; - //if (texture2D(texOccFull, ocxy).a <= 0.75) color.a = 0.1; - - vec2 ourpos = gl_FragCoord.xy; - ourpos.y = mapPixSize.y-ourpos.y; - // distance from this point to light origin - float lit = clamp(1.0-(distance(ourpos, lightPos)/(lightTexSize.x/2.0)), 0.0, 1.0); - lit = smoothstep(0.1, 1.0, lit); - color.a = lit; - - //if (texture2D(texOccFull, ocxy).a <= 0.75) discard; // empty space - //float pixelStep = 1.0/lightTexSize.x; - //if (!hasLight(vTexCoord0, pixelStep)) discard; - /* - color.r = vTexCoord0.x; - color.g = 0; - color.b = 0; - color.a = 1.0; - */ -#else - if (texture2D(texOccFull, ocxy).a <= 0.75) discard; // empty space - - // occluder hit; look for light in 8px radius - float pixelStep = 1.0/lightTexSize.y; - if (!hasLight(vTexCoord0, pixelStep)) discard; - // background - vec4 bcolor = texture2D(texBg, btxy); - // light is y-mirrored - vec2 ourpos = gl_FragCoord.xy; - ourpos.y = mapPixSize.y-ourpos.y; - // distance from this point to light origin - float lit = clamp(1.0-(distance(ourpos, lightPos)/(lightTexSize.x/2.0)), 0.0, 1.0); - lit = smoothstep(0.1, 1.0, lit); - if (lightColor.a == 0.0) { - color = bcolor*vec4(vec3(1.0), lit); - } else { - color = lightColor*lit; - color += bcolor*lit; - color.a = lit/2.0; - } -#endif - gl_FragColor = color; -} +/* DooM2D: Midnight on the Firing Line + * coded by Ketmar // Invisible Vector + * Understanding is not required. Only obedience. + * + * 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 3 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, see . + */ +// this shader will light level geometry +#version 130 + +#define PI 3.1415926 + +// alpha threshold for our occlusion map +#define THRESHOLD (0.75) + +#define SEARCH_RADIUS (4) +#define MIN_ALPHA (0.05) + +uniform sampler2D texLMap; // light texture of lightTexSize +uniform sampler2D texBg; // background +uniform sampler2D texOccFull; // occluders +uniform sampler2D texOccSmall; // occluders, small map +uniform vec2 lightTexSize; // x: lightSize; y: size of this texture +uniform vec2 mapPixSize; +uniform vec4 lightColor; +uniform vec2 lightPos; + + +//gl_FragCoord: in background + +void main (void) { + // light is y-mirrored + vec2 ourpos = vec2(gl_FragCoord.x, mapPixSize.y-gl_FragCoord.y); + + vec2 ocxy = ourpos/mapPixSize; + if (texture2D(texOccFull, ocxy).a <= THRESHOLD) { discard; return; } // empty space + + // occluder hit + // first, we should check if there is no other occluders in +x, +y and +x+y direction + vec2 a8 = trunc(ourpos/8); + vec2 ldxy = vec2(sign(lightPos.x-gl_FragCoord.x), sign(gl_FragCoord.y-lightPos.y)); + vec2 s8 = ldxy/(mapPixSize/8); + if (texture2D(texOccSmall, vec2(a8.x+s8.x, a8.y)).a > THRESHOLD && + texture2D(texOccSmall, vec2(a8.x, a8.y+s8.y)).a > THRESHOLD && + texture2D(texOccSmall, a8+s8).a > THRESHOLD) { discard; return; } + + /* + vec4 clr = vec4(0, 0, 0, 1); + if (ldxy.x < 0) clr.r = 0.5; else if (ldxy.x > 0) clr.r = 1; + if (ldxy.y < 0) clr.g = 0.5; else if (ldxy.y > 0) clr.g = 1; + gl_FragColor = clr; + return; + */ + + // ok, it's not blocked + // now move to tile edge, and trace 8px in +dx, +dy, +dx+dy dirs to find some light + vec2 ltpos = gl_TexCoord[0].xy; // in light texture (texLMap) + float pixelStep = 1.0/lightTexSize.y; // in light texture + // left-top tile pixel + vec2 tileopos = trunc(ourpos/8); + tileopos *= 8; + + //ldxy.y = -ldxy.y; + // move to opposide tile side if necessary + if (ldxy.x > 0) tileopos.x += 7; + if (ldxy.y > 0) tileopos.y += 7; + + //vec4 xcolor = texture2D(texBg, vec2(tileopos.x, mapPixSize.y-tileopos.y)/mapPixSize); + //gl_FragColor = vec4(xcolor.r, xcolor.g, xcolor.b, 1); + //return; + + // shift position in light texture to sync it with tileopos + ltpos += vec2((tileopos.x-ourpos.x)*pixelStep, -(tileopos.y-ourpos.y)*pixelStep); + + // trace light + bool lightHit = false; + ldxy *= pixelStep; // so we can use it to step in light texture + for (float count = 8; count > 0; --count) { + if (texture2D(texLMap, ltpos+ldxy).a > MIN_ALPHA || + texture2D(texLMap, vec2(ltpos.x+ldxy.x, ltpos.y)).a > MIN_ALPHA || + texture2D(texLMap, vec2(ltpos.x, ltpos.y+ldxy.y)).a > MIN_ALPHA) + { + lightHit = true; + break; + } + ltpos += ldxy; + } + // no hit -- get out of here + if (!lightHit) { discard; return; } + + //gl_FragColor = vec4(1, 1, 0, 1); + //return; + + vec4 color; + + // background + vec2 btxy = gl_FragCoord.xy/mapPixSize; + vec4 bcolor = texture2D(texBg, btxy); + // light is y-mirrored + //vec2 ourpos = gl_FragCoord.xy; + //ourpos.y = mapPixSize.y-ourpos.y; + // distance from this point to light origin + float lit = clamp(1.0-(distance(ourpos, lightPos)/(lightTexSize.x/2.0)), 0.0, 1.0); + lit = smoothstep(0.1, 1.0, lit); + if (lightColor.a == 0.0) { + color = bcolor*vec4(vec3(1.0), lit); + } else { + color = lightColor*lit; + color += bcolor*lit; + color.a = lit/2.0; + } + + gl_FragColor = color; +} diff --git a/data/shaders/srlight_trace.frag b/data/shaders/srlight_trace.frag index 2105dcc..0566239 100644 --- a/data/shaders/srlight_trace.frag +++ b/data/shaders/srlight_trace.frag @@ -29,7 +29,7 @@ uniform vec2 lightTexSize; uniform sampler2D texOccFull; // occluders map, full uniform sampler2D texOccSmall; // occluders, small map uniform vec2 lightPos; // light coords in occluders map -uniform vec2 mapPixSize; // size of occluders map +//uniform vec2 mapPixSize; // size of occluders map // alpha threshold for our occlusion map #define THRESHOLD (0.75) @@ -86,46 +86,43 @@ void main (void) { step8 = vec2((b8.x-a8.x)/len8, sign(b8.y-a8.y)); } - vec2 sps = mapPixSize/8; - //bool detailStep = false; //(len > 8); - bool detailStep = (texture2D(texOccSmall, round(a8)/sps).a > THRESHOLD); - //bool detailStep = true; + //vec2 sps = mapPixSize/8; + bool detailStep = (texelFetch(texOccSmall, ivec2(int(a8.x), int(a8.y)), 0).a > THRESHOLD); - // big steps - if (!detailStep) { - while (len > 0) { + while (len > 0) { + // big steps + if (!detailStep) { vec2 nx8 = round(vec2(a8.x+step8.x, a8.y)); vec2 ny8 = round(vec2(a8.x, a8.y+step8.y)); a8 += step8; - if (texture2D(texOccSmall, round(a8)/sps).a > THRESHOLD || - texture2D(texOccSmall, round(nx8)/sps).a > THRESHOLD || - texture2D(texOccSmall, round(ny8)/sps).a > THRESHOLD) + if (texelFetch(texOccSmall, ivec2(int(a8.x), int(a8.y)), 0).a <= THRESHOLD && + texelFetch(texOccSmall, ivec2(int(nx8.x), int(nx8.y)), 0).a <= THRESHOLD && + texelFetch(texOccSmall, ivec2(int(ny8.x), int(ny8.y)), 0).a <= THRESHOLD) { - detailStep = true; - break; - } else { len -= 8; a += step*8; - } - } - } - - // small steps - if (detailStep) { - while (len > 0) { - if (texture2D(texOccFull, round(a)/mapPixSize).a > THRESHOLD) { -#ifdef INTO_DEPTH - for (int stp = INTO_DEPTH; stp > 0; --stp) { - vec2 b = a+step; - if (texture2D(texOccFull, round(b)/mapPixSize).a <= THRESHOLD) break; - a = b; + } else { + // do 8 small steps + int xlen = (len > 8 ? 8 : int(len)); + while (xlen-- > 0) { + if (texelFetch(texOccFull, ivec2(int(a.x), int(a.y)), 0).a > THRESHOLD) { + #ifdef INTO_DEPTH + for (int stp = INTO_DEPTH; stp > 0; --stp) { + vec2 b = a+step; + if (texelFetch(texOccFull, ivec2(int(b.x), int(b.y)), 0).a <= THRESHOLD) break; + a = b; + } + #endif + dst = distance(lightPos, a)/(lightTexSize.x/2.0); + xlen = -42; + break; + } + --len; + a += step; } -#endif - dst = distance(lightPos, a)/(lightTexSize.x/2.0); - break; + if (xlen <= -42) break; + detailStep = false; // just in case } - --len; - a += step; } } diff --git a/data/shaders/srliquid_distort.frag b/data/shaders/srliquid_distort.frag index 202f24b..d1e039a 100644 --- a/data/shaders/srliquid_distort.frag +++ b/data/shaders/srliquid_distort.frag @@ -34,7 +34,7 @@ vec2 shift (in vec2 p) { void main (void) { vec2 texCoord = gl_TexCoord[0].xy; vec4 clr = texture2D(texLqMap, texCoord); - if (clr.a == 0.0) discard; + if (clr.a == 0.0) { discard; return; } // distort vec2 r = texCoord.xy; vec2 p = shift(r); diff --git a/render.d b/render.d index 27b597a..71970a8 100644 --- a/render.d +++ b/render.d @@ -377,14 +377,14 @@ __gshared uint attachedLightCount = 0; // ////////////////////////////////////////////////////////////////////////// // -enum MaxLightRadius = 255; +enum MaxLightRadius = 256; // ////////////////////////////////////////////////////////////////////////// // // for light __gshared FBO[MaxLightRadius+1] fboDistMap; -__gshared FBO fboOccluders; -__gshared Shader shadToPolar, shadBlur, shadBlurOcc, shadAmbient; +__gshared FBO fboLSpot, fboLSpotSmall; +__gshared Shader shadLightTrace, shadLightBlur, shadLightGeom, shadLightAmbient; __gshared TrueColorImage editorImg; __gshared FBO fboEditor; __gshared FBO fboConsole; @@ -415,37 +415,38 @@ public void initOpenGL () { }); // lights - shadToPolar = new Shader("light_trace", loadTextFile("shaders/srlight_trace.frag")); - shadToPolar.exec((Shader shad) { + shadLightTrace = new Shader("light_trace", loadTextFile("shaders/srlight_trace.frag")); + shadLightTrace.exec((Shader shad) { //shad["texLMap"] = 0; shad["texOccFull"] = 2; shad["texOccSmall"] = 3; }); - shadBlur = new Shader("light_blur", loadTextFile("shaders/srlight_blur.frag")); - shadBlur.exec((Shader shad) { + shadLightBlur = new Shader("light_blur", loadTextFile("shaders/srlight_blur.frag")); + shadLightBlur.exec((Shader shad) { shad["texDist"] = 0; shad["texBg"] = 1; shad["texOccFull"] = 2; shad["texOccSmall"] = 3; }); - shadBlurOcc = new Shader("light_geom", loadTextFile("shaders/srlight_geom.frag")); - shadBlurOcc.exec((Shader shad) { + shadLightGeom = new Shader("light_geom", loadTextFile("shaders/srlight_geom.frag")); + shadLightGeom.exec((Shader shad) { shad["texLMap"] = 0; shad["texBg"] = 1; shad["texOccFull"] = 2; shad["texOccSmall"] = 3; }); - shadAmbient = new Shader("light_ambient", loadTextFile("shaders/srlight_ambient.frag")); - shadAmbient.exec((Shader shad) { + shadLightAmbient = new Shader("light_ambient", loadTextFile("shaders/srlight_ambient.frag")); + shadLightAmbient.exec((Shader shad) { shad["texBg"] = 1; shad["texOccFull"] = 2; shad["texOccSmall"] = 3; }); - fboOccluders = new FBO(MaxLightRadius*2, MaxLightRadius*2, Texture.Option.Clamp, Texture.Option.Linear); + fboLSpot = new FBO(MaxLightRadius*2, MaxLightRadius*2, Texture.Option.Clamp, Texture.Option.Linear); + fboLSpotSmall = new FBO(fboLSpot.width/8, fboLSpot.height/8, Texture.Option.Clamp, Texture.Option.Linear); //TODO: this sux! foreach (int sz; 2..MaxLightRadius+1) { fboDistMap[sz] = new FBO(sz*2, 1, Texture.Option.Clamp, Texture.Option.Linear); // create 1d distance map FBO @@ -581,10 +582,10 @@ void loadMap (string mapname) { fboOrigBack = new FBO(map.width*TileSize, map.height*TileSize, Texture.Option.Nearest/*, Texture.Option.Depth*/); // background+foreground fboLMaskSmall = new FBO(map.width, map.height, Texture.Option.Nearest); // small lightmask - shadToPolar.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize-1, map.height*TileSize-1); }); - shadBlur.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); - shadBlurOcc.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); - shadAmbient.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); + //shadLightTrace.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize-1, map.height*TileSize-1); }); + shadLightBlur.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); + shadLightGeom.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); + shadLightAmbient.exec((Shader shad) { shad["mapPixSize"] = SVec2F(map.width*TileSize, map.height*TileSize); }); glActiveTexture(GL_TEXTURE0+0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -800,7 +801,7 @@ void renderLightAmbient() (int lightX, int lightY, int lightW, int lightH, in au //glDisable(GL_BLEND); orthoCamera(map.width*TileSize, map.height*TileSize); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - shadAmbient.exec((Shader shad) { + shadLightAmbient.exec((Shader shad) { shad["lightColor"] = SVec4F(lcol.x, lcol.y, lcol.z, lcol.w); //shad["lightPos"] = SVec2F(lightX, lightY); glRectf(lightX, lightY, lightX1, lightY1); @@ -831,7 +832,7 @@ void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightRa // build 1d distance map to fboShadowMapId fboDistMap.ptr[lightRadius].exec({ // no need to clear it, shader will take care of that - shadToPolar.exec((Shader shad) { + shadLightTrace.exec((Shader shad) { shad["lightTexSize"] = SVec2F(lightSize, lightSize); shad["lightPos"] = SVec2F(lightX, lightY); orthoCamera(lightSize, 1); @@ -841,16 +842,17 @@ void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightRa }); // build light texture for blending - fboOccluders.exec({ + fboLSpot.exec({ // no need to clear it, shader will take care of that // debug - //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + // need to clear it, for "small" + //glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //glClear(GL_COLOR_BUFFER_BIT); - shadBlur.exec((Shader shad) { + shadLightBlur.exec((Shader shad) { shad["lightTexSize"] = SVec2F(lightSize, MaxLightRadius*2); // x: size of distmap; y: size of this texture shad["lightColor"] = SVec4F(lcol.x, lcol.y, lcol.z, lcol.w); shad["lightPos"] = SVec2F(lightX-lightRadius, lightY-lightRadius); - orthoCamera(fboOccluders.tex.width, fboOccluders.tex.height); + orthoCamera(fboLSpot.tex.width, fboLSpot.tex.height); //drawAtXY(fboDistMap[lightRadius].tex.tid, 0, 0, lightSize, lightSize); bindTexture(fboDistMap.ptr[lightRadius].tex.tid); glBegin(GL_QUADS); @@ -862,51 +864,100 @@ void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightRa }); }); + // build "small" light texture for geometry-light shader + //glUseProgram(0); + version(none) fboLSpotSmall.exec({ + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + //orthoCamera(fboLSpotSmall.tex.width, fboLSpotSmall.tex.height); + //orthoCamera(fboLSpot.width, fboLSpot.height); + orthoCamera(lightSize, lightSize); + //orthoCamera(fboLevelLight.tex.width, fboLevelLight.tex.height); + bindTexture(fboLSpot.tex.tid); + float occe = 1.0f*lightSize/(MaxLightRadius*2); + float occs = 1.0f-occe; + glBegin(GL_QUADS); + /* + glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); // top-left + glTexCoord2f(1.0f, 0.0f); glVertex2i(fboLSpotSmall.tex.width, 0); // top-right + glTexCoord2f(1.0f, 1.0f); glVertex2i(fboLSpotSmall.tex.width, fboLSpotSmall.tex.height); // bottom-right + glTexCoord2f(0.0f, 1.0f); glVertex2i(0, fboLSpotSmall.tex.height); // bottom-left + */ + /* + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // top-left + glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f); // top-right + glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f); // bottom-right + glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f); // bottom-left + */ + /* + glTexCoord2f(0.0f, occs); glVertex2i(0, 0); // top-left + glTexCoord2f(occe, occs); glVertex2i(lightSize, 0); // top-right + glTexCoord2f(occe, 1.0f); glVertex2i(lightSize, lightSize); // bottom-right + glTexCoord2f(0.0f, 1.0f); glVertex2i(0, lightSize); // bottom-left + */ + glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); // top-left + glTexCoord2f(occe, 0.0f); glVertex2i(lightSize, 0); // top-right + glTexCoord2f(occe, 1.0f); glVertex2i(lightSize, lightSize); // bottom-right + glTexCoord2f(0.0f, 1.0f); glVertex2i(0, lightSize); // bottom-left + glEnd(); + /* + bindTexture(0); + glColor4f(1.0f, 0.0f, 0.0f, 0.5f); + glRectf(0, 0, fboLSpotSmall.tex.width, fboLSpotSmall.tex.height); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + */ + }); + // blend light texture fboLevelLight.exec({ glEnable(GL_BLEND); - //glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); orthoCamera(fboLevelLight.tex.width, fboLevelLight.tex.height); - //drawAtXY(fboOccluders.tex, lightX-lightRadius, lightY-lightRadius, mirrorY:true); - float occe = 1.0f*lightSize/(MaxLightRadius*2); - float occs = 1.0f-occe; int x0 = lightX-lightRadius+0; int y1 = lightY-lightRadius+0; int x1 = lightX+lightRadius-1+1; int y0 = lightY+lightRadius-1+1; - bindTexture(fboOccluders.tex.tid); - glBegin(GL_QUADS); - /* - glTexCoord2f(0.0f, 0.0f); glVertex2i(x0, y0); // top-left - glTexCoord2f(occe, 0.0f); glVertex2i(x1, y0); // top-right - glTexCoord2f(occe, occe); glVertex2i(x1, y1); // bottom-right - glTexCoord2f(0.0f, occe); glVertex2i(x0, y1); // bottom-left - */ - glTexCoord2f(0.0f, occs); glVertex2i(x0, y0); // top-left - glTexCoord2f(occe, occs); glVertex2i(x1, y0); // top-right - glTexCoord2f(occe, 1.0f); glVertex2i(x1, y1); // bottom-right - glTexCoord2f(0.0f, 1.0f); glVertex2i(x0, y1); // bottom-left - glEnd(); + float occe = 1.0f*lightSize/(MaxLightRadius*2); + float occs = 1.0f-occe; + /*version(none)*/ { + bindTexture(fboLSpot.tex.tid); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, occs); glVertex2i(x0, y0); // top-left + glTexCoord2f(occe, occs); glVertex2i(x1, y0); // top-right + glTexCoord2f(occe, 1.0f); glVertex2i(x1, y1); // bottom-right + glTexCoord2f(0.0f, 1.0f); glVertex2i(x0, y1); // bottom-left + glEnd(); + }/* else { + glDisable(GL_BLEND); + float occn = 1.0f*lightSize/(MaxLightRadius*2); + bindTexture(fboLSpotSmall.tex.tid); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, occn); glVertex2i(x0, y0); // top-left + glTexCoord2f(occn, occn); glVertex2i(x1, y0); // top-right + glTexCoord2f(occn, 0.0f); glVertex2i(x1, y1); // bottom-right + glTexCoord2f(0.0f, 0.0f); glVertex2i(x0, y1); // bottom-left + glEnd(); + }*/ /* bindTexture(0); glRectf(x0, y0, x1, y1); */ // and blend it again, with the shader that will touch only occluders - shadBlurOcc.exec((Shader shad) { + shadLightGeom.exec((Shader shad) { //shad["lightTexSize"] = SVec2F(lightSize, lightSize); - shad["lightTexSize"] = SVec2F(lightSize, fboOccluders.tex.height); + shad["lightTexSize"] = SVec2F(lightSize, fboLSpot.tex.height); shad["lightColor"] = SVec4F(lcol.x, lcol.y, lcol.z, lcol.w); shad["lightPos"] = SVec2F(lightX, lightY); //shad["lightPos"] = SVec2F(lightX-lightRadius, lightY-lightRadius); - bindTexture(fboOccluders.tex.tid); + bindTexture(fboLSpot.tex.tid); glBegin(GL_QUADS); glTexCoord2f(0.0f, occs); glVertex2i(x0, y0); // top-left glTexCoord2f(occe, occs); glVertex2i(x1, y0); // top-right glTexCoord2f(occe, 1.0f); glVertex2i(x1, y1); // bottom-right glTexCoord2f(0.0f, 1.0f); glVertex2i(x0, y1); // bottom-left glEnd(); - //drawAtXY(fboOccluders.tex.tid, lightX-lightRadius, lightY-lightRadius, lightSize, lightSize, mirrorY:true); + //drawAtXY(fboLSpot.tex.tid, lightX-lightRadius, lightY-lightRadius, lightSize, lightSize, mirrorY:true); }); }); } @@ -1248,7 +1299,7 @@ void renderScene (MonoTime curtime) { testLightY = testLightY/scale+mofsy/scale; testLightMoved = false; } - foreach (immutable _; 0..50) { + foreach (immutable _; 0..1) { renderLight(testLightX, testLightY, SVec4F(0.3f, 0.3f, 0.0f, 1.0f), 96); } } -- 2.11.4.GIT