Colorizing a specific area on the screen.
BlitzMax Forums/BlitzMax Programming/Colorizing a specific area on the screen.
| ||
Hi, first of all thanks to all those who have kindly supported/replied on my previous topics. This time I got stuck trying to make a colorizer thigy for my game. Any tips/tricks/examples maybe, are most welcome. Thank you! |
| ||
Perhaps you could elaborate a little more on "colorizer thingy"? :) |
| ||
haha, okey then. sorry. It for an RPG. The screen is build up like this: [_|] Where on the left i have the tiled map 32x32 tiles, and on the right the game-menu. So what is need, is a function, or command, or whatever it is, that allows me to recoller all that is visable on the left. (Includes the map, players, animals, etc...) |
| ||
Use SetColor before you draw the objects and set the color to whatever `tint` you want them drawn with? |
| ||
Ah, i think what i meen is colorizing as in changing the RGB levels. R -100% to +100% G -100% to +100% B -100% to +100% |
| ||
do you mean: ? |
| ||
Thank you :) but no, this overrides all the colors. Here, i made an example: [img]http://www.fantasaar.com/rgbhsl.jpg[/img] |
| ||
If you only want to colorize specific colors of the tiles/sprites - dont use it realtime, precompute the sprites. How to achieve? Use search function within the blitzmax programming section - I did post it a while ago: ColorizeImage, ColorizeTImage. bye MB |
| ||
Like this?Graphics 640,480 Type Tsq Field x:Int=Rnd(640),y:Int=Rnd(480),xd:Int=Rnd(-4,4),yd:Int=Rnd(-4,4) Field r:Int=Rnd(255),g:Int=Rnd(255),b:Int=Rnd(255) Method update() x:+xd+640; y:+yd+480; x:Mod 640; y:Mod 480 End Method Method draw() SetColor r,g,b DrawRect x,y,20,20 End Method End Type Local sq:Tsq[40] For Local t:Int=0 To 39;sq[t]=New Tsq;Next Local timer:ttimer=CreateTimer(25) Repeat WaitEvent() If EventSource()=timer Cls SetBlend SOLIDBLEND SetColor 255,255,255 For t=0 To 39 sq[t].update;sq[t].draw Next SetBlend SHADEBLEND SetColor 32,32,32 DrawRect 512,0,128,480 SetBlend LIGHTBLEND SetColor 160,144,128 DrawRect 512,0,128,480 SetColor 255,255,255 DrawText "HP : 142/150",530,20 DrawText "EXP: 045/100",530,30 DrawText "MP : 005/50",530,40 SetBlend SOLIDBLEND SetColor 255,0,0;DrawRect 530,60,24,24 SetColor 0,255,0;DrawRect 560,60,24,24 SetColor 0,0,255;DrawRect 590,60,24,24 Flip EndIf Until KeyHit(KEY_ESCAPE) |
| ||
CS_TBL, it comes closer, but it is not what i ment. Let me try and explain it another time, but written: Purple is made out of red and blue. Yellow out of red and green. So if i want to make this purple ball yellow, i substract blue, and add green. What i dont want is have this done pre-computed, as i changed it realtime. Basicly, i ill use it for effects such as: Nightfall Sunrise Drakredish looking caves Brightblueish looking water etc.... The SetColor function, only takes the light & darkness, and forces all colors to turn red. What i need is (as shown in the picture) [img="http://www.fantasaar.com/rgbhsl.jpg"] Is a function that ADDS or SUBSTRACTS blue, or red, or green, or both TO and FROM an area on the screen, in real-time. In addition i would like to know if it is possible to ADD and SUBSTRACT anything at all? Like, if i where on top of the colorization to add a darker layer or effect, like a vail, that only lights up when i have a torch. (which i then would want to have a yellowish looking radius but not make ALL look pure yellow, just by adding a bit green and red for that zone.) What i expect, is that i have to render the whole backbuffer, lock it, apply the effects, unlock it, draw the HUD (which will not be effected) and FLIP it. Thank you. |
| ||
You can do it with pixmaps pixel by pixel, but I'm afraid that is too slow for realtime. Precompute them (I don't think the night/day etc changes every frame). |
| ||
In realtime? No not possible. Simply because you have to do it for every pixel manually and you can not use images, only pixmaps / backbuffer. The only way having such an effect in realtime is using shaders and let the GPU doing it straight "on the data" instead of working on a RAM replica of it that need to be reuploaded again. What you can do thought is not use a 3 channel picture at all :) Use 3 images. One for each channel, filled with grayscale values where the color shall be drawn and by what amount and masked out the rest. Now just draw them and use the SetColor to colorize them with the final color you want them to be drawn. That indeed would work realtime and depending on what you wanted to do, it will even work very good. But you see that your media must be created for this special use. |
| ||
I see. Hmm... Aint it possible to seperate these channels on loading? It is odd tough, i thoughd that BMAX would be graphicly more powerfull then Multimedia Fustion of ClickTeam. Their software does actualy all that with a snap. But the core there lays in C++ Also i thoughd Visual Basic has no problems with seperating RGB chanels. Isn't BMAX hardware accelerated? |
| ||
This has nothing to do with that. MMF is 2D and does everything through CPU. This is nice but damned slow when you want alpha, rotation and scaling. BM does 2D through 3D acceleration. This is very powerfull in above aspects. But on the other hand, you have to drop many of the "2D tricks" as they just don't work anymore on 3D or not on a usefull performance. You can seperate the channels on loading if you want to. Load the image as Pixmap and read out the needed data into 3 seperate pixmaps. Thats actually quite simple by just going through all pixels and filter out the 3 colors and write them into a new pixmaps (where you set that color for R, B and G if you want to color it afterwards through SetColor, otherwise its not grayscale) BM does not do that because its something not done normally, a 3D card takes a 4 component texture so why send 4 single textures if you can send 1 which already contains all 4 channels? It would make it considerably slower, tripple to quadruple the VRAM usage (which is already an issue if you want to target 4-6 year old trash systems ... thought thats near impossible anyway, if you target them, use BlitzPlus which is 2D through DirectX7 DirectDraw and thus has no alpha, realtime scale / rotation therefor) |
| ||
I wonder if you could achieve a similar effect by creating alpha masks so that some portions of the image retain their colour when applied over the base colour? Some experimentation may be necessary. *EDIT* Another alternative would of course be to create different graphics for each scene and have them loaded as TAnimImages, you could then advance through the animation to determine the mood (not great for file size or memory but an alternative nonetheless) |
| ||
Hah, some creative ideas :) i see there i lots of tricks to try. ill do my best and i guess post an update when i found the solution. @Dreamora "This has nothing to do with that. MMF is 2D and does everything through CPU. This is nice but damned slow when you want alpha, rotation and scaling." Actualy, it is now Hardware Accelerated. I beleive it uses both. 2D todo 2D, and what can be done, or faster in HWA, is done on HWA. Thinks i do not really need are: Realtime scaling/Rotation. Alpha, however (like PNG) is really great to have supported. I will look into BlitzPlus. I do question if its powerfull enough. It is after all a very old product. |
| ||
i think this is what your after... this is a very unoptimised replace olour technique. usage i:tpixmap = loadpixmap("image.png") ' replace all exact white occurances with bright purple p:tpixmap = replacecolour(i:tpixamp,$ffffff,$ff00ff) ' replace all nearly white occurances with bright purple p:tpixmap = replacecolour(i:tpixamp,$ffffff,$ff00ff,10) functions Function replacecolour:TPixmap(p:TPixmap,old_rgb:Int,new_rgb:Int,threshold:Int) Local w:Int = PixmapWidth(p) Local h:Int = PixmapHeight(p) Local x:Int,y:Int Local b1:Byte Ptr Local b2:Byte Ptr Local n:TPixmap = CreatePixmap(w,h,pf_BGRA8888) Local r:Int = (old_rgb Shr 16) & 255 Local g:Int = (old_rgb Shr 8) & 255 Local b:Int = (old_rgb Shr 0) & 255 Local p1:TPixmap = ConvertPixmap(p,PF_BGRA8888) ' scan through image x =0 While x < w y = 0 While y < h b1 = PixmapPixelPtr(p1,x,y) b2 = PixmapPixelPtr(n,x,y) If threshold_check(r,b1[2],threshold) And threshold_check(g,b1[1],threshold) And threshold_check(b,b1[0],threshold) b2[0] = (new_rgb Shr 0) & 255 b2[1] = (new_rgb Shr 8) & 255 b2[2] = (new_rgb Shr 16) & 255 b2[3] = $ff Else b2[0] = b1[0] b2[1] = b1[1] b2[2] = b1[2] b2[3] = b1[3] EndIf y:+1 Wend x:+1 Wend Return n End Function Function threshold_check:Int(v1:Int,v2:Int,t:Int) If (v1 > v2-t) And (v1 < v2+t+1) Then Return True Return False End Function |
| ||
or if you want to dirrectly affect the pixels in the pixmap without creating a new pixmapFunction replacecolour2:Int(p:TPixmap,old_rgb:Int,new_rgb:Int,threshold:Int) Local w:Int = PixmapWidth(p) Local h:Int = PixmapHeight(p) Local x:Int,y:Int Local c:Int Local r1:Int,g1:Int,b1:Int ' Local n:TPixmap = CreatePixmap(w,h,pf_BGRA8888) Local r:Int = (old_rgb Shr 16) & 255 Local g:Int = (old_rgb Shr 8) & 255 Local b:Int = (old_rgb Shr 0) & 255 ' Local p1:TPixmap = ConvertPixmap(p,PF_BGRA8888) ' scan through image x =0 While x < w y = 0 While y < h c = ReadPixel(p,x,y) r1 = (c Shr 16) & 255 g1 = (c Shr 8) & 255 b1 = (c Shr 0) & 255 If threshold_check(r,r1,threshold) And threshold_check(g,g1,threshold) And threshold_check(b,b1,threshold) WritePixel p,x,y,new_rgb EndIf y:+1 Wend x:+1 Wend Return True End Function if you have an image you can call the routines with image.pixmaps[frame] this gets the pixmap for the relevant frame in the image |
| ||
@PantsOn - thats what my suggestion uses too. Instead of using a yellow ball - you make a gray one - then all colorcombinations are possible - and because you have one standard for the sprites (gray parts), you can easily cut the function call down to "new colors" (instead of oldcol and newcol). I remember to have grayalien given a code-snippet which also allowed lightness to be modified (so you can use fixed values for color, but dynamical usage of how hard it is melt together and so on). Depending on how much differently colored sprites of the same base you need the same time you can use precalculated sprites (one dark, one day, one rainy ...). Its not suitable for "rainbow-colorchanging balls" - therefor you need to experiment with the SetAlpha-Commands and effectsprites. bye MB |