Author Topic: [Lua] Palette Based Graphics Programming  (Read 5177 times)

Calin Leafshade

  • AGS Project Tracker Admins
  • Long live King Cat!
    • I can help with making music
    •  
    • I can help with voice acting
    •  
    • Calin Leafshade worked on a game that was nominated for an AGS Award!
      Calin Leafshade worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #40 on: 01 Dec 2013, 02:38 »
It's not mentioned in the code so it looks like Denzil planned to implement it but never did.

you could try Lua.Evaluate.

Code: Adventure Game Studio
  1. int i = 0;
  2. while(i < 255)
  3.     Lua.Evaluate(String.Format("palette_r[%d] = %d", i, value));
  4.     i++;
  5. end
  6.  
  7.  

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #41 on: 01 Dec 2013, 02:47 »
Got this:

Quote
Script link failed: Runtime Error: Unresolved import 'Lua::Evaluate^2'

I am really sorry I am having so much trouble with this. x3

Calin Leafshade

  • AGS Project Tracker Admins
  • Long live King Cat!
    • I can help with making music
    •  
    • I can help with voice acting
    •  
    • Calin Leafshade worked on a game that was nominated for an AGS Award!
      Calin Leafshade worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #42 on: 01 Dec 2013, 02:49 »
Not a problem dude.

Seems that function is also missing.

try:

Code: Adventure Game Studio
  1. Lua.SetVar(String.Format("palette_r[%d]",i), value)
  2.  

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #43 on: 01 Dec 2013, 03:17 »
Okay, I managed to make ProcessPalette start working! It's pretty smooth up until Next error is this particularily nebulous one:

Quote
Attempt to compare nil with number

Code: Lua
  1. function ProcessPalette (...)
  2.   local palindex = {...}
  3.   local paltemp = {...}
  4.   local i = 0
  5.   local i2 = 1
  6.   local upperboundary = 0
  7.   C8Palgorithm = {}
  8.   C8PaletteMap = {}
  9.   while (i < table.getn(palindex))
  10.   do
  11.     --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
  12.     paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
  13.     paltemp [i] = bit.rshift(paltemp [i],3)
  14.     i = i + 1
  15.   end
  16.   i = 0
  17.   C8palgorithm = {}
  18.   while (i < table.getn(palindex))
  19.   do
  20.       if (i > table.getn(palindex)-2) then upperboundary = 255
  21.       else upperboundary = (paltemp [i] + paltemp [i + 1])/2  --THIS IS THE LINE IT CHOKES AT
  22.       end
  23.      
  24.       while (i2 < upperboundary)
  25.       do
  26.         C8palgorithm [i2] = palindex[i]
  27.         i2 = i2 + 1
  28.       end
  29.     i = i + 1
  30.   end
  31.    
  32.    i= 0
  33.    paltemp = {}
  34.    while (i < 255)
  35.       do
  36.        --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
  37.        paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
  38.        paltemp [i] = bit.rshift(paltemp [i],3)
  39.        i = i+ 1
  40.       end
  41.     i = 0
  42.     while (i < 255)
  43.       do
  44.        C8PaletteMap [i] = C8palgorithm [paltemp[i]]
  45.        i = i + 1
  46.       end
  47.  
  48. end

Splitting the line into two:

Code: Lua
  1.         upperboundary = paltemp [i] + paltemp [i + 1]
  2.         upperboundary = upperboundary /2 --It chokes here now.

I'm sure I'll be able to figure out errors like these when I get more used to Lua, but... choking on a simple division?

Calin Leafshade

  • AGS Project Tracker Admins
  • Long live King Cat!
    • I can help with making music
    •  
    • I can help with voice acting
    •  
    • Calin Leafshade worked on a game that was nominated for an AGS Award!
      Calin Leafshade worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #44 on: 01 Dec 2013, 04:41 »
dont use table.getn use the # operator instead. #palindex returns the number of values in the array (numberically indexed) part of a table.

Quote
Attempt to compare nil with number

That error is for a comparison (i.e < > <= >= == ~=). If the value were nil you'd get an arithmatic error.
Are you sure thats the offending line?

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #45 on: 01 Dec 2013, 15:03 »
Okay, copied the lua file into Notepad++ to count the lines there, solved that issue.

But there are so many other issues cropping up I am beginning to lose hope that I'll ever get this done. I don't think I'm quite qualified to even do this.

1) The colourisation function crashes AGS with the same
Quote
Error: [Lua] [string "local select = select;local error = error;l..."]:1: bad argument #2 to 'setter' (number expected, got nil)

Error. I have no idea what is going wrong there. I added a UsingLua bool you can switch on and off to see the intended effect there.

2) Only Object 0 is affected by translucency. Even though in repeatedly_execute_always it iterates through all of the objects on screen, only Object 0 will be translucent.

3) Other objects are invisible behind a translucent object. I think this is related to 2, as somewhere along the line the function is just choking. Characters render fine. This is odd, as I knew I tested this in the AGSScript version. It just... stopped working.

I'll put the project here:
https://dl.dropboxusercontent.com/u/50882197/Game/paltest321_errors.zip
If anyone wants to take a look. It uses the FakeScreen functions (DrawObject, DrawCharacter) to build the background and the characters on it so that the translucency drawing functions know what is behind the object at the time. The workflow goes:

repeatedly execute always: Is there translucency to be rendered? If so, create a surface and start building on it until a translucent object needs to be rendered. Then, render the translucent object (DrawObject) and set that to be the object's graphic.
« Last Edit: 01 Dec 2013, 15:08 by Scavenger »

Re: [Lua] Palette Based Graphics Programming
« Reply #46 on: 01 Dec 2013, 23:32 »
Hi, hi, really sorry you've been having all these issues with the Lua plugin! Please bear with me a little. This is a really cool project and I always wanted people to use the plugin for ambitious interesting things so I feel like I've really dropped the ball on this one. I have posted some stuff in the plugin thread about where the problem seems to be in issue 1.) there. I will address missing API functions and the lousy documentation as soon as I can. Sorry again!

Re: [Lua] Palette Based Graphics Programming
« Reply #47 on: 02 Dec 2013, 12:59 »
Two problems I noticed in the Lua Colourise() function:
  • cpixel is sometimes -1, and C8PaletteMap[-1] doesn't exist, so surface.DrawingColor is being set to nil, which is invalid
  • there's an infinite loop problem in there:
Code: Lua
  1. while (i < w) do
  2.  
  3.   -- ( . . . ) --
  4.  
  5.   i = j + 1
  6. end
    (...should be i = i + 1)


Also, this bit in ProcessPalette:
Code: Lua
  1. while (i < palsiz)
  2. do
  3.   if (i > palsiz) then upperboundary = 255
  4.   -- ... --

...looks like it should probably have "-2" added, to be equivalent to the AGSScript version in pal2.asc:

Code: Adventure Game Studio
  1. while (i < palsiz)
  2. {
  3.   if (i > palsiz -2) upperboundary = 255;
« Last Edit: 02 Dec 2013, 13:24 by Denzil Quixode »

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #48 on: 03 Dec 2013, 02:25 »
It's cool, Denzil, I'm really liking this plugin and it can do some amazing things compared to plain AGSScript. It's mostly my newness to Lua that is holding me back.

I corrected those errors, but I'm still getting the same problem:

Code: Lua
  1. function Colourise (ds)
  2.   local surface = ds:GetDrawingSurface ()
  3.   local i = 0;
  4.   local j= 0;
  5.   local h = ds.Height
  6.   local w = ds.Width
  7.   local cpixel;
  8.   while (j < h)
  9.   do
  10.     while (i < w)
  11.     do
  12.       cpixel = surface:GetPixel (i, j)
  13.       if (cpixel == -1)
  14.         then
  15.           surface.DrawingColor = 0
  16.       else
  17.           surface.DrawingColor = C8PaletteMap [cpixel]
  18.         end
  19.       surface:DrawPixel (i, j)
  20.       i = i + 1
  21.     end
  22.     i = 0
  23.     j = j + 1
  24.   end
  25.   surface:Release ()
  26. end

Calin Leafshade

  • AGS Project Tracker Admins
  • Long live King Cat!
    • I can help with making music
    •  
    • I can help with voice acting
    •  
    • Calin Leafshade worked on a game that was nominated for an AGS Award!
      Calin Leafshade worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #49 on: 03 Dec 2013, 03:19 »
Here are some tricks to simplify your code:

Code: Lua
  1. function Colourise (ds)
  2.   local surface = ds:GetDrawingSurface ()
  3.   local h = ds.Height
  4.   local w = ds.Width
  5.   local cpixel;
  6.   for j=0, h-1 do
  7.     for i=0, w-1 do
  8.         cpixel = surface:GetPixel (i, j)
  9.         surface.DrawingColor = C8PaletteMap[cpixel] or 0
  10.         surface:DrawPixel (i, j)
  11.     end
  12.   end
  13.   surface:Release ()
  14. end
  15.  

See if that crashes. It makes it so that DrawingColor can never be nil.

Re: [Lua] Palette Based Graphics Programming
« Reply #50 on: 03 Dec 2013, 09:11 »
^^ Yeah, a good suggestion from Calin there. So it looks like Lua's C8PaletteMap has some holes in it, not all palette slots are being set in ProcessPalette().

One thing I notice about ProcessPalette() is that you're taking an array of parameters using palindex = {...} but this array will start from 1 rather than 0, and later code adapted from AGSScript naturally isn't expecting this. So to change it to a 0-based array, you could change the first few lines of ProcessPalette() from:

Code: Lua
  1. function ProcessPalette (...)
  2.   local palindex = {...}
  3.   local paltemp = {...}
  4.   local palsiz = #palindex

...to:

Code: Lua
  1. function ProcessPalette (...)
  2.   local palindex = {}
  3.   local paltemp = {}
  4.   local palsiz = select('#', ...) -- get number of arguments
  5.   for n = 1, palsiz do
  6.     palindex[n - 1] = select(n, ...) -- get nth argument
  7.     paltemp[n - 1] = select(n, ...)
  8.   end

A second thing in ProcessPalette(): it looks like, in the first while-loop, where the original AGSScript version of the function uses ags.palette[palindex[ i ]].r etc. the Lua version uses (the equivalent of) ags.palette[ i ].r

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #51 on: 03 Dec 2013, 17:07 »
Alright! With Calin and Denzil's amendments to the code, it no longer crashes, and it shows the effect! I fixed the palette[palindex[ i ]].r bit and the colours got more accurate, but they still aren't correct compared to the AGSScript version.

Code: Adventure Game Studio
  1. int paltemp [];
  2.   paltemp = new int [palsiz];
  3.   char i = 0;
  4.   int i2 = 1;
  5.   int upperboundary;
  6.   while (i < palsiz)
  7.   {
  8.     paltemp [i] = (palette[palindex[i]].r +  // This algorithm produces an accurate, fast approximation of
  9.                    palette[palindex[i]].r +  // The luminescence value of each of our palette slots.
  10.                    palette[palindex[i]].r +  //
  11.                    palette[palindex[i]].b +  // This ensures that when we colourise the final product, there
  12.                    palette[palindex[i]].g +  // will be little to no weird artifacts or lightness shifts.
  13.                    palette[palindex[i]].g +  //
  14.                    palette[palindex[i]].g +  // By using addition and bit shifts instead of multiplication,
  15.                    palette[palindex[i]].g    // the code will run a lot faster and more efficiently.
  16.                    )>>3;
  17.     i++;
  18.   }
  19.   i = 0;
  20.   while (i < palsiz)
  21.   {
  22.       //Display ("%d , %d", i,  i+1);
  23.       if (i > palsiz -2) upperboundary = 255;
  24.       else upperboundary = (paltemp [i] + paltemp [i + 1])/2;
  25.       //Display ("%d",upperboundary);
  26.  
  27.       while (i2 < upperboundary)
  28.       {
  29.         _C8palgorithm [i2] = palindex[i];
  30.         i2++;
  31.       }
  32.     i++;
  33.     }
  34.    
  35.     i= 0;
  36.     paltemp = new int [256];
  37.     while (i < 255)
  38.       {
  39.        paltemp [i] = (palette[i].r +  // This algorithm produces an accurate, fast approximation of
  40.                       palette[i].r +  // The luminescence value of each of our palette slots.
  41.                       palette[i].r +  //
  42.                       palette[i].b +  // This ensures that when we colourise the final product, there
  43.                       palette[i].g +  // will be little to no weird artifacts or lightness shifts.
  44.                       palette[i].g +  //
  45.                       palette[i].g +  // By using addition and bit shifts instead of multiplication,
  46.                       palette[i].g    // the code will run a lot faster and more efficiently.
  47.                       )>>3;
  48.                       i++;
  49.       }
  50.     i = 0;
  51.     while (i < 255)
  52.       {
  53.        _C8PaletteMap [i] = _C8palgorithm [paltemp[i]];
  54.        i++;
  55.       }

Code: Lua
  1. function ProcessPalette (...)
  2.   local palindex = {}
  3.   local paltemp = {}
  4.   local palsiz = select('#', ...) -- get number of arguments
  5.   for n = 1, palsiz do
  6.      palindex[n - 1] = select(n, ...) -- get nth argument
  7.      paltemp[n - 1] = select(n, ...)
  8.   end
  9.   local i = 0
  10.   local i2 = 1
  11.   local upperboundary = 0
  12.   C8palgorithm = {}
  13.   C8PaletteMap = {}
  14.   C8PaletteMap [0] = C8PaletteMap [0] or {}
  15.   C8palgorithm [0] = C8palgorithm [0] or {}
  16.   while (i < palsiz)
  17.   do
  18.     --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
  19.     paltemp [i] = palette_r [palindex[i]] + palette_r [palindex[i]] + palette_r [palindex[i]] + palette_b [palindex[i]] +  palette_g [palindex[i]] + palette_g [palindex[i]] + palette_g [palindex[i]] + palette_g [palindex[i]]
  20.     paltemp [i] = bit.rshift(paltemp [i],3)
  21.     i = i + 1
  22.   end
  23.   i = 0
  24.   C8palgorithm = {}
  25.   while (i < palsiz)
  26.   do
  27.       if (i > palsiz - 2) then upperboundary = 255
  28.       else
  29.         upperboundary = paltemp [i] + paltemp [i + 1]
  30.         upperboundary = upperboundary /2
  31.         end
  32.      
  33.       while (i2 < upperboundary)
  34.       do
  35.         C8palgorithm [i2] = palindex[i]
  36.         i2 = i2 + 1
  37.       end
  38.     i = i + 1
  39.   end
  40.    i= 0
  41.    paltemp = {}
  42.    while (i < 255)
  43.       do
  44.        --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
  45.        paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
  46.        paltemp [i] = bit.rshift(paltemp [i],3)
  47.        i = i+ 1
  48.       end
  49.     i = 0
  50.     while (i < 255)
  51.       do
  52.        C8PaletteMap [i] = C8palgorithm [paltemp[i]]
  53.        i = i + 1
  54.       end
  55.  
  56. end

Is the problem that Lua is counting from 1 again in the latter part of it?

The effect now looks like this:


The code looks identical, but the effect is very off. I'm not even sure how it's getting those non-blue colours.

ALSO, I'm trying to fix the translucency things, and I've noticed something very odd about the FakeScreen code I'm using:

Code: Adventure Game Studio
  1. while ((i < Game.CharacterCount) || (i < Room.ObjectCount)) {
  2.     if ((i < Game.CharacterCount) && (character[i].Room == player.Room)) surface.DrawCharacter(character[i]);
  3.     if (i < Room.ObjectCount) {
  4.       if (object[i].Visible) surface.DrawObject(object[i]);
  5.       if (object[i].Graphic && object[i].Visible) {
  6.         int scale = GetScalingAt(object[i].X, object[i].Y);
  7.         int ow = (Game.SpriteWidth[object[i].Graphic] * scale) / 100;
  8.         int oh = (Game.SpriteHeight[object[i].Graphic] * scale) / 100;
  9.         if (object[i].IgnoreScaling) {
  10.           ow = Game.SpriteWidth[object[i].Graphic];
  11.           oh = Game.SpriteHeight[object[i].Graphic];
  12.         }
  13.         int ox1 = object[i].X;
  14.         int ox2 = ox1 + ow;
  15.         int j = 0;
  16.         while (j < Game.CharacterCount) {
  17.           if (character[j].Room == player.Room) {
  18.             ViewFrame *frame = Game.GetViewFrame(character[j].View, character[j].Loop, character[j].Frame);
  19.             int cw = (Game.SpriteWidth[frame.Graphic] * character[j].Scaling) / 100;
  20.             int cx1 = character[j].x - (cw / 2);
  21.             if ((((cx1 + cw) >= ox1) && (cx1 <= ox2)) && (character[j].y > object[i].Baseline) && ((character[j].y - character[j].z) >= (object[i].Y - oh))) surface.DrawCharacter(character[j]);
  22.           }
  23.           j++;
  24.         }
  25.       }
  26.     }
  27.     i++;
  28.   }

It doesn't take into account the baseline of the objects, and it only seems to ever draw one object on it's surface. How do I sort objects by their baseline and draw them top-to-bottom, instead of by their object IDs? Otherwise I get stuff like this:



Which makes the effect kind of pointless. (The other object is invisible even when it's Y coordinate is above the translucent sprite. I have no idea what's going on!)

I'm really sorry for being so useless at solving these problems. This must be getting really irritating. x3

Re: [Lua] Palette Based Graphics Programming
« Reply #52 on: 04 Dec 2013, 18:03 »
The effect now looks like this:


The code looks identical, but the effect is very off. I'm not even sure how it's getting those non-blue colours.
I think there's something odd going on when you use DrawingColor zero. I tried changing Lua's Colourise() to draw every pixel to zero, and got a lot more of that colourful effect:



Then I tried the same as Calin's except with or 255 instead of or 0:



So it looks like (I'm guessing here) drawing with DrawingColor 0 is adding transparency, punching a "hole" in the image, but what is showing up "behind" it happens to be a lot of weird pixels when Lua does it, but solid black when AGSScript does it. I've got no idea why though.
« Last Edit: 04 Dec 2013, 18:05 by Denzil Quixode »

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    •  
    • I can help with backgrounds
    •  
    • I can help with characters
    •  
    • I can help with scripting
    •  
    • Scavenger worked on a game that was nominated for an AGS Award!
      Scavenger worked on a game that won an AGS Award!
Re: [Lua] Palette Based Graphics Programming
« Reply #53 on: 04 Dec 2013, 18:47 »
Yeah, that works! Weird that Lua is doing that with DrawingColor=0. I'm guessing it doesn't show up on the Translucency because Lua doesn't actually write pixels of the 0 colour.

This is a weird bug - does it do the same thing in 16 bit and 32bit with magic pink?