Recent

Author Topic: BGRA OpenGL StretchDraw how to do it 'pixelated'  (Read 10694 times)

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
BGRA OpenGL StretchDraw how to do it 'pixelated'
« on: June 14, 2015, 04:48:05 am »
Hi, I'm using the BGRA OpenGL and I want to draw the stretched bitmap in a pixelated way, instead of the bitmap get smooth when resized.

This is my code. Actually a window of 1280 by 720 pixels. It gets smooth when I upscale the window.

Edit: Maybe I must just stretch the bitmap when the object is created?

Code: [Select]
unit ugame;

{$mode objfpc}{$H+}

interface

uses
  Classes, Forms, SysUtils, Graphics, BGRABitmap, BGRABitmapTypes, BGRAOpenGL,
  Math;

type

  { TGame }

  TGame = class
  private
    FTilesX: integer;
    FTilesY: integer;
    FTileW: integer;
    FTileH: integer;
    FOffsetX: integer;
    FOffsetY: integer;
    FWidth: integer;
    FHeight: integer;
    FTexture: IBGLTexture;
  public
    constructor Create(Width, Height: integer);
    destructor Destroy; override;
  public
    procedure Draw;
  end;

implementation

{ TGame }

constructor TGame.Create(Width, Height: integer);
begin
  { window size }
  FWidth := Width;
  FHeight := Height;

  { number of tiles, zero based, to be specified in level file }
  FTilesX := 40 - 1;
  FTilesY := 23 - 1;

  { tile width resolution dependant, window size is fixed and can be set only at startup }
  FTileW := round(FWidth * 0.025); // 40 tiles of 32x32 @ 1280p
  FTileH := round(FHeight * 0.045); // 22,5 tiles of 32x32 @ 720p

  { center the map }
  FOffsetX := round((FWidth - ((FTilesX + 1) * FTileW)) * 0.5); // center x
  FOffsetY := round((FHeight - ((FTilesY + 1) * FTileH)) * 0.5); // center y

  { graphics loading, to be specified in level file }
  FTexture := BGLTexture(ExtractFilePath(Application.ExeName) + 'tile.png');
end;

destructor TGame.Destroy;
begin
  FTexture.FreeMemory;
  inherited Destroy;
end;

procedure TGame.Draw;
var
  y, x: integer;
begin
  { Fill background }
  BGLViewPort(FWidth, FHeight, BGRABlack);

  for y := 0 to FTilesY do
  begin
    for x := 0 to FTilesX do
    begin
      FTexture.StretchDraw(FOffsetX + (x * FTileW), FOffsetY + (y * FTileH), FTileW, FTileH);
    end;
  end;
end;

end.

« Last Edit: June 14, 2015, 07:23:38 am by 007 »

circular

  • Hero Member
  • *****
  • Posts: 4467
    • Personal webpage
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #1 on: June 14, 2015, 01:11:13 pm »
Ah it is not possible for now. Basically interpolation in OpenGL is set for the texture itself. So maybe it is possible to do that by adding a property to IBGLTexture.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #2 on: June 14, 2015, 02:39:09 pm »
Yes I've searched for that and seems problematic to do with OpenGL, so I will try resizing the bitmap with TBGLBitmap and then creating the already resized texture. The power of the mixed library :)

If someone in the future is reading this, this is the solution I found

Code: [Select]
  { graphics loading, to be specified in level file }
  Bitmap := TBGRABitmap.Create(ExtractFilePath(Application.ExeName) + 'tile.png');
  Bitmap.ResampleFilter := rfBox;
  BGRAReplace(Bitmap, Bitmap.Resample(FTileW,FTileH) as TBGRABitmap);

  BitmapGL := TBGLBitmap.Create(FTileW,FTileH);
  BitmapGL.BlendImage(0,0,Bitmap,boLinearBlend);
  Bitmap.Free;

  FTexture := BitmapGL.MakeTextureAndFree; 

Carver413

  • Full Member
  • ***
  • Posts: 119
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #3 on: June 14, 2015, 05:25:08 pm »
the problem is more in  BGRA then OpenGL you have your quad size bound to the texture size so no way to stretch it. if you increase the quad size but not the texture size your texture will stretch. uv maping should stay the same. also you might want to make use of the modelview matrix if your not already. it can move scale and rotate without making any changes to the object.

circular

  • Hero Member
  • *****
  • Posts: 4467
    • Personal webpage
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #4 on: June 14, 2015, 10:54:15 pm »
@Carver: it is simply not implemented yet in BGRA.

@007: isn't it possible to resample with a TBGLBitmap object directly?
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #5 on: June 15, 2015, 12:39:02 am »
@007: isn't it possible to resample with a TBGLBitmap object directly?

Now I'm doing this way, so I need only a bitmap and a texture:

Code: [Select]
  Bitmap := TBGRABitmap.Create(ExtractFilePath(Application.ExeName) + 'tile.png');
  Bitmap.ResampleFilter := rfBox;
  BGRAReplace(Bitmap, Bitmap.Resample(FTileW,FTileH));

  FTexture := BGLTexture(Bitmap.Data, FTileW, FTileH, FTileW, FTileH);
  Bitmap.Free;                         

---

About using TBGLBitmap:
Resample outs a TBGRABitmap. (TBGRAWinBitmap in my case - i think -).
The first part Is the same code but with TBGLBitmap. I can't use BGRAReplace, so I've changed it to BGLReplace.

Maybe I'm doing it wrong, but I get an EOutOfMemory error with that.
« Last Edit: June 15, 2015, 01:22:33 am by 007 »

Carver413

  • Full Member
  • ***
  • Posts: 119
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #6 on: June 15, 2015, 02:04:58 am »
@Carver: it is simply not implemented yet in BGRA.
I figured that was the case, always one more thing to do

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #7 on: June 15, 2015, 07:21:31 pm »
- If the 'pixelated drawing' is implemented I will not need to upscale texture, with 32x32 I will be able to draw to 40x40 pixels for example and texture size will remain 32x32 internally.

- I can just keep the downscale of textures to smaller sizes, so for example instead of having 32x32 texture when my game run on smaller resolutions, textures will be smaller and the game will run faster. I.e 8x8 texture when my game run at 320x240 resolution.

- When implemented 'pixelated drawing' will be faster than drawing a 48x48 texture (that internally has a 40x40 bitmap that I will use to draw). For example on higher resolutions than 1280x720. I mean if the 'pixelated drawing' is costly than just the resample one time. Although the size of the texture increases when I resample.

It will look like:
- 32x32 texture -> pixelated drawing -> 40x40 on screen
- 48x48 texture (with 40x40 pixels inside) -> normal drawing -> 40x40 on screen

What is faster of these two? Of course these are really small textures, maybe it's more visible if
32-32 -> 1000x1000
and
1024x1024 -> 1000x1000

of course texture resampled to higher sizes will use more memory, but I can't see if it will be faster or slower, since on screen both times are 1000x1000 pixels beign drawn :)

Hopefully I'm clear.

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #8 on: June 15, 2015, 08:44:53 pm »
Well forget that :(

Is almost impossible to get pixelated stuff also with resampling. Always there is a chance to get blurry pixels under different screen resolutions.

Downscaling sometimes I get blurry pixels, upscaling sometimes I get double pixels, so that's it.

So the thing is scale textures in 16,32,48 and so on only. The number of tiles shown on screen will be inconsistent. But is the only way to get pixel perfect stuff.

circular

  • Hero Member
  • *****
  • Posts: 4467
    • Personal webpage
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #9 on: June 15, 2015, 09:50:12 pm »
I am implementing the pixelated stretch. It seems to work fine so it will be in next version.

With OpenGL, I don't think there is much difference how it is resampled before it is strechted drawn.

I agree, the number of tiles could vary slightly depending on screen resolution to get pixel perfect tiles.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #10 on: June 15, 2015, 10:19:30 pm »
Alright. Thanks for implementing it.

So if doesnt't matter i will keep my current code. Also textures will be 32x32 most time and bigger as 48x48 sometimes when user set 1080p.

In order to dont lose pixels also will be a minimum screen size to play the game, so there is no problem of downscaling tiles.

At least that seems to work. Lol i just see that running Titan Souls at different screen resolutions :) always pixel perfect, 32x32 at 800x600 minimum playable resolution. So the game is really designed to work in the smallest resolution and then extra surrounding tiles are added for bigger resolutions. And the scaling is pixel perfect.
« Last Edit: June 15, 2015, 10:38:27 pm by 007 »

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #11 on: June 15, 2015, 11:23:40 pm »
Ok. Another thing (I post it here because is related):

Textures Upside down.

When I create a TBGRABitmap and then I use the data to create a IBGLTexture, everything is upside down. So top things are at bottom, noticed just now that I set up some real texture, not just perfect rectangles with a fill color  ::)

Using TBGLBitmap works fine, but as I explained before I can't resample using that.

So yes, maybe I'll wait until there is ready the pixelated stretch.

@007: isn't it possible to resample with a TBGLBitmap object directly?

Now I'm doing this way, so I need only a bitmap and a texture:

Code: [Select]
  Bitmap := TBGRABitmap.Create(ExtractFilePath(Application.ExeName) + 'tile.png');
  Bitmap.ResampleFilter := rfBox;
  BGRAReplace(Bitmap, Bitmap.Resample(FTileW,FTileH));

  FTexture := BGLTexture(Bitmap.Data, FTileW, FTileH, FTileW, FTileH);
  Bitmap.Free;                         

---

About using TBGLBitmap:
Resample outs a TBGRABitmap. (TBGRAWinBitmap in my case - i think -).
The first part Is the same code but with TBGLBitmap. I can't use BGRAReplace, so I've changed it to BGLReplace.

Maybe I'm doing it wrong, but I get an EOutOfMemory error with that.

circular

  • Hero Member
  • *****
  • Posts: 4467
    • Personal webpage
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #12 on: June 15, 2015, 11:32:43 pm »
Indeed there are can be differences in line order.

Ah yes, there is this problem of resampling.
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4740
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #13 on: June 16, 2015, 12:15:57 am »
Don't worry I also learn something with all this practice:

For doing pixel perfect 16x16 is better.
Double is 32x32 (1 pixel is 2) and 48x48 where 1 pixel is 3 and so on.

32x32 is too big for start since the nearest pixel perfect is 64. And tiles will be too huge.

circular

  • Hero Member
  • *****
  • Posts: 4467
    • Personal webpage
Re: BGRA OpenGL StretchDraw how to do it 'pixelated'
« Reply #14 on: June 16, 2015, 12:31:12 am »
I understand.

Maybe it would make sense to have tiles both for 16x16 and 32x32, so that you could have a bit more details. However, then for 48x48, I am not sure the result would be great from 32x32.
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018