hedgewars/uRender.pas
branchwebgl
changeset 8026 4a4f21070479
parent 7069 bcf9d8e64e92
child 8330 aaefa587e277
--- a/hedgewars/uRender.pas	Sun Nov 11 16:53:16 2012 +0100
+++ b/hedgewars/uRender.pas	Sun Nov 11 17:15:19 2012 +0100
@@ -17,12 +17,13 @@
  *)
 
 {$INCLUDE "options.inc"}
+{$IF GLunit = GL}{$DEFINE GLunit:=GL,GLext}{$ENDIF}
 
 unit uRender;
 
 interface
 
-uses SDLh, uTypes, GLunit, uConsts;
+uses SDLh, uTypes, GLunit, uConsts, uStore, uMatrix;
 
 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
@@ -51,7 +52,6 @@
 procedure Tint                  (r, g, b, a: Byte); inline;
 procedure Tint                  (c: Longword); inline;
 
-
 implementation
 uses uVariables;
 
@@ -68,7 +68,7 @@
 begin
 DrawTextureFromRect(X, Y, r^.w, r^.h, r, SourceTexture)
 end;
-
+{
 procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
 var rr: TSDL_Rect;
     _l, _r, _t, _b: real;
@@ -115,6 +115,63 @@
 
 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+glDrawArrays(GL_TRIANGLE_FAN, 0, High(VertexBuffer) - Low(VertexBuffer) + 1);
+end;
+}
+
+procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+var 
+    rr: TSDL_Rect;
+    VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
+    //VertexBuffer, TextureBuffer: TVertexRect;
+    _l, _r, _t, _b: GLfloat;
+begin
+if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
+    exit;
+
+// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
+if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
+    exit;
+if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
+    exit;
+
+rr.x:= X;
+rr.y:= Y;
+rr.w:= W;
+rr.h:= H;
+
+_l:= r^.x / SourceTexture^.w * SourceTexture^.rx;
+_r:= (r^.x + r^.w) / SourceTexture^.w * SourceTexture^.rx;
+_t:= r^.y / SourceTexture^.h * SourceTexture^.ry;
+_b:= (r^.y + r^.h) / SourceTexture^.h * SourceTexture^.ry;
+
+glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
+
+VertexBuffer[0].X:= X;
+VertexBuffer[0].Y:= Y;
+VertexBuffer[1].X:= rr.w + X;
+VertexBuffer[1].Y:= Y;
+VertexBuffer[2].X:= rr.w + X;
+VertexBuffer[2].Y:= rr.h + Y;
+VertexBuffer[3].X:= X;
+VertexBuffer[3].Y:= rr.h + Y;
+
+TextureBuffer[0].X:= _l;
+TextureBuffer[0].Y:= _t;
+TextureBuffer[1].X:= _r;
+TextureBuffer[1].Y:= _t;
+TextureBuffer[2].X:= _r;
+TextureBuffer[2].Y:= _b;
+TextureBuffer[3].X:= _l;
+TextureBuffer[3].Y:= _b;
+
+SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
+SetTexCoordPointer(@TextureBuffer[0], Length(VertexBuffer));
+
+{$IFDEF GL2}
+UpdateModelviewProjection;
+{$ENDIF}
+
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 end;
 
@@ -126,17 +183,30 @@
 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
 begin
 
+{$IFDEF GL2}
+hglPushMatrix;
+hglTranslatef(X, Y, 0);
+hglScalef(Scale, Scale, 1);
+{$ELSE}
 glPushMatrix;
 glTranslatef(X, Y, 0);
 glScalef(Scale, Scale, 1);
+{$ENDIF}
 
 glBindTexture(GL_TEXTURE_2D, Texture^.id);
 
-glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb);
-glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
+SetVertexPointer(@Texture^.vb, Length(Texture^.vb));
+SetTexCoordPointer(@Texture^.tb, Length(Texture^.vb));
+
+{$IFDEF GL2}
+UpdateModelviewProjection;
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
+hglPopMatrix;
+{$ELSE}
+glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
+glPopMatrix;
+{$ENDIF}
 
-glPopMatrix
 end;
 
 procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
@@ -155,14 +225,25 @@
 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
     exit;
 
+{$IFDEF GL2}
+hglPushMatrix;
+hglTranslatef(X, Y, 0);
+{$ELSE}
 glPushMatrix;
 glTranslatef(X, Y, 0);
+{$ENDIF}
+
 if Dir = 0 then Dir:= 1;
 
+{$IFDEF GL2}
+hglRotatef(Angle, 0, 0, Dir);
+hglTranslatef(Dir*OffsetX, OffsetY, 0);
+hglScalef(Scale, Scale, 1);
+{$ELSE}
 glRotatef(Angle, 0, 0, Dir);
-
 glTranslatef(Dir*OffsetX, OffsetY, 0);
 glScalef(Scale, Scale, 1);
+{$ENDIF}
 
 // Any reason for this call? And why only in t direction, not s?
 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -197,11 +278,21 @@
 TextureBuffer[3].X:= fl;
 TextureBuffer[3].Y:= fb;
 
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
+SetTexCoordPointer(@TextureBuffer[0], Length(VertexBuffer));
+
+{$IFDEF GL2}
+UpdateModelviewProjection;
+{$ENDIF}
+
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
-glPopMatrix
+{$IFDEF GL2}
+hglPopMatrix;
+{$ELSE}
+glPopMatrix;
+{$ENDIF}
+
 end;
 
 procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -214,19 +305,42 @@
 
 procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
 begin
+
+{$IFDEF GL2}
+hglPushMatrix;
+hglTranslatef(X, Y, 0);
+{$ELSE}
 glPushMatrix;
 glTranslatef(X, Y, 0);
+{$ENDIF}
 
 if Dir < 0 then
+{$IFDEF GL2}
+    hglRotatef(Angle, 0, 0, -1)
+{$ELSE}
     glRotatef(Angle, 0, 0, -1)
+{$ENDIF}
 else
+{$IFDEF GL2}
+    hglRotatef(Angle, 0, 0,  1);
+{$ELSE}
     glRotatef(Angle, 0, 0,  1);
+{$ENDIF}
 if Dir < 0 then
+{$IFDEF GL2}
+    hglScalef(-1.0, 1.0, 1.0);
+{$ELSE}
     glScalef(-1.0, 1.0, 1.0);
+{$ENDIF}
 
 DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
 
-glPopMatrix
+{$IFDEF GL2}
+hglPopMatrix;
+{$ELSE}
+glPopMatrix;
+{$ENDIF}
+
 end;
 
 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
@@ -238,17 +352,29 @@
 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
     exit;
 
+{$IFDEF GL2}
+hglPushMatrix;
+hglTranslatef(X, Y, 0);
+{$ELSE}
 glPushMatrix;
 glTranslatef(X, Y, 0);
+{$ENDIF}
 
 if Dir < 0 then
     begin
     hw:= - hw;
+{$IFDEF GL2}
+    hglRotatef(Angle, 0, 0, -1);
+{$ELSE}
     glRotatef(Angle, 0, 0, -1);
+{$ENDIF}
     end
 else
-    glRotatef(Angle, 0, 0,  1);
-
+{$IFDEF GL2}
+    hglRotatef(Angle, 0, 0,  1);
+{$ELSE}
+    glRotatef(Angle, 0, 0, 1);
+{$ENDIF}
 
 glBindTexture(GL_TEXTURE_2D, Texture^.id);
 
@@ -261,11 +387,21 @@
 VertexBuffer[3].X:= -hw;
 VertexBuffer[3].Y:= hh;
 
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
+SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
+SetTexCoordPointer(@Texture^.tb, Length(VertexBuffer));
+
+{$IFDEF GL2}
+UpdateModelviewProjection;
+{$ENDIF}
+
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
-glPopMatrix
+{$IFDEF GL2}
+hglPopMatrix;
+{$ELSE}
+glPopMatrix;
+{$ENDIF}
+
 end;
 
 procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
@@ -324,10 +460,11 @@
 end;
 
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
-var VertexBuffer: array [0..3] of TVertex2f;
+var VertexBuffer: array [0..1] of TVertex2f;
 begin
+    glEnable(GL_LINE_SMOOTH);
+{$IFNDEF GL2}
     glDisable(GL_TEXTURE_2D);
-    glEnable(GL_LINE_SMOOTH);
 
     glPushMatrix;
     glTranslatef(WorldDx, WorldDy, 0);
@@ -339,13 +476,37 @@
     VertexBuffer[1].X:= X1;
     VertexBuffer[1].Y:= Y1;
 
-    glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+    SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
     glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
     Tint($FF, $FF, $FF, $FF);
     
     glPopMatrix;
     
     glEnable(GL_TEXTURE_2D);
+
+{$ELSE}
+    EnableTexture(False);
+
+    hglPushMatrix;
+    hglTranslatef(WorldDx, WorldDy, 0);
+    glLineWidth(Width);
+
+    UpdateModelviewProjection;
+
+    Tint(r, g, b, a);
+    VertexBuffer[0].X:= X0;
+    VertexBuffer[0].Y:= Y0;
+    VertexBuffer[1].X:= X1;
+    VertexBuffer[1].Y:= Y1;
+
+    SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
+    glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
+    Tint($FF, $FF, $FF, $FF);
+
+    hglPopMatrix;
+    EnableTexture(True);
+
+{$ENDIF}
     glDisable(GL_LINE_SMOOTH);
 end;
 
@@ -353,12 +514,17 @@
 var VertexBuffer: array [0..3] of TVertex2f;
 begin
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
+
 if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
     exit;
 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then
     exit;
 
+{$IFDEF GL2}
+EnableTexture(False);
+{$ELSE}
 glDisable(GL_TEXTURE_2D);
+{$ENDIF}
 
 Tint($00, $00, $00, $80);
 
@@ -371,11 +537,17 @@
 VertexBuffer[3].X:= r.x;
 VertexBuffer[3].Y:= r.y + r.h;
 
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
 Tint($FF, $FF, $FF, $FF);
+
+{$IFDEF GL2}
+EnableTexture(True);
+{$ELSE}
 glEnable(GL_TEXTURE_2D)
+{$ENDIF}
+
 end;
 
 procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); 
@@ -394,6 +566,9 @@
         CircleVertex[i].X := X + Radius*cos(i*pi/30);
         CircleVertex[i].Y := Y + Radius*sin(i*pi/30);
     end;
+
+{$IFNDEF GL2}
+
     glDisable(GL_TEXTURE_2D);
     glEnable(GL_LINE_SMOOTH);
     glPushMatrix;
@@ -403,6 +578,18 @@
     glPopMatrix;
     glEnable(GL_TEXTURE_2D);
     glDisable(GL_LINE_SMOOTH);
+
+{$ELSE}
+    EnableTexture(False);
+    glEnable(GL_LINE_SMOOTH);
+    hglPushMatrix;
+    glLineWidth(Width);
+    SetVertexPointer(@CircleVertex[0], 60);
+    glDrawArrays(GL_LINE_LOOP, 0, 60);
+    hglPopMatrix;
+    EnableTexture(True);
+    glDisable(GL_LINE_SMOOTH);
+{$ENDIF}
 end;
 
 
@@ -435,10 +622,15 @@
         r:= (Step + 1) * 32 / HHTexture^.w
     end;
 
-
+{$IFDEF GL2}
+    hglPushMatrix();
+    hglTranslatef(X, Y, 0);
+    hglRotatef(Angle, 0, 0, 1);
+{$ELSE}
     glPushMatrix();
     glTranslatef(X, Y, 0);
     glRotatef(Angle, 0, 0, 1);
+{$ENDIF}
 
     glBindTexture(GL_TEXTURE_2D, HHTexture^.id);
 
@@ -451,11 +643,20 @@
     TextureBuffer[3].X:= l;
     TextureBuffer[3].Y:= b;
 
-    glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-    glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+    SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
+    SetTexCoordPointer(@TextureBuffer[0], Length(VertexBuffer));
+
+{$IFDEF GL2}
+    UpdateModelviewProjection;
+{$ENDIF}
+
     glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
-    glPopMatrix
+{$IFDEF GL2}
+    hglPopMatrix;
+{$ELSE}
+    glPopMatrix;
+{$ENDIF}
 end;
 
 procedure DrawScreenWidget(widget: POnScreenWidget);
@@ -501,12 +702,14 @@
     end;
 {$ELSE}
 begin
-widget:= widget; // avoid hint
+{widget:= widget; // avoid hint}
 {$ENDIF}
 end;
 
 procedure Tint(r, g, b, a: Byte); inline;
-var nc, tw: Longword;
+var
+    nc, tw: Longword;
+    scale:Real = 1.0/255.0;
 begin
     nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
 
@@ -523,7 +726,12 @@
         b:= tw
         end;
 
+    {$IFDEF GL2}
+    glUniform4f(uMainTintLocation, r*scale, g*scale, b*scale, a*scale);
+    //glColor4ub(r, g, b, a);
+    {$ELSE}
     glColor4ub(r, g, b, a);
+    {$ENDIF}
     lastTint:= nc;
 end;
 
@@ -532,4 +740,5 @@
     Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
 end;
 
+
 end.