From 06fa9adcb7cf327343bcf9a105ac79b820d78c3b Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Thu, 4 Feb 2016 02:45:45 +0200 Subject: [PATCH] shader optimization; won some frames on big lights --- srblurlight.frag => srlight_blur.frag | 35 ++++-- srlight_topolar.frag | 30 +++++ srtopolar.frag => srlight_topolar_orig.frag | 7 +- wadarc.d | 2 +- xmain_d2d.d | 182 ++++++++++++++++++++++------ 5 files changed, 202 insertions(+), 54 deletions(-) rename srblurlight.frag => srlight_blur.frag (76%) create mode 100644 srlight_topolar.frag rename srtopolar.frag => srlight_topolar_orig.frag (85%) diff --git a/srblurlight.frag b/srlight_blur.frag similarity index 76% rename from srblurlight.frag rename to srlight_blur.frag index 32677f1..6fb85dd 100644 --- a/srblurlight.frag +++ b/srlight_blur.frag @@ -5,16 +5,15 @@ uniform sampler2D tex0; // 1D distance uniform sampler2D tex1; // background uniform vec2 lightTexSize; -uniform bool shadowDoBloor; +#define SHADOW_DO_BLUR -const float softShadows = 1.0f; +#define SOFT_SHADOWS (1.0f) // sample from the 1D distance map -float sample (vec2 coord, float r) { - return step(r, texture2D(tex0, coord).r); -} +//float sample (in vec2 coord, in float r) { return step(r, texture2D(tex0, coord).r); } +#define sample(cc_) step(r, texture2D(tex0, vec2(tc.x+(cc_)*blur, tc.y)).r) void main (void) { @@ -33,16 +32,16 @@ void main (void) { vec2 tc = vec2(coord, 0.0); // the center tex0 coord, which gives us hard shadows - float center = sample(vec2(tc.x, tc.y), r); + float center = step(r, texture2D(tex0, tc.xy).r); //sample(vec2(tc.x, tc.y), r); // we multiply the blur amount by our distance from center // this leads to more blurriness as the shadow "fades away" float blur = ltsxi*smoothstep(0.0, 1.0, r); // now we use a simple gaussian blur - float sum = 0.0; - if (shadowDoBloor) { - sum += sample(vec2(tc.x-4.0*blur, tc.y), r)*0.05; + #ifdef SHADOW_DO_BLUR + /* + float sum = sample(vec2(tc.x-4.0*blur, tc.y), r)*0.05; sum += sample(vec2(tc.x-3.0*blur, tc.y), r)*0.09; sum += sample(vec2(tc.x-2.0*blur, tc.y), r)*0.12; sum += sample(vec2(tc.x-1.0*blur, tc.y), r)*0.15; @@ -51,12 +50,22 @@ void main (void) { sum += sample(vec2(tc.x+2.0*blur, tc.y), r)*0.12; sum += sample(vec2(tc.x+3.0*blur, tc.y), r)*0.09; sum += sample(vec2(tc.x+4.0*blur, tc.y), r)*0.05; - } else { - sum = center; - } + */ + float sum = sample(-4.0)*0.05; + sum += sample(-3.0)*0.09; + sum += sample(-2.0)*0.12; + sum += sample(-1.0)*0.15; + sum += center*0.16; + sum += sample( 1.0)*0.15; + sum += sample( 2.0)*0.12; + sum += sample( 3.0)*0.09; + sum += sample( 4.0)*0.05; + #else + float sum = center; + #endif // sum of 1.0 -> in light, 0.0 -> in shadow - float lit = mix(center, sum, softShadows); + float lit = mix(center, sum, SOFT_SHADOWS); // multiply the summed amount by our distance, which gives us a radial falloff // then multiply by vertex (light) color diff --git a/srlight_topolar.frag b/srlight_topolar.frag new file mode 100644 index 0000000..b30edf7 --- /dev/null +++ b/srlight_topolar.frag @@ -0,0 +1,30 @@ +#version 120 + +#define PI 3.1415926 + +uniform sampler2D tex0; +uniform vec2 lightTexSize; + + +// alpha threshold for our occlusion map +#define THRESHOLD (0.75) + +#define inv2 (1/2.0) + + +void main (void) { + float ltsyStep = 1.0/lightTexSize.y; + float theta = PI*1.5+(gl_TexCoord[0].x*2.0-1.0)*PI; + float nsint = -sin(theta); + float ncost = -cos(theta); + float dst; + for (dst = 0.0; dst < 1.0; dst += ltsyStep) { + float r = (1.0+(dst*2.0-1.0))*0.5; + // sample the occlusion map + float dataa = texture2D(tex0, vec2(r*nsint, r*ncost)*inv2+0.5).a; + // if we've hit an opaque fragment (occluder), then get new distance + // if the new distance is below the current, then we'll use that for our ray + if (dataa > THRESHOLD) break; // the current distance is how far from the top we've come + } + gl_FragColor = vec4(vec3(dst), 1.0); +} diff --git a/srtopolar.frag b/srlight_topolar_orig.frag similarity index 85% rename from srtopolar.frag rename to srlight_topolar_orig.frag index 6319cf3..89307dd 100644 --- a/srtopolar.frag +++ b/srlight_topolar_orig.frag @@ -14,10 +14,11 @@ void main (void) { vec2 vTexCoord0 = gl_TexCoord[0].xy; float distance = 1.0; float ltsy = lightTexSize.y; - //float ltsy = 256.0; - for (float y = 0.0; y < ltsy; y += 1.0) { - float yy = ltsy-y-1.0; + float ltsyStep = 1.0/ltsy; + float yinv = 0.0; + for (float y = 0.0; y < ltsy; y += 1.0, yinv += ltsyStep) { // rectangular to polar filter + //vec2 norm = vec2(vTexCoord0.s, /*y/ltsy*/yinv)*2.0-1.0; vec2 norm = vec2(vTexCoord0.s, y/ltsy)*2.0-1.0; float theta = PI*1.5+norm.x*PI; float r = (1.0+norm.y)*0.5; diff --git a/wadarc.d b/wadarc.d index 3da297b..2c96f06 100644 --- a/wadarc.d +++ b/wadarc.d @@ -268,7 +268,7 @@ private: dir[fidx].size = lmpsize; dir[fidx].name = fixName(nm); dir[fidx].path = fixPath(nm); - debug writeln(dir[fidx].path, " : ", dir[fidx].name); + //debug writeln(dir[fidx].path, " : ", dir[fidx].name); } debug writeln(dir.length, " files found"); } diff --git a/xmain_d2d.d b/xmain_d2d.d index 92a2631..2bcb015 100644 --- a/xmain_d2d.d +++ b/xmain_d2d.d @@ -1,6 +1,10 @@ module xmain_d2d is aliced; private: +import core.atomic; +import core.thread; +import core.time; + import glbinds; import glutils; import wadarc; @@ -27,7 +31,6 @@ public enum vlWidth = 800; public enum vlHeight = 800; __gshared int scale = 1; __gshared bool scanlines = false; -__gshared bool shadowDoBloor = true; // ////////////////////////////////////////////////////////////////////////// // @@ -36,7 +39,7 @@ enum MaxLightSize = 512; // ////////////////////////////////////////////////////////////////////////// // // for light -__gshared FBO[MaxLightSize] fboOccluders, fboShadowMap; +__gshared FBO[MaxLightSize+1] fboOccluders, fboShadowMap; __gshared Shader shadToPolar, shadBlur; __gshared FBO fboLevel; @@ -56,9 +59,13 @@ void initOpenGL () { shadLiquid = new Shader("liquid", import("srliquid.frag")); // lights - shadToPolar = new Shader("topolar", import("srtopolar.frag")); - shadBlur = new Shader("blur", import("srblurlight.frag")); - foreach (int sz; 1..MaxLightSize) { + shadToPolar = new Shader("topolar", import("srlight_topolar.frag")); + shadBlur = new Shader("blur", import("srlight_blur.frag")); + shadBlur.exec({ + shadBlur["tex0"] = 0; + shadBlur["tex1"] = 1; + }); + foreach (int sz; 1..MaxLightSize+1) { // create occluders FBO fboOccluders[sz] = new FBO(sz, sz); // create 1d shadowmap FBO @@ -126,10 +133,7 @@ void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightSi // blend light fboLevel.exec({ shadBlur.exec({ - shadBlur["shadowDoBloor"] = shadowDoBloor; shadBlur["lightTexSize"] = SVec2F(lightSize, lightSize); - shadBlur["tex0"] = 0; - shadBlur["tex1"] = 1; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); // set light color @@ -145,6 +149,7 @@ void renderLight() (int lightX, int lightY, in auto ref SVec4F lcol, int lightSi // ////////////////////////////////////////////////////////////////////////// // __gshared int lightX = vlWidth/2, lightY = vlHeight/2; __gshared int mapOfsX, mapOfsY; +__gshared bool movement = false; void renderScene () { @@ -160,7 +165,7 @@ void renderScene () { orthoCamera(map.width*8, map.height*8); // draw background - glColor3f(1.0f, 1.0f, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, 0.0f); //drawAtXY(map.texgl.ptr[map.Back], 0, 0); // water, acid, lava shadLiquid.exec({ @@ -192,19 +197,21 @@ void renderScene () { glBindTexture(GL_TEXTURE_2D, map.texgl.ptr[map.Back].tid); glActiveTexture(GL_TEXTURE0+0); - renderLight( 27, map.height*8-1-391-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); - renderLight(542, map.height*8-1-424-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); - renderLight(377, map.height*8-1-368-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 32); - renderLight(147, map.height*8-1-288-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 64); - renderLight( 71, map.height*8-1-200-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); - renderLight(249, map.height*8-1-200-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); - renderLight(426, map.height*8-1-200-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); - renderLight(624, map.height*8-1-200-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); - renderLight(549, map.height*8-1-298-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 64); - renderLight( 74, map.height*8-1-304-2, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 32); - renderLight(24*8+4, map.height*8-1-(24+18)*8-2, SVec4F(0.6f, 0.0f, 0.0f, 1.0f), 128); + renderLight( 27, map.height*8-1-391-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); + renderLight(542, map.height*8-1-424-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); + renderLight(377, map.height*8-1-368-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 32); + renderLight(147, map.height*8-1-288-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 64); + renderLight( 71, map.height*8-1-200-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); + renderLight(249, map.height*8-1-200-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); + renderLight(426, map.height*8-1-200-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); + renderLight(624, map.height*8-1-200-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 128); + renderLight(549, map.height*8-1-298-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 64); + renderLight( 74, map.height*8-1-304-0, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 32); - //renderLight(lightX, lightY, SVec3F(1.0f, 1.0f, 0.0f), 128); + renderLight(24*8+4, map.height*8-1-(24+18)*8-2, SVec4F(0.6f, 0.0f, 0.0f, 1.0f), 128); + foreach (immutable _; 0..20) { + renderLight(lightX, lightY, SVec4F(0.3f, 0.3f, 0.0f, 1.0f), 256); + } // restore blending fboLevel.exec({ @@ -230,7 +237,106 @@ void renderScene () { // ////////////////////////////////////////////////////////////////////////// // -public void main () { +// rendering thread +shared int diedie = 0; + + +void renderThread () { + MonoTime prevFrameStartTime = MonoTime.currTime; + version(use_vsync) {} else MonoTime ltt = MonoTime.currTime; + MonoTime lasttime = MonoTime.currTime; + MonoTime time; + enum MaxFPSFrames = 16; + float frtimes = 0.0f; + int framenum = 0; + int prevFPS = -1; + bool first = true; + for (;;) { + if (sdwindow.closed) break; + if (atomicLoad(diedie) > 0) break; + + time = MonoTime.currTime; + version(use_vsync) { + } else { + // max 60 FPS; capped by vsync + //{ import core.stdc.stdio; printf(" spent only %d msecs\n", cast(int)((time-ltt).total!"msecs")); } + if (!first && (time-ltt).total!"msecs" < 16) { + //{ import core.stdc.stdio; printf(" spent only %d msecs\n", cast(int)((time-ltt).total!"msecs")); } + import core.sys.posix.signal : timespec; + import core.sys.posix.time : nanosleep; + timespec ts = void; + ts.tv_sec = 0; + ts.tv_nsec = (16-cast(int)((time-ltt).total!"msecs"))*1000*1000; // milli to nano + nanosleep(&ts, null); // idc how much time was passed + time = MonoTime.currTime; + } + ltt = time; + first = false; + } + + { + auto frameTime = cast(float)(time-prevFrameStartTime).total!"msecs"/1000.0f; + prevFrameStartTime = time; + + //{ import core.stdc.stdio; printf("frametime: %f\n", frameTime*1000.0f); } + //{ import core.stdc.stdio; printf("FPS: %d\n", cast(int)(1.0f/frameTime)); } + frtimes += frameTime; + if (++framenum >= MaxFPSFrames || frtimes >= 3.0f) { + import std.string : format; + int newFPS = cast(int)(cast(float)MaxFPSFrames/frtimes+0.5); + if (newFPS != prevFPS) { + sdwindow.title = "%s / FPS:%s".format("D2D", newFPS); + prevFPS = newFPS; + } + framenum = 0; + frtimes = 0.0f; + } + + XLockDisplay(sdwindow.display); + if (glXMakeCurrent(sdwindow.display, sdwindow.window, sdwindow.glc) == 0) { + XUnlockDisplay(sdwindow.display); + { import core.stdc.stdio; printf(" FUUUU\n"); } + //glXMakeCurrent(sdwindow.display, 0, null); + import core.sys.posix.signal : timespec; + import core.sys.posix.time : nanosleep; + timespec ts = void; + ts.tv_sec = 0; + ts.tv_nsec = 16*1000*1000; // milli to nano + nanosleep(&ts, null); // idc how much time was passed + time = MonoTime.currTime; + continue; + } + XUnlockDisplay(sdwindow.display); + renderScene(); + XLockDisplay(sdwindow.display); + glXSwapBuffers(sdwindow.display, sdwindow.window); + glFinish(); + glXMakeCurrent(sdwindow.display, 0, null); + XUnlockDisplay(sdwindow.display); + } + } + atomicStore(diedie, 2); +} + + +// ////////////////////////////////////////////////////////////////////////// // +void closeWindow () { + if (atomicLoad(diedie) != 2) { + atomicStore(diedie, 1); + while (atomicLoad(diedie) != 2) {} + } + if (!sdwindow.closed) { + flushGui(); + sdwindow.close(); + } +} + + +// ////////////////////////////////////////////////////////////////////////// // +__gshared Thread renderTid; + + +void main () { static void setDP () { version(rdmd) { setDataPath("data"); @@ -254,19 +360,22 @@ public void main () { mapOfsX = 8*36; mapOfsY = 8*56; - sdwindow = new SimpleWindow(vlWidth, vlHeight, "OpenGL 2d soft shadows", OpenGlOptions.yes, Resizablity.fixedSize); + sdwindow = new SimpleWindow(vlWidth, vlHeight, "D2D", OpenGlOptions.yes, Resizablity.fixedSize); sdwindow.visibleForTheFirstTime = delegate () { sdwindow.setAsCurrentOpenGlContext(); // make this window active sdwindow.vsync = false; //sdwindow.useGLFinish = false; initOpenGL(); - sdwindow.redrawOpenGlScene(); + //sdwindow.redrawOpenGlScene(); + if (!renderTid) { + if (glXMakeCurrent(sdwindow.display, 0, null) == 0) { import core.stdc.stdio; printf("can't release OpenGL context(1)\n"); } + renderTid = new Thread(&renderThread); + renderTid.start(); + } }; - sdwindow.redrawOpenGlScene = delegate () { - renderScene(); - }; + //sdwindow.redrawOpenGlScene = delegate () { renderScene(); }; enum MSecsPerFrame = 1000/30; /* 30 is FPS */ @@ -284,17 +393,16 @@ public void main () { import std.math : cos, sin; __gshared float itime = 0.0; itime += 0.02; - mapOfsX = cast(int)(800.0/2.0+cos(itime)*220.0); - mapOfsY = cast(int)(800.0/2.0+120.0+sin(itime)*160.0); + if (movement) { + mapOfsX = cast(int)(800.0/2.0+cos(itime)*220.0); + mapOfsY = cast(int)(800.0/2.0+120.0+sin(itime)*160.0); + } if (scale == 1) mapOfsX = mapOfsY = 0; - sdwindow.redrawOpenGlSceneNow(); + //sdwindow.redrawOpenGlSceneNow(); }, delegate (KeyEvent event) { if (sdwindow.closed) return; - if (event.pressed && event.key == Key.Escape) { - flushGui(); - sdwindow.close(); - } + if (event.pressed && event.key == Key.Escape) { closeWindow(); return; } switch (event.key) { case Key.Left: pressed[Left] = event.pressed; break; case Key.Right: pressed[Right] = event.pressed; break; @@ -310,13 +418,13 @@ public void main () { lightY += mapOfsY/scale; }, delegate (dchar ch) { + if (ch == 'q') { closeWindow(); return; } if (ch == 's') scanlines = !scanlines; - if (ch == 'q') { flushGui(); sdwindow.close(); } if (ch == '1') scale = 1; if (ch == '2') scale = 2; - if (ch == 'b') shadowDoBloor = !shadowDoBloor; + if (ch == ' ') movement = !movement; }, ); - if (!sdwindow.closed) { flushGui(); sdwindow.close(); } + closeWindow(); flushGui(); } -- 2.11.4.GIT