hedgewars/uRender.pas
changeset 10304 7e40820b7ed6
parent 10302 ea0b0e2efd95
child 10306 4fca8bcfaff0
equal deleted inserted replaced
10303:f726e36c3e24 10304:7e40820b7ed6
    21 
    21 
    22 unit uRender;
    22 unit uRender;
    23 
    23 
    24 interface
    24 interface
    25 
    25 
    26 uses SDLh, uTypes, GLunit, uConsts{$IFDEF GL2}, uMatrix{$ENDIF};
    26 uses SDLh, uTypes, GLunit;
       
    27 
       
    28 procedure initModule;
       
    29 procedure freeModule;
    27 
    30 
    28 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
    31 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
    29 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
    32 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
    30 procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
    33 procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
    31 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
    34 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
    46 procedure DrawCircle            (X, Y, Radius, Width: LongInt);
    49 procedure DrawCircle            (X, Y, Radius, Width: LongInt);
    47 procedure DrawCircle            (X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
    50 procedure DrawCircle            (X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
    48 
    51 
    49 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
    52 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
    50 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
    53 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
    51 procedure DrawFillRect          (r: TSDL_Rect);
    54 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
    52 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    55 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    53 procedure DrawScreenWidget      (widget: POnScreenWidget);
    56 procedure DrawScreenWidget      (widget: POnScreenWidget);
    54 procedure DrawWaterBody         (pVertexBuffer: Pointer);
    57 procedure DrawWaterBody         (pVertexBuffer: Pointer);
    55 
    58 
       
    59 procedure RenderClear           ();
       
    60 procedure RenderSetClearColor      (r, g, b, a: real);
    56 procedure Tint                  (r, g, b, a: Byte); inline;
    61 procedure Tint                  (r, g, b, a: Byte); inline;
    57 procedure Tint                  (c: Longword); inline;
    62 procedure Tint                  (c: Longword); inline;
    58 procedure untint(); inline;
    63 procedure untint(); inline;
    59 procedure setTintAdd            (f: boolean); inline;
    64 procedure setTintAdd            (f: boolean); inline;
    60 
    65 
    64 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
    69 function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline;
    65 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
    70 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
    66 
    71 
    67 procedure SetScale(f: GLfloat);
    72 procedure SetScale(f: GLfloat);
    68 procedure UpdateViewLimits();
    73 procedure UpdateViewLimits();
       
    74 
       
    75 procedure RenderSetup();
       
    76 
       
    77 // TODO everything below this should not need a public interface
    69 
    78 
    70 procedure EnableTexture(enable:Boolean);
    79 procedure EnableTexture(enable:Boolean);
    71 
    80 
    72 procedure SetTexCoordPointer(p: Pointer;n: Integer);
    81 procedure SetTexCoordPointer(p: Pointer;n: Integer);
    73 procedure SetVertexPointer(p: Pointer;n: Integer);
    82 procedure SetVertexPointer(p: Pointer;n: Integer);
    84 procedure openglRotatef         (RotX, RotY, RotZ: GLfloat; dir: LongInt); inline;
    93 procedure openglRotatef         (RotX, RotY, RotZ: GLfloat; dir: LongInt); inline;
    85 procedure openglTint            (r, g, b, a: Byte); inline;
    94 procedure openglTint            (r, g, b, a: Byte); inline;
    86 
    95 
    87 
    96 
    88 implementation
    97 implementation
    89 uses uVariables;
    98 uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}SysUtils, uVariables, uUtils, uConsts
       
    99      {$IFDEF GL2}, uMatrix, uConsole{$ENDIF};
    90 
   100 
    91 {$IFDEF USE_TOUCH_INTERFACE}
   101 {$IFDEF USE_TOUCH_INTERFACE}
    92 const
   102 const
    93     FADE_ANIM_TIME = 500;
   103     FADE_ANIM_TIME = 500;
    94     MOVE_ANIM_TIME = 500;
   104     MOVE_ANIM_TIME = 500;
    95 {$ENDIF}
   105 {$ENDIF}
    96 
   106 
       
   107 {$IFDEF GL2}
       
   108 var
       
   109     shaderMain: GLuint;
       
   110     shaderWater: GLuint;
       
   111 {$ENDIF}
       
   112 
    97 var LastTint: LongWord = 0;
   113 var LastTint: LongWord = 0;
    98 
   114 
    99 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
   115 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
   100 begin
   116 begin
   101     isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
   117     isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0);
   111 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
   127 function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline;
   112 begin
   128 begin
   113     if Y > ViewBottomY then exit(1);
   129     if Y > ViewBottomY then exit(1);
   114     if Y + Height < ViewTopY then exit(-1);
   130     if Y + Height < ViewTopY then exit(-1);
   115     isDyAreaOffscreen:= 0;
   131     isDyAreaOffscreen:= 0;
       
   132 end;
       
   133 
       
   134 procedure RenderClear();
       
   135 begin
       
   136     glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
       
   137 end;
       
   138 
       
   139 procedure RenderSetClearColor(r, g, b, a: real);
       
   140 begin
       
   141     glClearColor(r, g, b, a);
       
   142 end;
       
   143 
       
   144 {$IFDEF GL2}
       
   145 function CompileShader(shaderFile: string; shaderType: GLenum): GLuint;
       
   146 var
       
   147     shader: GLuint;
       
   148     f: Textfile;
       
   149     source, line: AnsiString;
       
   150     sourceA: Pchar;
       
   151     lengthA: GLint;
       
   152     compileResult: GLint;
       
   153     logLength: GLint;
       
   154     log: PChar;
       
   155 begin
       
   156     Assign(f, PathPrefix + cPathz[ptShaders] + '/' + shaderFile);
       
   157     filemode:= 0; // readonly
       
   158     Reset(f);
       
   159     if IOResult <> 0 then
       
   160     begin
       
   161         AddFileLog('Unable to load ' + shaderFile);
       
   162         halt(-1);
       
   163     end;
       
   164 
       
   165     source:='';
       
   166     while not eof(f) do
       
   167     begin
       
   168         ReadLn(f, line);
       
   169         source:= source + line + #10;
       
   170     end;
       
   171 
       
   172     Close(f);
       
   173 
       
   174     WriteLnToConsole('Compiling shader: ' + PathPrefix + cPathz[ptShaders] + '/' + shaderFile);
       
   175 
       
   176     sourceA:=PChar(source);
       
   177     lengthA:=Length(source);
       
   178 
       
   179     shader:=glCreateShader(shaderType);
       
   180     glShaderSource(shader, 1, @sourceA, @lengthA);
       
   181     glCompileShader(shader);
       
   182     glGetShaderiv(shader, GL_COMPILE_STATUS, @compileResult);
       
   183     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, @logLength);
       
   184 
       
   185     if logLength > 1 then
       
   186     begin
       
   187         log := GetMem(logLength);
       
   188         glGetShaderInfoLog(shader, logLength, nil, log);
       
   189         WriteLnToConsole('========== Compiler log  ==========');
       
   190         WriteLnToConsole(shortstring(log));
       
   191         WriteLnToConsole('===================================');
       
   192         FreeMem(log, logLength);
       
   193     end;
       
   194 
       
   195     if compileResult <> GL_TRUE then
       
   196     begin
       
   197         WriteLnToConsole('Shader compilation failed, halting');
       
   198         halt(-1);
       
   199     end;
       
   200 
       
   201     CompileShader:= shader;
       
   202 end;
       
   203 
       
   204 function CompileProgram(shaderName: string): GLuint;
       
   205 var
       
   206     program_: GLuint;
       
   207     vs, fs: GLuint;
       
   208     linkResult: GLint;
       
   209     logLength: GLint;
       
   210     log: PChar;
       
   211 begin
       
   212     program_:= glCreateProgram();
       
   213     vs:= CompileShader(shaderName + '.vs', GL_VERTEX_SHADER);
       
   214     fs:= CompileShader(shaderName + '.fs', GL_FRAGMENT_SHADER);
       
   215     glAttachShader(program_, vs);
       
   216     glAttachShader(program_, fs);
       
   217 
       
   218     glBindAttribLocation(program_, aVertex, PChar('vertex'));
       
   219     glBindAttribLocation(program_, aTexCoord, PChar('texcoord'));
       
   220     glBindAttribLocation(program_, aColor, PChar('color'));
       
   221 
       
   222     glLinkProgram(program_);
       
   223     glDeleteShader(vs);
       
   224     glDeleteShader(fs);
       
   225 
       
   226     glGetProgramiv(program_, GL_LINK_STATUS, @linkResult);
       
   227     glGetProgramiv(program_, GL_INFO_LOG_LENGTH, @logLength);
       
   228 
       
   229     if logLength > 1 then
       
   230     begin
       
   231         log := GetMem(logLength);
       
   232         glGetProgramInfoLog(program_, logLength, nil, log);
       
   233         WriteLnToConsole('========== Compiler log  ==========');
       
   234         WriteLnToConsole(shortstring(log));
       
   235         WriteLnToConsole('===================================');
       
   236         FreeMem(log, logLength);
       
   237     end;
       
   238 
       
   239     if linkResult <> GL_TRUE then
       
   240     begin
       
   241         WriteLnToConsole('Linking program failed, halting');
       
   242         halt(-1);
       
   243     end;
       
   244 
       
   245     CompileProgram:= program_;
       
   246 end;
       
   247 {$ENDIF}
       
   248 
       
   249 procedure RenderSetup();
       
   250 var AuxBufNum: LongInt = 0;
       
   251     tmpstr: ansistring;
       
   252     tmpint: LongInt;
       
   253     tmpn: LongInt;
       
   254 begin
       
   255     // suppress hint/warning
       
   256     AuxBufNum:= AuxBufNum;
       
   257 
       
   258     // get the max (h and v) size for textures that the gpu can support
       
   259     glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize);
       
   260     if MaxTextureSize <= 0 then
       
   261         begin
       
   262         MaxTextureSize:= 1024;
       
   263         AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024');
       
   264         end
       
   265     else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then
       
   266         begin
       
   267         cReducedQuality := cReducedQuality or rqNoBackground;
       
   268         AddFileLog('Texture size too small for backgrounds, disabling.');
       
   269         end;
       
   270     // everyone loves debugging
       
   271     // find out which gpu we are using (for extension compatibility maybe?)
       
   272     AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER))));
       
   273     AddFileLog('  |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR))));
       
   274     AddFileLog('  |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION))));
       
   275     AddFileLog('  |----- Texture Size: ' + inttostr(MaxTextureSize));
       
   276 {$IFDEF USE_VIDEO_RECORDING}
       
   277     glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum);
       
   278     AddFileLog('  |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum));
       
   279 {$ENDIF}
       
   280 {$IFNDEF PAS2C}
       
   281     AddFileLog('  \----- Extensions: ');
       
   282 
       
   283     // fetch extentions and store them in string
       
   284     tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS)));
       
   285     tmpn := WordCount(tmpstr, [' ']);
       
   286     tmpint := 1;
       
   287 
       
   288     repeat
       
   289     begin
       
   290         // print up to 3 extentions per row
       
   291         // ExtractWord will return empty string if index out of range
       
   292         AddFileLog(TrimRight(
       
   293             ExtractWord(tmpint, tmpstr, [' ']) + ' ' +
       
   294             ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' +
       
   295             ExtractWord(tmpint+2, tmpstr, [' '])
       
   296         ));
       
   297         tmpint := tmpint + 3;
       
   298     end;
       
   299     until (tmpint > tmpn);
       
   300 {$ENDIF}
       
   301     AddFileLog('');
       
   302 
       
   303     defaultFrame:= 0;
       
   304 
       
   305 {$IFDEF USE_VIDEO_RECORDING}
       
   306     if GameType = gmtRecord then
       
   307     begin
       
   308         if glLoadExtension('GL_EXT_framebuffer_object') then
       
   309         begin
       
   310             CreateFramebuffer(defaultFrame, depthv, texv);
       
   311             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame);
       
   312             AddFileLog('Using framebuffer for video recording.');
       
   313         end
       
   314         else if AuxBufNum > 0 then
       
   315         begin
       
   316             glDrawBuffer(GL_AUX0);
       
   317             glReadBuffer(GL_AUX0);
       
   318             AddFileLog('Using auxiliary buffer for video recording.');
       
   319         end
       
   320         else
       
   321         begin
       
   322             glDrawBuffer(GL_BACK);
       
   323             glReadBuffer(GL_BACK);
       
   324             AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.');
       
   325         end;
       
   326     end;
       
   327 {$ENDIF}
       
   328 
       
   329 {$IFDEF GL2}
       
   330 
       
   331 {$IFDEF PAS2C}
       
   332     err := glewInit();
       
   333     if err <> GLEW_OK then
       
   334     begin
       
   335         WriteLnToConsole('Failed to initialize GLEW.');
       
   336         halt;
       
   337     end;
       
   338 {$ENDIF}
       
   339 
       
   340 {$IFNDEF PAS2C}
       
   341     if not Load_GL_VERSION_2_0 then
       
   342         halt;
       
   343 {$ENDIF}
       
   344 
       
   345     shaderWater:= CompileProgram('water');
       
   346     glUseProgram(shaderWater);
       
   347     glUniform1i(glGetUniformLocation(shaderWater, pchar('tex0')), 0);
       
   348     uWaterMVPLocation:= glGetUniformLocation(shaderWater, pchar('mvp'));
       
   349 
       
   350     shaderMain:= CompileProgram('default');
       
   351     glUseProgram(shaderMain);
       
   352     glUniform1i(glGetUniformLocation(shaderMain, pchar('tex0')), 0);
       
   353     uMainMVPLocation:= glGetUniformLocation(shaderMain, pchar('mvp'));
       
   354     uMainTintLocation:= glGetUniformLocation(shaderMain, pchar('tint'));
       
   355 
       
   356     uCurrentMVPLocation:= uMainMVPLocation;
       
   357 
       
   358     Tint(255, 255, 255, 255);
       
   359     UpdateModelviewProjection;
       
   360 {$ENDIF}
       
   361 
       
   362 {$IFNDEF USE_S3D_RENDERING}
       
   363     if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
       
   364     begin
       
   365         // prepare left and right frame buffers and associated textures
       
   366         if glLoadExtension('GL_EXT_framebuffer_object') then
       
   367             begin
       
   368             CreateFramebuffer(framel, depthl, texl);
       
   369             CreateFramebuffer(framer, depthr, texr);
       
   370 
       
   371             // reset
       
   372             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame)
       
   373             end
       
   374         else
       
   375             cStereoMode:= smNone;
       
   376     end;
       
   377 {$ENDIF}
       
   378 
       
   379 // set view port to whole window
       
   380 glViewport(0, 0, cScreenWidth, cScreenHeight);
       
   381 
       
   382 {$IFDEF GL2}
       
   383     uMatrix.initModule;
       
   384     hglMatrixMode(MATRIX_MODELVIEW);
       
   385     // prepare default translation/scaling
       
   386     hglLoadIdentity();
       
   387     hglScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
       
   388     hglTranslatef(0, -cScreenHeight / 2, 0);
       
   389 
       
   390     EnableTexture(True);
       
   391 
       
   392     glEnableVertexAttribArray(aVertex);
       
   393     glEnableVertexAttribArray(aTexCoord);
       
   394     glGenBuffers(1, @vBuffer);
       
   395     glGenBuffers(1, @tBuffer);
       
   396     glGenBuffers(1, @cBuffer);
       
   397 {$ELSE}
       
   398     glMatrixMode(GL_MODELVIEW);
       
   399     // prepare default translation/scaling
       
   400     glLoadIdentity();
       
   401     glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
       
   402     glTranslatef(0, -cScreenHeight / 2, 0);
       
   403 
       
   404     // disable/lower perspective correction (will not need it anyway)
       
   405     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
       
   406     // disable dithering
       
   407     glDisable(GL_DITHER);
       
   408     // enable common states by default as they save a lot
       
   409     glEnable(GL_TEXTURE_2D);
       
   410     glEnableClientState(GL_VERTEX_ARRAY);
       
   411     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
   412 {$ENDIF}
       
   413 
       
   414     // enable alpha blending
       
   415     glEnable(GL_BLEND);
       
   416     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       
   417     // disable/lower perspective correction (will not need it anyway)
   116 end;
   418 end;
   117 
   419 
   118 procedure openglLoadIdentity(); inline;
   420 procedure openglLoadIdentity(); inline;
   119 begin
   421 begin
   120 {$IFDEF GL2}
   422 {$IFDEF GL2}
   283     ViewRightX:= round(tmp); // ceil could make more sense
   585     ViewRightX:= round(tmp); // ceil could make more sense
   284     ViewLeftX:= round(-tmp); // floor could make more sense
   586     ViewLeftX:= round(-tmp); // floor could make more sense
   285     tmp:= cScreenHeight / cScaleFactor;
   587     tmp:= cScreenHeight / cScaleFactor;
   286     ViewBottomY:= round(tmp) + cScreenHeight div 2; // ceil could make more sense
   588     ViewBottomY:= round(tmp) + cScreenHeight div 2; // ceil could make more sense
   287     ViewTopY:= round(-tmp) + cScreenHeight div 2; // floor could make more sense
   589     ViewTopY:= round(-tmp) + cScreenHeight div 2; // floor could make more sense
       
   590 
       
   591     // visual debugging fun :D
       
   592     if cViewLimitsDebug then
       
   593         begin
       
   594         // some margin on each side
       
   595         tmp:= min(cScreenWidth, cScreenHeight) div 2 / cScaleFactor;
       
   596         ViewLeftX  := ViewLeftX   + trunc(tmp);
       
   597         ViewRightX := ViewRightX  - trunc(tmp);
       
   598         ViewBottomY:= ViewBottomY - trunc(tmp);
       
   599         ViewTopY   := ViewTopY    + trunc(tmp);
       
   600         end;
       
   601 
       
   602     ViewWidth := ViewRightX  - ViewLeftX + 1;
       
   603     ViewHeight:= ViewBottomY - ViewTopY  + 1;
   288 end;
   604 end;
   289 
   605 
   290 procedure SetScale(f: GLfloat);
   606 procedure SetScale(f: GLfloat);
   291 begin
   607 begin
   292 // leave immediately if scale factor did not change
   608     // leave immediately if scale factor did not change
   293     if f = cScaleFactor then
   609     if f = cScaleFactor then
   294         exit;
   610         exit;
   295 
   611 
   296     // for going back to default scaling just pop matrix
   612     // for going back to default scaling just pop matrix
   297     if f = cDefaultZoomLevel then
   613     if f = cDefaultZoomLevel then
   301     else
   617     else
   302         begin
   618         begin
   303         openglPushMatrix; // save default scaling in matrix
   619         openglPushMatrix; // save default scaling in matrix
   304         openglLoadIdentity();
   620         openglLoadIdentity();
   305         openglScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
   621         openglScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
   306         openglTranslatef(0, -cScreenHeight / 2, 0);
   622         openglTranslatef(0, -cScreenHeight div 2, 0);
   307         end;
   623         end;
   308 
   624 
   309     cScaleFactor:= f;
   625     cScaleFactor:= f;
   310     updateViewLimits();
   626     updateViewLimits();
   311 
   627 
   335     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
   651     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
   336 begin
   652 begin
   337 if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
   653 if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
   338     exit;
   654     exit;
   339 
   655 
       
   656 {if isDxAreaOffscreen(X, W) <> 0 then
       
   657     exit;
       
   658 if isDyAreaOffscreen(Y, H) <> 0 then
       
   659     exit;}
       
   660 
   340 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   661 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   341 if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
   662 {if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
   342     exit;
   663     exit;
   343 if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
   664 if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
   344     exit;
   665     exit;}
   345 
   666 
   346 rr.x:= X;
   667 rr.x:= X;
   347 rr.y:= Y;
   668 rr.y:= Y;
   348 rr.w:= W;
   669 rr.w:= W;
   349 rr.h:= H;
   670 rr.h:= H;
   355 
   676 
   356 glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
   677 glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
   357 
   678 
   358 if Dir < 0 then
   679 if Dir < 0 then
   359     begin
   680     begin
   360     VertexBuffer[0].X:= X + rr.w/2;
   681     VertexBuffer[0].X:= X + rr.w div 2;
   361     VertexBuffer[0].Y:= Y;
   682     VertexBuffer[0].Y:= Y;
   362     VertexBuffer[1].X:= X - rr.w/2;
   683     VertexBuffer[1].X:= X - rr.w div 2;
   363     VertexBuffer[1].Y:= Y;
   684     VertexBuffer[1].Y:= Y;
   364     VertexBuffer[2].X:= X - rr.w/2;
   685     VertexBuffer[2].X:= X - rr.w div 2;
   365     VertexBuffer[2].Y:= rr.h + Y;
   686     VertexBuffer[2].Y:= rr.h + Y;
   366     VertexBuffer[3].X:= X + rr.w/2;
   687     VertexBuffer[3].X:= X + rr.w div 2;
   367     VertexBuffer[3].Y:= rr.h + Y;
   688     VertexBuffer[3].Y:= rr.h + Y;
   368     end
   689     end
   369 else
   690 else
   370     begin
   691     begin
   371     VertexBuffer[0].X:= X;
   692     VertexBuffer[0].X:= X;
   400 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
   721 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
   401 begin
   722 begin
   402 
   723 
   403 openglPushMatrix;
   724 openglPushMatrix;
   404 openglTranslatef(X, Y, 0);
   725 openglTranslatef(X, Y, 0);
   405 openglScalef(Scale, Scale, 1);
   726 
       
   727 if Scale <> 1.0 then
       
   728     openglScalef(Scale, Scale, 1);
   406 
   729 
   407 glBindTexture(GL_TEXTURE_2D, Texture^.id);
   730 glBindTexture(GL_TEXTURE_2D, Texture^.id);
   408 
   731 
   409 SetVertexPointer(@Texture^.vb, Length(Texture^.vb));
   732 SetVertexPointer(@Texture^.vb, Length(Texture^.vb));
   410 SetTexCoordPointer(@Texture^.tb, Length(Texture^.vb));
   733 SetTexCoordPointer(@Texture^.tb, Length(Texture^.vb));
   411 
   734 
   412 {$IFDEF GL2}
       
   413 UpdateModelviewProjection;
   735 UpdateModelviewProjection;
   414 {$ENDIF}
       
   415 
   736 
   416 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
   737 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
   417 openglPopMatrix;
   738 openglPopMatrix;
   418 
   739 
   419 end;
   740 end;
   455 procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
   776 procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
   456 var ft, fb, fl, fr: GLfloat;
   777 var ft, fb, fl, fr: GLfloat;
   457     hw, hh, nx, ny: LongInt;
   778     hw, hh, nx, ny: LongInt;
   458     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
   779     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
   459 begin
   780 begin
       
   781 
       
   782 if isDxAreaOffscreen(X, w) <> 0 then
       
   783     exit;
       
   784 if isDyAreaOffscreen(Y, h) <> 0 then
       
   785     exit;
       
   786 
   460 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   787 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   461 if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then
   788 {if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then
   462     exit;
   789     exit;
   463 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
   790 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
   464     exit;
   791     exit;}
   465 
   792 
   466 openglPushMatrix;
   793 openglPushMatrix;
   467 
   794 
   468 openglTranslatef(X, Y, 0);
   795 openglTranslatef(X, Y, 0);
   469 
   796 
   556 end;
   883 end;
   557 
   884 
   558 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
   885 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
   559 var VertexBuffer: array [0..3] of TVertex2f;
   886 var VertexBuffer: array [0..3] of TVertex2f;
   560 begin
   887 begin
       
   888 
       
   889 if isDxAreaOffscreen(X, 2 * hw) <> 0 then
       
   890     exit;
       
   891 if isDyAreaOffscreen(Y, 2 * hh) <> 0 then
       
   892     exit;
       
   893 
   561 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   894 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   562 if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then
   895 {if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then
   563     exit;
   896     exit;
   564 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
   897 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
   565     exit;
   898     exit;}
   566 
   899 
   567 openglPushMatrix;
   900 openglPushMatrix;
   568 openglTranslatef(X, Y, 0);
   901 openglTranslatef(X, Y, 0);
   569 
   902 
   570 if Dir < 0 then
   903 if Dir < 0 then
   645 DrawTextureFromRect(X + r.x, Y + r.y, @r, SpritesData[Sprite].Texture)
   978 DrawTextureFromRect(X + r.x, Y + r.y, @r, SpritesData[Sprite].Texture)
   646 end;
   979 end;
   647 
   980 
   648 procedure DrawTextureCentered(X, Top: LongInt; Source: PTexture);
   981 procedure DrawTextureCentered(X, Top: LongInt; Source: PTexture);
   649 var scale: GLfloat;
   982 var scale: GLfloat;
   650 begin
   983     left : LongInt;
       
   984 begin
       
   985     // scale down if larger than screen
   651     if (Source^.w + 20) > cScreenWidth then
   986     if (Source^.w + 20) > cScreenWidth then
   652         scale:= cScreenWidth / (Source^.w + 20)
   987         begin
       
   988         scale:= cScreenWidth / (Source^.w + 20);
       
   989         DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale);
       
   990         end
   653     else
   991     else
   654         scale:= 1.0;
   992         begin
   655     DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale)
   993         left:= X - Source^.w div 2;
       
   994         if (not isAreaOffscreen(left, Top, Source^.w, Source^.h)) then
       
   995             DrawTexture(left, Top, Source);
       
   996         end;
   656 end;
   997 end;
   657 
   998 
   658 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
   999 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
   659 begin
  1000 begin
   660 DrawLine(X0, Y0, X1, Y1, Width, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF)
  1001 DrawLine(X0, Y0, X1, Y1, Width, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF)
   688     EnableTexture(True);
  1029     EnableTexture(True);
   689 
  1030 
   690     glDisable(GL_LINE_SMOOTH);
  1031     glDisable(GL_LINE_SMOOTH);
   691 end;
  1032 end;
   692 
  1033 
   693 procedure DrawFillRect(r: TSDL_Rect);
  1034 procedure DrawRect(rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
   694 var VertexBuffer: array [0..3] of TVertex2f;
  1035 var VertexBuffer: array [0..3] of TVertex2f;
   695 begin
  1036 begin
   696 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
  1037 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
   697 
  1038 {if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
   698 if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
       
   699     exit;
  1039     exit;
   700 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then
  1040 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then
   701     exit;
  1041     exit;}
   702 
  1042 
   703 EnableTexture(False);
  1043 EnableTexture(False);
   704 
  1044 
   705 Tint($00, $00, $00, $80);
  1045 Tint(r, g, b, a);
   706 
  1046 
   707 VertexBuffer[0].X:= r.x;
  1047 with rect do
   708 VertexBuffer[0].Y:= r.y;
  1048 begin
   709 VertexBuffer[1].X:= r.x + r.w;
  1049     VertexBuffer[0].X:= x;
   710 VertexBuffer[1].Y:= r.y;
  1050     VertexBuffer[0].Y:= y;
   711 VertexBuffer[2].X:= r.x + r.w;
  1051     VertexBuffer[1].X:= x + w;
   712 VertexBuffer[2].Y:= r.y + r.h;
  1052     VertexBuffer[1].Y:= y;
   713 VertexBuffer[3].X:= r.x;
  1053     VertexBuffer[2].X:= x + w;
   714 VertexBuffer[3].Y:= r.y + r.h;
  1054     VertexBuffer[2].Y:= y + h;
       
  1055     VertexBuffer[3].X:= x;
       
  1056     VertexBuffer[3].Y:= y + h;
       
  1057 end;
   715 
  1058 
   716 SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
  1059 SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
   717 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
  1060 if Fill then
       
  1061     glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer))
       
  1062 else
       
  1063     glDrawArrays(GL_LINE_LOOP, 0, Length(VertexBuffer));
   718 
  1064 
   719 untint;
  1065 untint;
   720 
  1066 
   721 EnableTexture(True);
  1067 EnableTexture(True);
   722 
  1068 
   951         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD)
  1297         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD)
   952     else
  1298     else
   953         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1299         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   954 end;
  1300 end;
   955 
  1301 
       
  1302 procedure initModule;
       
  1303 begin
       
  1304 end;
       
  1305 
       
  1306 procedure freeModule;
       
  1307 begin
       
  1308 {$IFDEF GL2}
       
  1309     glDeleteProgram(shaderMain);
       
  1310     glDeleteProgram(shaderWater);
       
  1311     glDeleteBuffers(1, @vBuffer);
       
  1312     glDeleteBuffers(1, @tBuffer);
       
  1313     glDeleteBuffers(1, @cBuffer);
       
  1314 {$ENDIF}
       
  1315 end;
   956 end.
  1316 end.