GameMaker: Studio

GameMaker: Studio

查看统计:
BOYCOTT S-T-E-A-M! 2015 年 11 月 2 日 上午 12:50
Changing Color of Parts of a Sprite?
I know that you can use image_blend to tint the color of a sprite entirely, but is there any ways to only change the color of certain things on a sprite?

For instance, if I have a sprite of a person wearing a white uniform is there any blending functions that would allow me to only tint the coloring of the white uniform without altering the color of the persons skin?

The sprite editor has an feature called "colourize partial" which allows you to take one hue of the image and replace it with a different hue. This is essentially exactly the functionality I'm looking for, but I'm looking for a way to have it done via code. That way I could make a single graphic for a soldier or vehicle and have a portion of it changed to match the color of the player that is in control of it without having changed the color of the sprite as a whole.
最后由 BOYCOTT S-T-E-A-M! 编辑于; 2015 年 11 月 2 日 上午 1:14
< >
正在显示第 1 - 13 条,共 13 条留言
Daynar 2015 年 11 月 2 日 上午 4:46 
In the past to achieve this effect I've seperated all the parts of the sprite I want to be different colors and then blended each part with whatever color as it was drawn. You might be able to keep the sprite as one and use shaders, but I'm not good with shaders so you may not be able to.
BOYCOTT S-T-E-A-M! 2015 年 11 月 2 日 上午 6:17 
Wow... there really isn't a simple and efficient way to do color or palette swapping?

I'm actually pretty shocked by this. I figured that since it was easily doable in the sprite editor there would likely be some form of sprite, color, or draw function that would allow you to do it.


I was hoping to have my units have a part of them showing the color of the player that is in control of them. Currently I have seperate sprites for each player color, but now that I'm at the point of having to actually do various animations and things its just turning into a massive chore and a huge amount of sprites despite not having many different types of units in my game.

If I further broke my objects down into more objects, a pre-determined color part of the object and a part that is easily altered by blending, then I'd end up having even more sprites and having even more things to have to coordinate together during animation.

I kinda pity anyone making an RPG or anything similar since they wouldn't be able to just do simple color swapping, but have to actually make entirely new sprites. Ouch.


I've tried looking into the idea of using shaders for it since from what I've read it sounds like thats a way to do it... unfortunately I can't find anyone actually giving understand information on how it works and how to make and use shaders.

All I've managed to find is people showing off what shaders can do or providing their own shaders. No explaination of how I can go about making any to suit my needs though.

Even tried to figure out the shaders demo that comes with Gamemaker since that has a thing on color swapping, but it didn't really explain anything about how its working. All I could gather is that it was able to take the color of pure white in an image and swap it to red. No idea about how to do things with a tolerance range or anything of the sort.
Blind 2015 年 11 月 2 日 下午 2:38 
This is done via shaders. Have and input shader read white and output based on your variable
Daynar 2015 年 11 月 2 日 下午 4:11 
It's not actually that hard to do with just sprites. You know those naked 'maniquine' characters people draw? Just have it draw that for the player and then have 2 variables for each piece of clothing or put it in an array. Then draw the clothing overtop the player sprite, this is easiest to work with if you have all the clothing/recolored bits animate to follow the player and have the sprite origin offset to match the origin of the player. (so that you can just use the player x/y)
so the draw event would look like this.
draw_self() //hat/hair draw_sprite_ext(clothing[0,0],image_index,x,y,image_xscale,image_yscale,image_angle,clothing[0,1],image_alpha) //shirt draw_sprite_ext(clothing[1,0],image_index,x,y,image_xscale,image_yscale,image_angle,clothing[1,1],image_alpha) //pants draw_sprite_ext(clothing[2,0],image_index,x,y,image_xscale,image_yscale,image_angle,clothing[2,1],image_alpha) //shoes draw_sprite_ext(clothing[3,0],image_index,x,y,image_xscale,image_yscale,image_angle,clothing[3,1],image_alpha)
I did this with teams on a space game I tried and I essentiall set up s_shipname_base and s_shipname_color. The color sprite was usually plain white or had bits of grey to make bits darker.

If you can get shaders to work that would be easier to do what you want to, and I bet it isnt even that hard to do. Using shaders you can probably check the color of a pixel and change it to be whatever color you want if it's equal or close enough to your desired color. Or even have a 'green screen' effect with that particular color.
最后由 Daynar 编辑于; 2015 年 11 月 2 日 下午 4:16
BOYCOTT S-T-E-A-M! 2015 年 11 月 4 日 下午 12:53 
Thank you both for the replies.



引用自 Daynar

Yeah I could do it with a grayscale version of what I want to have various colors and then just draw over it, or under it, the parts that I don't want to ever change colors. I had considered doing that but it would mean having to deal with objects that are two parts and having them animate together which I was trying to avoid in this project.

If it comes down to it I may do it that way or just leave it as I have it currently where the team colors are hard coded and using their own seperate object / sprite.




引用自 BBX
This is done via shaders. Have and input shader read white and output based on your variable.

I can understand the concept, but its the execution I'm having trouble fully grasping. I'm used to the concept of replacing one specific color or even a general hue, governed by a tolerance, from working with art programs. I'm just having some trouble managing to wrap my head around making a shader to do that.


Actually, I had found a shader that does exactly what I need in every way. It was posted up in this thread at YoYo Games ( YoYo Games Forum [gmc.yoyogames.com]).

Sadly though, while the shader itself performs the exact functions I need I haven't been able to figure out how to use it properly in my project. I see the four arguments I need to pass into it, but trying to do it like it shows in the manual hasn't panned out for me.

There is a example project to demonstrate the shader in action even, but all that did was further confuse me.


For reference, here is the coding of the shader from that thread.
// // shColorReplaceBlend // // Replaces one color with another. Can replace // similar colors while preserving shading. // // colorIn color to replace (vec4) // colorOut replacement color (vec4) // colorTolerance HSVA tolerances (vec4) // blend 1.0 preserves shading of original, // 0.0 replaces color as-is (float) // // GMLscripts.com // varying vec2 v_vTexcoord; varying vec4 v_vColour; uniform vec4 colorIn; uniform vec4 colorOut; uniform vec4 colorTolerance; uniform float blend; vec3 rgb_to_hsv(vec3 col) { float H = 0.0; float S = 0.0; float V = 0.0; float M = max(col.r, max(col.g, col.b)); float m = min(col.r, min(col.g, col.b)); V = M; float C = M - m; if (C > 0.0) { if (M == col.r) H = mod( (col.g - col.b) / C, 6.0); if (M == col.g) H = (col.b - col.r) / C + 2.0; if (M == col.b) H = (col.r - col.g) / C + 4.0; H /= 6.0; S = C / V; } return vec3(H, S, V); } vec3 hsv_to_rgb(vec3 col) { float H = col.r; float S = col.g; float V = col.b; float C = V * S; H *= 6.0; float X = C * (1.0 - abs( mod(H, 2.0) - 1.0 )); float m = V - C; C += m; X += m; if (H < 1.0) return vec3(C, X, m); if (H < 2.0) return vec3(X, C, m); if (H < 3.0) return vec3(m, C, X); if (H < 4.0) return vec3(m, X, C); if (H < 5.0) return vec3(X, m, C); else return vec3(C, m, X); } void main() { vec4 colorPixel = texture2D( gm_BaseTexture, v_vTexcoord ); vec4 colorHSV = vec4( rgb_to_hsv( colorPixel.rgb ), colorPixel.a); vec4 colorInHSV = vec4( rgb_to_hsv( colorIn.rgb ), colorIn.a); vec4 colorDelta = colorHSV - colorInHSV; if (abs(colorDelta.r)>0.5) colorDelta.r -= sign(colorDelta.r); if ( all( lessThanEqual( abs(colorDelta), colorTolerance ) ) ) { vec4 colorOutHSV = vec4( rgb_to_hsv( colorOut.rgb ), colorOut.a); colorPixel = mix( colorOut, vec4 ( hsv_to_rgb( vec3( mod( colorOutHSV.r + colorDelta.r, 1.0 ), clamp( colorOutHSV.g + colorDelta.g, 0.0, 1.0 ), clamp( colorOutHSV.b + colorDelta.b, 0.0, 1.0 ) ) ), clamp( colorOut.a + colorDelta.a, 0.0, 1.0) ), blend ); } gl_FragColor = v_vColour * colorPixel; }
最后由 BOYCOTT S-T-E-A-M! 编辑于; 2015 年 11 月 4 日 下午 12:57
Daynar 2015 年 11 月 5 日 下午 2:25 
Hmm given you have a working shader getting to to work in your project shouldnt be too difficult. What is the code you have been using when you try getting it to work? It may be easier to 'debug' your code than provide another example since the developers demo didn't help.
最后由 Daynar 编辑于; 2015 年 11 月 5 日 下午 2:27
BOYCOTT S-T-E-A-M! 2015 年 11 月 6 日 上午 7:38 
I had dropped working on implementing the shader and moved on to the combat mechanics of my game so sadly I no longer have the exact code I had to try to use the shader.

Basically though, it was like this. The inputs for the shader are...
// colorIn color to replace (vec4) // colorOut replacement color (vec4) // colorTolerance HSVA tolerances (vec4) // blend 1.0 preserves shading of original, // 0.0 replaces color as-is (float)

I based my coding off what I saw in the manual in regards to shaders. In the create event of my controller object I had...
colorIn = shader_get_uniform(shColorReplaceBlend, "colorIn"); colorOut = shader_get_uniform(shColorReplaceBlend, "colorOut"); colorTolerance = shader_get_uniform(shColorReplaceBlend, "colorTolerance"); colorBlend = shader_get_uniform(shColorReplaceBlend, "blend");

Then in the draw event of my objects I had this...
shader_set(shColorReplaceBlend); shader_set_uniform_f(colorIn, 23,144,96); shader_set_uniform_f(colorOut, 53,144,96); shader_set_uniform_f(colorTolerance , 5,5,5); shader_set_uniform_f(colorBlend,1.0 ); draw_self(); shader_reset();


If I recall correctly, my error messages were in relation to the input I was putting in. I'm under the impression that I wasn't properly using the "shader_set_uniform_f" function, but never managded to figure out what I was doing wrong.
最后由 BOYCOTT S-T-E-A-M! 编辑于; 2015 年 11 月 6 日 上午 7:39
Daynar 2015 年 11 月 6 日 下午 2:26 
Well it looks like colorIn Out and Tolerance are all declared as vec4 in the shader itself, but you only give them 3 variables. Looking at his code the fourth variable is likely alpha.
BOYCOTT S-T-E-A-M! 2015 年 11 月 7 日 下午 12:02 
I had thought that the "blend" was being used as the alpha since its what determines if the replacement color is a flat color or if it takes on the original colors shading.

I'll give it a shot.
BOYCOTT S-T-E-A-M! 2015 年 11 月 7 日 下午 12:19 
I stand corrected on what I said earlier though about having an error message. I retried with the code I had in place when I had last tested it and I simply get no results. No errors, no messages actually. The project compiles and runs fine, but no changes to the objects sprites.

I tried adding in a fourth value for the Color In, Out, and Tolerance. Same results. No errors or anything, but no results.

Thanks for the suggestion to try though.

I'm trying to pick apart the example project for that shader still. Its a bit of a pain for me since the example was meant more to demonstrate the capabilities and limitations of the shader and not actually to teach you how to use it.

UPDATE - Seems the example project is using a slightly modified shader code than the one that its an example of. It also uses two additional scripts that seem to do something with setting the color and getting the rgba values for... well no idea really.

I managed to get the examples shader and script coding in my own project and not erroring out, but still not change what-so-ever in my objects sprites.
最后由 BOYCOTT S-T-E-A-M! 编辑于; 2015 年 11 月 7 日 下午 12:55
BOYCOTT S-T-E-A-M! 2015 年 11 月 7 日 下午 1:00 
Actually, finally got it "working."

I had stupidly been using my colorIn and colorOut as a Hue, Saturation, Value, and Alpha input. It seems the shader, at least the one from the example, wants RGBa input for the colorIn and ColorOut.

So managed to actually get results, quite close to what I wanted. Now I just need to actually pick everything apart and try to actually fully understand it so I can hopefully implement it in a way thats actually functional for my own project and not as "hackey" and butchered into place.

Thanks again for the responses. Helped to get my brain on track and at least get close enough to my goal that I think I can get it going in the end.
最后由 BOYCOTT S-T-E-A-M! 编辑于; 2015 年 11 月 7 日 下午 1:01
BOYCOTT S-T-E-A-M! 2018 年 7 月 15 日 下午 7:24 
Any particular reason for the necropost?

Seems kinda pointless to just bring back this old thread without making any form of contribution to it.
Daynar 2018 年 7 月 16 日 下午 4:45 
Well since it's necroed I think the best way is to use shaders to replace the color in parts of the sprite colored like a greenscreen, and use image blend as a backup if shaders arnt supported on the target platform.
< >
正在显示第 1 - 13 条,共 13 条留言
每页显示数: 1530 50

发帖日期: 2015 年 11 月 2 日 上午 12:50
回复数: 13