diff -r 1ff3dd3705b1 -r 99273b7afbff hedgewars/uRender.pas --- 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;