--- a/hedgewars/uRender.pas Mon Feb 16 22:33:15 2015 +0300
+++ b/hedgewars/uRender.pas Thu Apr 02 21:09:56 2015 +0300
@@ -48,6 +48,7 @@
procedure DrawCircle (X, Y, Radius, Width: LongInt);
procedure DrawCircle (X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
+procedure DrawCircleFilled (X, Y, Radius: LongInt; r, g, b, a: Byte);
procedure DrawLine (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
procedure DrawLine (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
@@ -59,12 +60,16 @@
procedure DrawWaves (Dir, dX, dY, oX: LongInt; tnt: Byte);
procedure RenderClear ();
-procedure RenderSetClearColor (r, g, b, a: real);
+procedure RenderClear (mode: TRenderMode);
+procedure RenderSetClearColor (r, g, b, a: real);
procedure Tint (r, g, b, a: Byte); inline;
procedure Tint (c: Longword); inline;
procedure untint(); inline;
procedure setTintAdd (f: boolean); inline;
+// call this to finish the rendering of current frame
+procedure FinishRender();
+
function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
// 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen
@@ -74,13 +79,14 @@
procedure SetScale(f: GLfloat);
procedure UpdateViewLimits();
-procedure RenderSetup();
+procedure RendererSetup();
+procedure RendererCleanup();
+
+procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
+procedure ResetDepth(rm: TRenderMode);
// TODO everything below this should not need a public interface
-procedure CreateFramebuffer(var frame, depth, tex: GLuint);
-procedure DeleteFramebuffer(var frame, depth, tex: GLuint);
-
procedure EnableTexture(enable:Boolean);
procedure SetTexCoordPointer(p: Pointer;n: Integer); inline;
@@ -89,14 +95,9 @@
procedure UpdateModelviewProjection(); inline;
-procedure openglLoadIdentity (); inline;
-procedure openglTranslProjMatrix(X, Y, Z: GLFloat); inline;
procedure openglPushMatrix (); inline;
procedure openglPopMatrix (); inline;
procedure openglTranslatef (X, Y, Z: GLfloat); inline;
-procedure openglScalef (ScaleX, ScaleY, ScaleZ: GLfloat); inline;
-procedure openglRotatef (RotX, RotY, RotZ: GLfloat; dir: LongInt); inline;
-procedure openglTint (r, g, b, a: Byte); inline;
implementation
@@ -123,6 +124,20 @@
LastColorPointerN, LastTexCoordPointerN, LastVertexPointerN: Integer;
{$ENDIF}
+{$IFDEF USE_S3D_RENDERING}
+ // texture/vertex buffers for left/right/default eye modes
+ texLRDtb, texLvb, texRvb: array [0..3] of TVertex2f;
+{$ENDIF}
+
+procedure openglLoadIdentity (); forward;
+procedure openglTranslProjMatrix(X, Y, Z: GLFloat); forward;
+procedure openglScalef (ScaleX, ScaleY, ScaleZ: GLfloat); forward;
+procedure openglRotatef (RotX, RotY, RotZ: GLfloat; dir: LongInt); forward;
+procedure openglTint (r, g, b, a: Byte); forward;
+
+procedure CreateFramebuffer(var frame, depth, tex: GLuint); forward;
+procedure DeleteFramebuffer(var frame, depth, tex: GLuint); forward;
+
function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
begin
isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
@@ -147,11 +162,92 @@
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
end;
+{$IFDEF USE_S3D_RENDERING}
+procedure RenderClear(mode: TRenderMode);
+var frame: GLuint;
+begin
+ if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+ begin
+ case mode of
+ rmLeftEye: frame:= frameL;
+ rmRightEye: frame:= frameR;
+ else
+ frame:= defaultFrame;
+ end;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame);
+
+ RenderClear();
+ end
+ else
+ begin
+ // draw left eye in red channel only
+ if mode = rmLeftEye then
+ begin
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ RenderClear();
+ 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);
+ end
+ else
+ begin
+ // 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);
+ end;
+ end;
+end;
+{$ENDIF}
+
procedure RenderSetClearColor(r, g, b, a: real);
begin
glClearColor(r, g, b, a);
end;
+procedure FinishRender();
+begin
+
+{$IFDEF USE_S3D_RENDERING}
+if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+ begin
+ RenderClear(rmDefault);
+
+ SetScale(cDefaultZoomLevel);
+
+
+ // same for all
+ SetTexCoordPointer(@texLRDtb, Length(texLRDtb));
+
+
+ // draw left frame
+ glBindTexture(GL_TEXTURE_2D, texl);
+ SetVertexPointer(@texLvb, Length(texLvb));
+ //UpdateModelviewProjection;
+ glDrawArrays(GL_TRIANGLE_FAN, 0, Length(texLvb));
+
+ // draw right frame
+ glBindTexture(GL_TEXTURE_2D, texl);
+ SetVertexPointer(@texRvb, Length(texRvb));
+ //UpdateModelviewProjection;
+ glDrawArrays(GL_TRIANGLE_FAN, 0, Length(texRvb));
+
+ SetScale(zoom);
+ end;
+{$ENDIF}
+end;
+
{$IFDEF GL2}
function CompileShader(shaderFile: string; shaderType: GLenum): GLuint;
var
@@ -302,14 +398,42 @@
glDeleteRenderbuffersEXT(1, @depth);
glDeleteFramebuffersEXT(1, @frame);
end;
+{$ENDIF}
+procedure RendererCleanup();
+begin
+{$IFNDEF PAS2C}
+{$IFDEF USE_VIDEO_RECORDING}
+ if defaultFrame <> 0 then
+ DeleteFramebuffer(defaultFrame, depthv, texv);
{$ENDIF}
-procedure RenderSetup();
+{$IFDEF USE_S3D_RENDERING}
+ if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+ begin
+ DeleteFramebuffer(framel, depthl, texl);
+ DeleteFramebuffer(framer, depthr, texr);
+ end
+{$ENDIF}
+{$ENDIF}
+end;
+
+procedure RendererSetup();
var AuxBufNum: LongInt = 0;
tmpstr: ansistring;
tmpint: LongInt;
tmpn: LongInt;
begin
+{$IFDEF MOBILE}
+ // TODO: this function creates an opengles1.1 context
+ // un-comment below and add proper logic to support opengles2.0
+ //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ if SDLGLcontext = nil then
+ SDLGLcontext:= SDL_GL_CreateContext(SDLwindow);
+ SDLTry(SDLGLcontext <> nil, true);
+ SDL_GL_SetSwapInterval(1);
+{$ENDIF}
+
// suppress hint/warning
AuxBufNum:= AuxBufNum;
@@ -426,12 +550,66 @@
CreateFramebuffer(framel, depthl, texl);
CreateFramebuffer(framer, depthr, texr);
+
+
+
// reset
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame)
end
else
cStereoMode:= smNone;
end;
+
+ // set up vertex/texture buffers for frame textures
+ texLRDtb[0].X:= 0.0;
+ texLRDtb[0].Y:= 0.0;
+ texLRDtb[1].X:= 1.0;
+ texLRDtb[1].Y:= 0.0;
+ texLRDtb[2].X:= 1.0;
+ texLRDtb[2].Y:= 1.0;
+ texLRDtb[3].X:= 0.0;
+ texLRDtb[3].Y:= 1.0;
+
+ if cStereoMode = smHorizontal then
+ begin
+ texLvb[0].X:= cScreenWidth / -2;
+ texLvb[0].Y:= cScreenHeight;
+ texLvb[1].X:= 0;
+ texLvb[1].Y:= cScreenHeight;
+ texLvb[2].X:= 0;
+ texLvb[2].Y:= 0;
+ texLvb[3].X:= cScreenWidth / -2;
+ texLvb[3].Y:= 0;
+
+ texRvb[0].X:= 0;
+ texRvb[0].Y:= cScreenHeight;
+ texRvb[1].X:= cScreenWidth / 2;
+ texRvb[1].Y:= cScreenHeight;
+ texRvb[2].X:= cScreenWidth / 2;
+ texRvb[2].Y:= 0;
+ texRvb[3].X:= 0;
+ texRvb[3].Y:= 0;
+ end
+ else
+ begin
+ texLvb[0].X:= cScreenWidth / -2;
+ texLvb[0].Y:= cScreenHeight / 2;
+ texLvb[1].X:= cScreenWidth / 2;
+ texLvb[1].Y:= cScreenHeight / 2;
+ texLvb[2].X:= cScreenWidth / 2;
+ texLvb[2].Y:= 0;
+ texLvb[3].X:= cScreenWidth / -2;
+ texLvb[3].Y:= 0;
+
+ texRvb[0].X:= cScreenWidth / -2;
+ texRvb[0].Y:= cScreenHeight;
+ texRvb[1].X:= cScreenWidth / 2;
+ texRvb[1].Y:= cScreenHeight;
+ texRvb[2].X:= cScreenWidth / 2;
+ texRvb[2].Y:= cScreenHeight / 2;
+ texRvb[3].X:= cScreenWidth / -2;
+ texRvb[3].Y:= cScreenHeight / 2;
+ end;
{$ENDIF}
// set view port to whole window
@@ -1220,6 +1398,25 @@
glDisable(GL_LINE_SMOOTH);
end;
+procedure DrawCircleFilled(X, Y, Radius: LongInt; r, g, b, a: Byte);
+var
+ i: LongInt;
+begin
+ VertexBuffer[0].X := X;
+ VertexBuffer[0].Y := Y;
+
+ for i := 1 to 19 do begin
+ VertexBuffer[i].X := X + Radius*cos(i*pi/9);
+ VertexBuffer[i].Y := Y + Radius*sin(i*pi/9);
+ end;
+
+ EnableTexture(False);
+ Tint(r, g, b, a);
+ SetVertexPointer(@VertexBuffer[0], 20);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 20);
+ Untint();
+ EnableTexture(True);
+end;
procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
const VertexBuffer: array [0..3] of TVertex2f = (
@@ -1387,11 +1584,6 @@
firsti:= -1;
afteri:= 0;
-if GameTicks < 2000 then
- lol:= 2000 - GameTicks
-else
- lol:= 0;
-
if InTopY < 0 then
InTopY:= 0;
@@ -1403,6 +1595,13 @@
end
else
begin
+
+ // animate water walls raise animation at start of game
+ if GameTicks < 2000 then
+ lol:= 2000 - GameTicks
+ else
+ lol:= 0;
+
if InLeftX > ViewLeftX then
begin
VertexBuffer[0].X:= OutLeftX - lol;
@@ -1712,6 +1911,42 @@
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
end;
+procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
+var tmp: LongInt;
+begin
+{$IFNDEF USE_S3D_RENDERING}
+ rm:= rm; d:= d; tmp:= tmp; // avoid hint
+{$ELSE}
+ d:= d / 5;
+ if rm = rmDefault then
+ exit
+ else if rm = rmLeftEye then
+ d:= -d;
+ cStereoDepth:= cStereoDepth + d;
+ openglTranslProjMatrix(d, 0, 0);
+ tmp:= round(d / cScaleFactor * cScreenWidth);
+ ViewLeftX := ViewLeftX - tmp;
+ ViewRightX:= ViewRightX - tmp;
+{$ENDIF}
+end;
+
+procedure ResetDepth(rm: TRenderMode);
+var tmp: LongInt;
+begin
+{$IFNDEF USE_S3D_RENDERING}
+ rm:= rm; tmp:= tmp; // avoid hint
+{$ELSE}
+ if rm = rmDefault then
+ exit;
+ openglTranslProjMatrix(-cStereoDepth, 0, 0);
+ tmp:= round(cStereoDepth / cScaleFactor * cScreenWidth);
+ ViewLeftX := ViewLeftX + tmp;
+ ViewRightX:= ViewRightX + tmp;
+ cStereoDepth:= 0;
+{$ENDIF}
+end;
+
+
procedure initModule;
begin
LastTint:= cWhiteColor + 1;