Engine: experimental3D
authorsmaxx
Wed, 18 Aug 2010 20:29:41 +0200
branchexperimental3D
changeset 3696 6009d8378422
parent 3694 3e9c0634065c
child 3698 793386610068
Engine: * Rewrote stereo rendering * Simplified anaglyph rendering (no longer requires framebuffers) * Added stereo mode selection: Anaglyph (different combinations of red, green, blue and cyan), side-by-side (horizontal and vertical) and alternate frame rendering (AFR)
QTfrontend/game.cpp
QTfrontend/gameuiconfig.cpp
QTfrontend/gameuiconfig.h
QTfrontend/pages.cpp
QTfrontend/pages.h
hedgewars/hwengine.pas
hedgewars/uConsts.pas
hedgewars/uMisc.pas
hedgewars/uStore.pas
hedgewars/uWorld.pas
--- a/QTfrontend/game.cpp	Mon Aug 02 15:05:56 2010 +0200
+++ b/QTfrontend/game.cpp	Wed Aug 18 20:29:41 2010 +0200
@@ -288,7 +288,7 @@
     arguments << config->netNick().toUtf8().toBase64();
     arguments << (config->isMusicEnabled() ? "1" : "0");
     arguments << QString::number(config->translateQuality());
-    arguments << (config->isStereoEnabled() ? "1" : "0");
+    arguments << QString::number(config->stereoMode());
     return arguments;
 }
 
--- a/QTfrontend/gameuiconfig.cpp	Mon Aug 02 15:05:56 2010 +0200
+++ b/QTfrontend/gameuiconfig.cpp	Wed Aug 18 20:29:41 2010 +0200
@@ -48,7 +48,7 @@
     Form->ui.pageOptions->CBFrontendFullscreen->setChecked(ffscr);
 
     Form->ui.pageOptions->SLQuality->setValue(value("video/quality", 5).toUInt());
-    Form->ui.pageOptions->CBEnableStereo->setChecked(value("video/anaglyph", false).toBool());
+    Form->ui.pageOptions->CBStereoMode->setCurrentIndex(value("video/stereo", 0).toUInt());
     Form->ui.pageOptions->CBFrontendEffects->setChecked(frontendEffects);
     Form->ui.pageOptions->CBEnableSound->setChecked(value("audio/sound", true).toBool());
     Form->ui.pageOptions->CBEnableFrontendSound->setChecked(value("frontend/sound", true).toBool());
@@ -114,7 +114,7 @@
     setValue("video/fullscreen", vid_Fullscreen());
 
     setValue("video/quality", Form->ui.pageOptions->SLQuality->value());
-    setValue("video/anaglyph", isStereoEnabled());
+    setValue("video/stereo", stereoMode());
 
     setValue("frontend/effects", isFrontendEffects());
 
@@ -263,9 +263,9 @@
     return Form->ui.pageOptions->CBAltDamage->isChecked();
 }
 
-bool GameUIConfig::isStereoEnabled() const
+quint32 GameUIConfig::stereoMode() const
 {
-    return Form->ui.pageOptions->CBEnableStereo->isChecked();
+    return Form->ui.pageOptions->CBStereoMode->currentIndex();
 }
 
 bool GameUIConfig::appendDateTimeToRecordName()
--- a/QTfrontend/gameuiconfig.h	Mon Aug 02 15:05:56 2010 +0200
+++ b/QTfrontend/gameuiconfig.h	Wed Aug 18 20:29:41 2010 +0200
@@ -52,7 +52,7 @@
     bool isFrontendEffects() const;
     bool isFrontendFullscreen() const;
     void resizeToConfigValues();
-    bool isStereoEnabled() const;
+    quint32 stereoMode() const;
 
 #ifdef __APPLE__
 #ifdef SPARKLE_ENABLED
--- a/QTfrontend/pages.cpp	Mon Aug 02 15:05:56 2010 +0200
+++ b/QTfrontend/pages.cpp	Wed Aug 18 20:29:41 2010 +0200
@@ -573,6 +573,7 @@
 
             QVBoxLayout * GBAlayout = new QVBoxLayout(AGGroupBox);
             QHBoxLayout * GBAreslayout = new QHBoxLayout(0);
+            QHBoxLayout * GBAstereolayout = new QHBoxLayout(0);
             QHBoxLayout * GBAqualayout = new QHBoxLayout(0);
 
             CBFrontendFullscreen = new QCheckBox(AGGroupBox);
@@ -621,9 +622,24 @@
             GBAqualayout->addWidget(SLQuality);
             GBAlayout->addLayout(GBAqualayout);
 
-            CBEnableStereo = new QCheckBox(AGGroupBox);
-            CBEnableStereo->setText(QCheckBox::tr("Anaglyph rendering (red/cyan)"));
-            GBAlayout->addWidget(CBEnableStereo);
+            QLabel * stereo = new QLabel(AGGroupBox);
+            stereo->setText(QLabel::tr("Stereo rendering"));
+            GBAstereolayout->addWidget(stereo);
+
+            CBStereoMode = new QComboBox(AGGroupBox);
+            CBStereoMode->addItem(QComboBox::tr("Disabled"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Cyan"));
+            CBStereoMode->addItem(QComboBox::tr("Cyan/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Blue"));
+            CBStereoMode->addItem(QComboBox::tr("Blue/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Green"));
+            CBStereoMode->addItem(QComboBox::tr("Green/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Side-by-side (horizontal)"));
+            CBStereoMode->addItem(QComboBox::tr("Side-by-side (vertical)"));
+            CBStereoMode->addItem(QComboBox::tr("Alternate frame rendering"));
+
+            GBAstereolayout->addWidget(CBStereoMode);
+            GBAlayout->addLayout(GBAstereolayout);
 
             hr = new QFrame(AGGroupBox);
             hr->setFrameStyle(QFrame::HLine);
--- a/QTfrontend/pages.h	Mon Aug 02 15:05:56 2010 +0200
+++ b/QTfrontend/pages.h	Wed Aug 18 20:29:41 2010 +0200
@@ -220,9 +220,9 @@
     QComboBox *CBTeamName;
     IconedGroupBox *AGGroupBox;
     QComboBox *CBResolution;
+    QComboBox *CBStereoMode;
     QCheckBox *CBEnableSound;
     QCheckBox *CBEnableFrontendSound;
-    QCheckBox *CBEnableStereo;
     QCheckBox *CBEnableMusic;
     QCheckBox *CBEnableFrontendMusic;
     QCheckBox *CBFullscreen;
--- a/hedgewars/hwengine.pas	Mon Aug 02 15:05:56 2010 +0200
+++ b/hedgewars/hwengine.pas	Wed Aug 18 20:29:41 2010 +0200
@@ -230,7 +230,7 @@
     recordFileName:= gameArgs[8];
     
     val(gameArgs[9], cReducedQuality);
-    isStereoEnabled:= false; // TODO: Enable anaglyph rendering on iPhone?
+    cStereoMode:= smNone; // TODO: Enable anaglyph rendering on iPhone?
 {$ENDIF}
 
     initEverything(true);
@@ -437,6 +437,7 @@
 
 ////////////////////
 procedure GetParams;
+var i : LongInt;
 begin
     case ParamCount of
         19: begin
@@ -458,7 +459,8 @@
             UserNick:= DecodeBase64(ParamStr(16));
             isMusicEnabled:= ParamStr(17) = '1';
             val(ParamStr(18), cReducedQuality);
-            isStereoEnabled:= ParamStr(19) = '1';
+            val(ParamStr(19), i);
+            cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), i)));
         end;
         3: begin
             val(ParamStr(2), ipcPort);
--- a/hedgewars/uConsts.pas	Mon Aug 02 15:05:56 2010 +0200
+++ b/hedgewars/uConsts.pas	Wed Aug 18 20:29:41 2010 +0200
@@ -141,6 +141,9 @@
 
     TWave = (waveRollup, waveSad, waveWave, waveHurrah, waveLemonade, waveShrug, waveJuggle);
 
+    TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
+    TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical, smAFR);
+
     THHFont = record
             Handle: PTTF_Font;
             Height: LongInt;
--- a/hedgewars/uMisc.pas	Mon Aug 02 15:05:56 2010 +0200
+++ b/hedgewars/uMisc.pas	Wed Aug 18 20:29:41 2010 +0200
@@ -35,7 +35,8 @@
     isSpeed         : boolean;
     isFirstFrame    : boolean;
 
-    isStereoEnabled : boolean;
+    //isStereoEnabled : boolean;
+    cStereoMode     : TStereoMode;
 
     fastUntilLag    : boolean;
 
--- a/hedgewars/uStore.pas	Mon Aug 02 15:05:56 2010 +0200
+++ b/hedgewars/uStore.pas	Wed Aug 18 20:29:41 2010 +0200
@@ -803,7 +803,7 @@
     SDL_FreeSurface(MissionIcons);
     FreeTexture(ropeIconTex);
     FreeTexture(HHTexture);
-    if isStereoEnabled then
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
     begin
         glDeleteTextures(1, @texl);
         glDeleteRenderbuffersEXT(1, @depthl);
@@ -1192,7 +1192,7 @@
         cGPUVendor:= gvIntel;
 //SupportNPOTT:= glLoadExtension('GL_ARB_texture_non_power_of_two');
 
-    if isStereoEnabled then
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
     begin
         // prepare left and right frame buffers and associated textures
         glLoadExtension('GL_EXT_framebuffer_object');
--- a/hedgewars/uWorld.pas	Mon Aug 02 15:05:56 2010 +0200
+++ b/hedgewars/uWorld.pas	Wed Aug 18 20:29:41 2010 +0200
@@ -22,19 +22,19 @@
 interface
 uses SDLh, uGears, uConsts, uFloat, uRandom;
 
-type TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
-
 var FollowGear: PGear;
     WindBarWidth: LongInt;
     bShowAmmoMenu: boolean;
     bSelected: boolean;
     bShowFinger: boolean;
     Frames: Longword;
+    AFRToggle: Boolean;
     WaterColor, DeepWaterColor: TSDL_Color;
     WorldDx: LongInt;
     WorldDy: LongInt;
     SkyOffset: LongInt;
     HorizontOffset: LongInt;
+    bAFRRight: Boolean;
 {$IFDEF COUNTTICKS}
     cntTicks: LongWord;
 {$ENDIF}
@@ -564,13 +564,22 @@
     if not isPaused then
         MoveCamera;
 
-    if not isStereoEnabled then
-    begin
+    if cStereoMode = smNone then
+        begin
         glClear(GL_COLOR_BUFFER_BIT);
         DrawWorldStereo(Lag, rmDefault)
-    end
-    else
-    begin
+        end
+    else if (cStereoMode = smAFR) then
+        begin
+        AFRToggle:= not AFRToggle;
+        glClear(GL_COLOR_BUFFER_BIT);
+        if AFRToggle then
+            DrawWorldStereo(Lag, rmLeftEye)
+        else
+            DrawWorldStereo(Lag, rmRightEye)
+        end
+    else if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+        begin
         // create left fb
         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel);
         glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
@@ -583,56 +592,97 @@
 
         // detatch drawing from fbs
         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-        glGetFloatv(GL_COLOR_CLEAR_VALUE, @cc);
-        glClearColor(0, 0, 0, 0);
         glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
-        glClearColor(cc[0], cc[1], cc[2], cc[3]);
         SetScale(cDefaultZoomLevel);
 
-        // enable gl stuff
-        glEnable(GL_TEXTURE_2D);
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_ONE, GL_ONE);
-
         // draw left frame
         glBindTexture(GL_TEXTURE_2D, texl);
-        glColor3f(0.0, 1.0, 1.0);
         glBegin(GL_QUADS);
-            glTexCoord2f(0.0, 0.0);
-            glVertex2d(cScreenWidth / -2, cScreenHeight);
-            glTexCoord2f(1.0, 0.0);
-            glVertex2d(cScreenWidth / 2, cScreenHeight);
-            glTexCoord2f(1.0, 1.0);
-            glVertex2d(cScreenWidth / 2, 0);
-            glTexCoord2f(0.0, 1.0);
-            glVertex2d(cScreenWidth / -2, 0);
+            if cStereoMode = smHorizontal then
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(0, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(0, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, 0);
+                end
+            else
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight / 2);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight / 2);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, 0);
+                end;
         glEnd();
 
         // draw right frame
         glBindTexture(GL_TEXTURE_2D, texr);
-        glColor3f(1.0, 0.0, 0.0);
         glBegin(GL_QUADS);
-            glTexCoord2f(0.0, 0.0);
-            glVertex2d(cScreenWidth / -2, cScreenHeight);
-            glTexCoord2f(1.0, 0.0);
-            glVertex2d(cScreenWidth / 2, cScreenHeight);
-            glTexCoord2f(1.0, 1.0);
-            glVertex2d(cScreenWidth / 2, 0);
-            glTexCoord2f(0.0, 1.0);
-            glVertex2d(cScreenWidth / -2, 0);
+            if cStereoMode = smHorizontal then
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(0, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(0, 0);
+                end
+            else
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight / 2);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight / 2);
+                end;
         glEnd();
-
-        // reset
-        glColor3f(1.0, 1.0, 1.0);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         SetScale(zoom);
-    end
+        end
+    else
+        begin
+        // clear scene
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        // draw left eye in red channel only
+        if cStereoMode = smGreenRed then
+            glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)
+        else if cStereoMode = smBlueRed then
+            glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
+        else if cStereoMode = smCyanRed then
+            glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
+        else
+            glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
+        DrawWorldStereo(Lag, rmLeftEye);
+        // draw right eye in selected channel(s) only
+        if cStereoMode = smRedGreen then
+            glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)
+        else if cStereoMode = smRedBlue then
+            glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
+        else if cStereoMode = smRedCyan then
+            glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
+        else
+            glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
+        DrawWorldStereo(Lag, rmRightEye);
+        end
 end;
 
 procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
 begin
+    d:= d / 5;
     if rm = rmDefault then exit
-    else if rm = rmRightEye then d:= -d;
+    else if rm = rmLeftEye then d:= -d;
     stereoDepth:= stereoDepth + d;
     glMatrixMode(GL_PROJECTION);
     glTranslatef(d, 0, 0);
@@ -971,7 +1021,7 @@
 offsetY:= cOffsetY;
 
 // don't increment fps when drawing the right frame
-if (RM = rmDefault) or (RM = rmLeftEye) then
+if (RM = rmDefault) or (RM = rmRightEye) then
 begin
     inc(Frames);