creating a new branch for experimental 3d stereographic rendering
currently it contains only an updated version of the anaglyph patch by Smaxx
--- a/.hgeol Thu Jul 29 18:31:48 2010 -0400
+++ b/.hgeol Fri Jul 30 13:07:46 2010 +0200
@@ -1,6 +1,7 @@
[patterns]
**.h = native
**.c = native
+**.m = native
**.cpp = native
**.lua = native
**.txt = native
--- a/hedgewars/uMisc.pas Thu Jul 29 18:31:48 2010 -0400
+++ b/hedgewars/uMisc.pas Fri Jul 30 13:07:46 2010 +0200
@@ -35,6 +35,8 @@
isSpeed : boolean;
isFirstFrame : boolean;
+ isStereoEnabled : boolean = true;
+
fastUntilLag : boolean;
GameState : TGameState;
--- a/hedgewars/uStore.pas Thu Jul 29 18:31:48 2010 -0400
+++ b/hedgewars/uStore.pas Fri Jul 30 13:07:46 2010 +0200
@@ -39,7 +39,9 @@
rotationQt: GLfloat;
wScreen: LongInt;
hScreen: LongInt;
-
+ framel, framer, depthl, depthr: GLuint;
+ texl, texr: GLuint;
+
procedure initModule;
procedure freeModule;
@@ -801,6 +803,15 @@
SDL_FreeSurface(MissionIcons);
FreeTexture(ropeIconTex);
FreeTexture(HHTexture);
+ if isStereoEnabled then
+ begin
+ glDeleteTextures(1, @texl);
+ glDeleteRenderbuffersEXT(1, @depthl);
+ glDeleteFramebuffersEXT(1, @framel);
+ glDeleteTextures(1, @texr);
+ glDeleteRenderbuffersEXT(1, @depthr);
+ glDeleteFramebuffersEXT(1, @framer)
+ end
end;
@@ -1170,7 +1181,9 @@
{$ENDIF}
end;
-{$IFNDEF IPHONEOS}
+{$IFDEF IPHONEOS}
+ cGPUVendor:= gvApple;
+{$ELSE}
if StrPos(Str2PChar(vendor), Str2PChar('nvidia')) <> nil then
cGPUVendor:= gvNVIDIA
else if StrPos(Str2PChar(vendor), Str2PChar('intel')) <> nil then
@@ -1178,8 +1191,37 @@
else if StrPos(Str2PChar(vendor), Str2PChar('ati')) <> nil then
cGPUVendor:= gvIntel;
//SupportNPOTT:= glLoadExtension('GL_ARB_texture_non_power_of_two');
-{$ELSE}
- cGPUVendor:= gvApple;
+ if isStereoEnabled then
+ begin
+ glLoadExtension('GL_EXT_framebuffer_object');
+ glGenFramebuffersEXT(1, @framel);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel);
+ glGenRenderbuffersEXT(1, @depthl);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthl);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthl);
+ glGenTextures(1, @texl);
+ glBindTexture(GL_TEXTURE_2D, texl);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cScreenWidth, cScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texl, 0);
+
+ glGenFramebuffersEXT(1, @framer);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framer);
+ glGenRenderbuffersEXT(1, @depthr);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthr);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthr);
+ glGenTextures(1, @texr);
+ glBindTexture(GL_TEXTURE_2D, texr);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cScreenWidth, cScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texr, 0);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
+ end;
{$ENDIF}
{$IFDEF DEBUGFILE}
--- a/hedgewars/uWorld.pas Thu Jul 29 18:31:48 2010 -0400
+++ b/hedgewars/uWorld.pas Fri Jul 30 13:07:46 2010 +0200
@@ -22,6 +22,7 @@
interface
uses SDLh, uGears, uConsts, uFloat, uRandom;
+type TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
var FollowGear: PGear;
WindBarWidth: LongInt;
@@ -44,6 +45,7 @@
procedure InitWorld;
procedure DrawWorld(Lag: LongInt);
+procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
procedure AddCaption(s: shortstring; Color: Longword; Group: TCapGroup);
procedure ShowMission(caption, subcaption, text: ansistring; icon, time : LongInt);
procedure HideMission;
@@ -528,14 +530,7 @@
procedure DrawWorld(Lag: LongInt);
-var i, t: LongInt;
- r: TSDL_Rect;
- tdx, tdy: Double;
- grp: TCapGroup;
- s: string[15];
- highlight: Boolean;
- offset, offsetX, offsetY, ScreenBottom: LongInt;
- VertexBuffer: array [0..3] of TVertex2f;
+var cc: array[0..3] of GLfloat;
begin
if not isPaused then
begin
@@ -564,6 +559,93 @@
if not isPaused then
MoveCamera;
+ if not isStereoEnabled then
+ begin
+ glClear(GL_COLOR_BUFFER_BIT);
+ DrawWorldStereo(Lag, rmDefault)
+ end
+ else
+ begin
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+ DrawWorldStereo(Lag, rmLeftEye);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framer);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+ DrawWorldStereo(0, rmRightEye);
+ 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(2.0);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ 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);
+ glEnd();
+ 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);
+ glEnd();
+ glColor3f(1.0, 1.0, 1.0);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ SetScale(zoom);
+ end
+end;
+
+ const cStereo_Sky = 0.0750;
+ cStereo_Horizon = 0.0250;
+ cStereo_Water = 0.0125;
+ var stereoDepth: GLfloat = 0;
+
+ procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
+ begin
+ if rm = rmDefault then exit
+ else if rm = rmRightEye then d:= -d;
+ stereoDepth:= stereoDepth + d;
+ glMatrixMode(GL_PROJECTION);
+ glTranslatef(d, 0, 0);
+ glMatrixMode(GL_MODELVIEW)
+ end;
+
+ procedure ResetDepth(rm: TRenderMode);
+ begin
+ if rm = rmDefault then exit;
+ glMatrixMode(GL_PROJECTION);
+ glTranslatef(-stereoDepth, 0, 0);
+ glMatrixMode(GL_MODELVIEW);
+ stereoDepth:= 0;
+ end;
+
+ procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
+ var i, t: LongInt;
+ r: TSDL_Rect;
+ tdx, tdy: Double;
+ grp: TCapGroup;
+ s: string[15];
+ highlight: Boolean;
+ offset, offsetX, offsetY, screenBottom: LongInt;
+ scale: GLfloat;
+ VertexBuffer: array [0..3] of TVertex2f;
+ begin
if (cReducedQuality and rqNoBackground) = 0 then
begin
// Offsets relative to camera - spare them to wimpier cpus, no bg or flakes for them anyway
@@ -575,7 +657,9 @@
HorizontOffset:= HorizontOffset + ((ScreenBottom-SkyOffset) div 20);
// background
+ChangeDepth(RM, cStereo_Sky);
DrawRepeated(sprSky, sprSkyL, sprSkyR, (WorldDx + LAND_WIDTH div 2) * 3 div 8, SkyOffset);
+ChangeDepth(RM, -cStereo_Horizon);
DrawRepeated(sprHorizont, sprHorizontL, sprHorizontR, (WorldDx + LAND_WIDTH div 2) * 3 div 5, HorizontOffset);
end;
@@ -585,10 +669,15 @@
begin
// Waves
DrawWater(255, SkyOffset);
+ChangeDepth(RM, -cStereo_Water);
DrawWaves( 1, 0 - WorldDx div 32, - cWaveHeight + offsetY div 35, 64);
+ChangeDepth(RM, -cStereo_Water);
DrawWaves( -1, 25 + WorldDx div 25, - cWaveHeight + offsetY div 38, 48);
+ChangeDepth(RM, -cStereo_Water);
DrawWaves( 1, 75 - WorldDx div 19, - cWaveHeight + offsetY div 45, 32);
+ChangeDepth(RM, -cStereo_Water);
DrawWaves(-1, 100 + WorldDx div 14, - cWaveHeight + offsetY div 70, 24);
+ResetDepth(RM);
end
else
DrawWaves(-1, 100, - (cWaveHeight + (cWaveHeight shr 1)), 0);
@@ -628,16 +717,21 @@
DrawWater(cWaterOpacity, 0);
// Waves
+ChangeDepth(RM, cStereo_Water);
DrawWaves( 1, 25 - WorldDx div 9, - cWaveHeight, 12);
if (cReducedQuality and rq2DWater) = 0 then
begin
//DrawWater(cWaterOpacity, - offsetY div 40);
+ChangeDepth(RM, cStereo_Water);
DrawWaves(-1, 50 + WorldDx div 6, - cWaveHeight - offsetY div 40, 8);
DrawWater(cWaterOpacity, - offsetY div 20);
+ChangeDepth(RM, cStereo_Water);
DrawWaves( 1, 75 - WorldDx div 4, - cWaveHeight - offsetY div 20, 2);
DrawWater(cWaterOpacity, - offsetY div 10);
+ChangeDepth(RM, cStereo_Water);
DrawWaves( -1, 25 + WorldDx div 3, - cWaveHeight - offsetY div 10, 0);
+ResetDepth(RM);
end
else
DrawWaves(-1, 50, - (cWaveHeight shr 1), 0);
@@ -862,6 +956,8 @@
offsetX:= 10;
{$ENDIF}
offsetY:= cOffsetY;
+if (RM = rmDefault) or (RM = rmLeftEye) then
+begin
inc(Frames);
if cShowFPS or (GameType = gmtDemo) then inc(CountTicks, Lag);
@@ -914,6 +1010,8 @@
// lag warning (?)
inc(SoundTimerTicks, Lag);
+end;
+
if SoundTimerTicks >= 50 then
begin
SoundTimerTicks:= 0;