level scrolling
[dd2d.git] / xmain.d
blobddc02ff8321bf6886a0eefef98a9e86740f9d4bf
1 // main driver
2 module gfxcore;
4 private:
5 import iv.glbinds;
6 import glutils;
8 import wadarc;
11 // ////////////////////////////////////////////////////////////////////////// //
12 import arsd.color;
13 import arsd.png;
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 // ////////////////////////////////////////////////////////////////////////// //
37 enum LightSize = 256;
40 // ////////////////////////////////////////////////////////////////////////// //
41 void initOpenGL () {
42 glEnable(GL_TEXTURE_2D);
43 glDisable(GL_LIGHTING);
44 glDisable(GL_DITHER);
45 glDisable(GL_BLEND);
46 glDisable(GL_DEPTH_TEST);
48 // load textures
49 texMain = new Texture("shadow_experiment/cat4.png");
50 //lightDot = new Texture("shadow_experiment/dot.png");
51 lightDot = new Texture("shadow_experiment/light.png");
53 // create shaders
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);
63 // setup matrices
64 glMatrixMode(GL_MODELVIEW);
65 glLoadIdentity();
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
77 glUseProgram(0);
78 glDisable(GL_BLEND);
79 fboOccluders.exec({
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*/);
85 });
87 // //////////////////////////////////////////////////////////////////// //
88 // build 1d shadow map to fboShadowMapId
89 fboShadowMap.exec({
90 shadToPolar.exec({
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);
97 });
98 });
100 // //////////////////////////////////////////////////////////////////// //
101 fboLevel.exec({
102 shadBlur.exec({
103 shadBlur["lightTexSize"] = SVec2F(LightSize, LightSize);
104 glEnable(GL_BLEND);
105 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
106 // set light color
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 () {
121 version(rdmd) {
122 setDataPath("data");
123 } else {
124 import std.file : thisExePath;
125 import std.path : dirName;
126 setDataPath(thisExePath.dirName);
130 setDP();
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;
140 initOpenGL();
141 sdwindow.redrawOpenGlScene();
144 sdwindow.redrawOpenGlScene = delegate () {
145 enum BackIntens = 0.25f;
147 glUseProgram(0);
149 // clear background (so we can see lights and shadows ;-)
150 fboLevel.exec({
151 glDisable(GL_BLEND);
152 glClearColor(BackIntens, BackIntens, BackIntens, 1.0f);
153 glClear(GL_COLOR_BUFFER_BIT);
156 // background
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);
162 // additive lights
163 glEnable(GL_BLEND);
164 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
166 renderLight(lightX, lightY);
168 // final render
169 glColor3f(1.0f, 1.0f, 1.0f);
171 // overlay normal scene
172 glEnable(GL_BLEND);
173 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
175 // draw final opaque and full-lit parts
176 fboLevel.exec({
177 glEnable(GL_BLEND);
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);
189 // distance FBO
190 //drawAtXY(fboOccluders.tex, lightX-LightSize/2, lightY-LightSize/2);
191 drawAtXY(fboShadowMap.tex, vlWidth-fboShadowMap.tex.width, vlHeight-LightSize-4);
193 // mark light area
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,
206 delegate () {
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) {
213 flushGui();
214 sdwindow.close();
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(); }
226 flushGui();