11 // ////////////////////////////////////////////////////////////////////////// //
16 __gshared SimpleWindow sdwindow
;
19 public enum vlWidth
= 800;
20 public enum vlHeight
= 600;
21 public enum scale
= 1;
23 public enum vlEffectiveWidth
= vlWidth
*scale
;
24 public enum vlEffectiveHeight
= vlHeight
*scale
;
27 // ////////////////////////////////////////////////////////////////////////// //
28 __gshared Texture texMain
;
29 __gshared Texture lightDot
;
31 __gshared FBO fboOccluders
, fboShadowMap
, fboLevel
;
33 __gshared Shader shadScanlines
, shadToPolar
, shadBlur
;
36 // ////////////////////////////////////////////////////////////////////////// //
40 // ////////////////////////////////////////////////////////////////////////// //
42 glEnable(GL_TEXTURE_2D
);
43 glDisable(GL_LIGHTING
);
46 glDisable(GL_DEPTH_TEST
);
49 texMain
= new Texture("shadow_experiment/cat4.png");
50 //lightDot = new Texture("shadow_experiment/dot.png");
51 lightDot
= new Texture("shadow_experiment/light.png");
54 shadToPolar
= new Shader("topolar", loadTextFile("data/shaders/srlight_topolar.frag"));
55 shadBlur
= new Shader("blur", loadTextFile("data/shaders/srlight_blur.frag"));
57 // create occluders FBO
58 fboOccluders
= new FBO(LightSize
, LightSize
);
60 // create 1d shadowmap FBO
61 fboShadowMap
= new FBO(LightSize
, 1, Texture
.Option
.Clamp
);
64 glMatrixMode(GL_MODELVIEW
);
67 glActiveTexture(GL_TEXTURE0
+0);
68 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
69 orthoCamera(vlWidth
, vlHeight
);
73 // ////////////////////////////////////////////////////////////////////////// //
74 void renderLight (int lightX
, int lightY
) {
75 // //////////////////////////////////////////////////////////////////// //
76 // draw shadow casters to fboOccludersId, light should be in the center
80 glColor3f(0.0f, 0.0f, 0.0f);
81 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
82 glClear(GL_COLOR_BUFFER_BIT
);
83 orthoCamera(LightSize
, LightSize
);
84 drawAtXY(texMain
, LightSize
/2-lightX
, LightSize
/2-lightY
/*, mirrorY:true*/);
87 // //////////////////////////////////////////////////////////////////// //
88 // build 1d shadow map to fboShadowMapId
91 glColor3f(0.0f, 0.0f, 0.0f);
92 shadToPolar
["lightTexSize"] = SVec2F(LightSize
, LightSize
);
93 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
94 glClear(GL_COLOR_BUFFER_BIT
);
95 orthoCamera(LightSize
, 1);
96 drawAtXY(fboOccluders
.tex
.tid
, 0, 0, LightSize
, 1);
100 // //////////////////////////////////////////////////////////////////// //
103 shadBlur
["lightTexSize"] = SVec2F(LightSize
, LightSize
);
105 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
107 glColor3f(1.0f, 1.0f, 0.0f);
108 orthoCamera(vlWidth
, vlHeight
);
109 drawAtXY(fboShadowMap
.tex
.tid
, lightX
-LightSize
/2, lightY
-LightSize
/2, LightSize
, LightSize
);
115 // ////////////////////////////////////////////////////////////////////////// //
116 __gshared
int lightX
= vlWidth
/2, lightY
= vlHeight
/2;
119 public void main () {
120 static void setDP () {
124 import std
.file
: thisExePath
;
125 import std
.path
: dirName
;
126 setDataPath(thisExePath
.dirName
);
132 setOpenGLContextVersion(3, 2);
134 sdwindow
= new SimpleWindow(vlEffectiveWidth
, vlEffectiveHeight
, "OpenGL 2d soft shadows", OpenGlOptions
.yes
, Resizablity
.fixedSize
);
136 sdwindow
.visibleForTheFirstTime
= delegate () {
137 sdwindow
.setAsCurrentOpenGlContext(); // make this window active
138 sdwindow
.vsync
= false;
139 //sdwindow.useGLFinish = false;
141 sdwindow
.redrawOpenGlScene();
144 sdwindow
.redrawOpenGlScene
= delegate () {
145 enum BackIntens
= 0.25f;
149 // clear background (so we can see lights and shadows ;-)
152 glClearColor(BackIntens
, BackIntens
, BackIntens
, 1.0f);
153 glClear(GL_COLOR_BUFFER_BIT
);
157 glActiveTexture(GL_TEXTURE0
+1);
158 glBindTexture(GL_TEXTURE_2D
, /*map.texgl.ptr[map.Back].tid*/texMain
.tid
);
159 //glBindTexture(GL_TEXTURE_2D, map.texgl.ptr[map.Back].tid);
160 glActiveTexture(GL_TEXTURE0
+0);
164 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
166 renderLight(lightX
, lightY
);
169 glColor3f(1.0f, 1.0f, 1.0f);
171 // overlay normal scene
173 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
175 // draw final opaque and full-lit parts
178 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
179 glColor3f(1.0f, 1.0f, 1.0f);
180 orthoCamera(vlWidth
, vlHeight
);
181 drawAtXY(texMain
.tid
, 0, 0, vlWidth
, vlHeight
);
184 // shadow casters FBO
185 //drawAtXY(fboOccluders.tex, lightX-LightSize/2, lightY-LightSize/2);
186 drawAtXY(fboOccluders
.tex
, vlWidth
-fboOccluders
.tex
.width
, vlHeight
-fboOccluders
.tex
.height
);
187 //drawAtXY(fboOccluders.tid, 0, 0, vlWidth, vlHeight);
190 //drawAtXY(fboOccluders.tex, lightX-LightSize/2, lightY-LightSize/2);
191 drawAtXY(fboShadowMap
.tex
, vlWidth
-fboShadowMap
.tex
.width
, vlHeight
-LightSize
-4);
194 drawAtXYC(lightDot
, lightX
-LightSize
/2, lightY
-LightSize
/2);
195 drawAtXYC(lightDot
, lightX
+LightSize
/2, lightY
-LightSize
/2);
196 drawAtXYC(lightDot
, lightX
, lightY
);
197 drawAtXYC(lightDot
, lightX
-LightSize
/2, lightY
+LightSize
/2);
198 drawAtXYC(lightDot
, lightX
+LightSize
/2, lightY
+LightSize
/2);
201 enum MSecsPerFrame
= 1000/30; /* 30 is FPS */
203 uint[8] frameTimes
= 1000;
205 sdwindow
.eventLoop(MSecsPerFrame
,
207 if (sdwindow
.closed
) return;
208 sdwindow
.redrawOpenGlSceneNow();
210 delegate (KeyEvent event
) {
211 if (sdwindow
.closed
) return;
212 if (event
.pressed
&& event
.key
== Key
.Escape
) {
217 delegate (MouseEvent event
) {
218 lightX
= event
.x
/scale
;
219 lightY
= event
.y
/scale
-1;
221 delegate (dchar ch
) {
222 if (ch
== 'q') { flushGui(); sdwindow
.close(); }
225 if (!sdwindow
.closed
) { flushGui(); sdwindow
.close(); }