• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [Shaders] Circle Area *SOLVED*

Momfus

Member
Hi, I'm new in the use of shaders and i tried to make a shader on a sprite that make all the area inside a circle (center in the middle of the sprite) with a gray color and nothing outside of that circle.

I have a object ob_planet with a 300x300 sprite (is just a circle with different colors) and in the creat event i have this:

Code:
my_shader = shader_circle_gray;

uv = sprite_get_uvs(sprite_index, 0);

middle = 0;

middle[0] = (uv[0] + uv[2])/2;
middle[1] = (uv[1] + uv[3])/2;

In the draw event this:


Code:
shader_set(my_shader);

    var shader_params = shader_get_uniform(my_shader, "middle");
    shader_set_uniform_f_array(shader_params, middle );

    draw_self();

shader_reset();

Now, in the fragment of the shader


Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 middle; //middle of the sprite using uv

void main(){

    vec4 o_pixel = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);

    float red = o_pixel.r;
    float green = o_pixel.g;
    float blue = o_pixel.b;
    float alpha = o_pixel.a;
   
   //circle radio
    float radio = 0.1; 
   
   
    if(  "know if the actual pixel is in the circle area center in the middle" ){
   
        float gray= (red + green + blue ) / 3.0;
        red = gray;
        green = gray;
        blue = gray;
   
    }
   
   
   
    o_pixel = vec4(red, green, blue, alpha);
    gl_FragColor = o_pixel;  
   
}

I read the xorTutorials.com and thebookofshaders.com but i can't make a circle with a "r" radio that make the sprite gray inside the circle. Some help please?
 

jo-thijs

Member
Hi, I'm new in the use of shaders and i tried to make a shader on a sprite that make all the area inside a circle (center in the middle of the sprite) with a gray color and nothing outside of that circle.

I have a object ob_planet with a 300x300 sprite (is just a circle with different colors) and in the creat event i have this:

Code:
my_shader = shader_circle_gray;

uv = sprite_get_uvs(sprite_index, 0);

middle = 0;

middle[0] = (uv[0] + uv[2])/2;
middle[1] = (uv[1] + uv[3])/2;

In the draw event this:


Code:
shader_set(my_shader);

    var shader_params = shader_get_uniform(my_shader, "middle");
    shader_set_uniform_f_array(shader_params, middle );

    draw_self();

shader_reset();

Now, in the fragment of the shader


Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 middle; //middle of the sprite using uv

void main(){

    vec4 o_pixel = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);

    float red = o_pixel.r;
    float green = o_pixel.g;
    float blue = o_pixel.b;
    float alpha = o_pixel.a;
  
   //circle radio
    float radio = 0.1;
  
  
    if(  "know if the actual pixel is in the circle area center in the middle" ){
  
        float gray= (red + green + blue ) / 3.0;
        red = gray;
        green = gray;
        blue = gray;
  
    }
  
  
  
    o_pixel = vec4(red, green, blue, alpha);
    gl_FragColor = o_pixel; 
  
}

I read the xorTutorials.com and thebookofshaders.com but i can't make a circle with a "r" radio that make the sprite gray inside the circle. Some help please?
Hi and welcome to the GMC!

It looks like you've almost got it implemented.
Just replace this:
Code:
"know if the actual pixel is in the circle area center in the middle"
with this:
Code:
length(v_vTexcoord - middle) < r
and define r (probably through another uniform float variable).
 

Momfus

Member
Hi and welcome to the GMC!

It looks like you've almost got it implemented.
Just replace this:
Code:
"know if the actual pixel is in the circle area center in the middle"
with this:
Code:
length(v_vTexcoord - middle) < r
and define r (probably through another uniform float variable).


Firt of all: thanks for the welcome.

I replace with that but the problem is that v_vTexcoord is a vec2 (like middle) but the variable "radio" (with the valor of 0.1 ) is only a float

Code that a replace:

Code:
float radio = 0.1; 
   
   
    if( ( v_vTexcoord - middle ) < radio ){
   
        float gris = (red + green + blue ) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
   
    }

The erro said:
In Shader shader_circle_gray at line 23 : '<' : wrong operand types no operation '<' exists that takes a left-hand operand of type '2-component vector of float' and a right operand of type 'float' (or there is no acceptable conversion)

Also, that would make a rectangle and not a circle :/
 

jo-thijs

Member
Firt of all: thanks for the welcome.

I replace with that but the problem is that v_vTexcoord is a vec2 (like middle) but the variable "radio" (with the valor of 0.1 ) is only a float

Code that a replace:

Code:
float radio = 0.1;
  
  
    if( ( v_vTexcoord - middle ) < radio ){
  
        float gris = (red + green + blue ) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
  
    }

The erro said:
In Shader shader_circle_gray at line 23 : '<' : wrong operand types no operation '<' exists that takes a left-hand operand of type '2-component vector of float' and a right operand of type 'float' (or there is no acceptable conversion)

Also, that would make a rectangle and not a circle :/
You forgot to apply the function length.
 

Momfus

Member
You forgot to apply the function length.
You are right...but don't work :/

I know the calculate that i have to make is more complex but i can figure it out with shaders.

I try with

Code:
float radio = 0.5;
   
    if( abs( length(v_vTexcoord - middle) ) < radio ){
   
        float gris = (red + green + blue) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
   
    }
And without "abs" and different value in radio


Code:
float radio = 0.1;
   
    if( length(v_vTexcoord - middle)  < radio ){
   
        float gris = (red + green + blue) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
   
    }
But i don't see any change. I also tried to implement the code that show me the web page TheBookOfShaders.com (chapter: shapes) but i don`t know what i have to remplace (with the use of a sprite) the line "vec2 st = gl_FragCoord.xy/u_resolution.xy;"

The code that i see there is this
Code:
uniform vec2 u_resolution; //I know that this is the screen resolution but i want this in a sprite

float circle(in vec2 _st, in float _radius){
    vec2 dist = _st-vec2(0.5);
    return 1.-smoothstep(_radius-(_radius*0.01),
                         _radius+(_radius*0.01),
                         dot(dist,dist)*4.0);
}

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
   
    vec3 color = vec3(circle(st,0.9));
 

jo-thijs

Member
You are right...but don't work :/

I know the calculate that i have to make is more complex but i can figure it out with shaders.

I try with

Code:
float radio = 0.5;
  
    if( abs( length(v_vTexcoord - middle) ) < radio ){
  
        float gris = (red + green + blue) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
  
    }
And without "abs" and different value in radio


Code:
float radio = 0.1;
  
    if( length(v_vTexcoord - middle)  < radio ){
  
        float gris = (red + green + blue) / 3.0;
        red = gris;
        green = gris;
        blue = gris;
  
    }
But i don't see any change. I also tried to implement the code that show me the web page TheBookOfShaders.com (chapter: shapes) but i don`t know what i have to remplace (with the use of a sprite) the line "vec2 st = gl_FragCoord.xy/u_resolution.xy;"

The code that i see there is this
Code:
uniform vec2 u_resolution; //I know that this is the screen resolution but i want this in a sprite

float circle(in vec2 _st, in float _radius){
    vec2 dist = _st-vec2(0.5);
    return 1.-smoothstep(_radius-(_radius*0.01),
                         _radius+(_radius*0.01),
                         dot(dist,dist)*4.0);
}

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
  
    vec3 color = vec3(circle(st,0.9));
0.5 and 0.1 are very likely way too high values.
You should have radio be a uniform float and then add tis to the create event of your object:
Code:
radius = min(uv[2] - uv[0], uv[3] - uv[1]);
And set the uniform float radio to the value radius in the draw event.
 

Momfus

Member
0.5 and 0.1 are very likely way too high values.
You should have radio be a uniform float and then add tis to the create event of your object:
Code:
radius = min(uv[2] - uv[0], uv[3] - uv[1]);
And set the uniform float radio to the value radius in the draw event.

You are right! I try that and a radius = 0.05 and works...but draw me an elipse and not a circle. Some reason why?

PS: The planet ir the pink one in the middle
 

Attachments

jo-thijs

Member
You are right! I try that and a radius = 0.05 and works...but draw me an elipse and not a circle. Some reason why?

PS: The planet ir the pink one in the middle
You might have to use a uniform vec2 scale instead of a uniform float radio and then use this instead of radius in the create event:
Code:
scale[0] = 2 / (uv[2] - uv[0]);
scale[1] = 2 / (uv[3] - uv[1]);
and then use this in your shader:
Code:
    if( length((v_vTexcoord - middle) * scale)  < radio ){
where radio is a value like 1 or 0.5.
 

Momfus

Member
I figure it out!!!!!

The problem is that my sprite is 300x300 but the horizontal is less than the hight (is not a perfect circle) so if I restrict that all the hight and width of the sprite have to be use...works the first solution.

I made the other solution that you propuse, i that works too without the restriction that i said before....my question now is "why?" and why you use in the scale array the two divided by something (in other words...why two?)

scale[0] = 2 / (uv[2] - uv[0] ) ;

it like

scale[0] = 2 / ( "the right coordinate of the sprite in the texture pages minus the left coordinates")


it's because the corners without the alpha are not pow by 2 o something like that?

Your a master...that works and I apreciate that, but i need to know the "why?" thing jaja
 

jo-thijs

Member
I figure it out!!!!!

The problem is that my sprite is 300x300 but the horizontal is less than the hight (is not a perfect circle) so if I restrict that all the hight and width of the sprite have to be use...works the first solution.

I made the other solution that you propuse, i that works too without the restriction that i said before....my question now is "why?" and why you use in the scale array the two divided by something (in other words...why two?)

scale[0] = 2 / (uv[2] - uv[0] ) ;

it like

scale[0] = 2 / ( "the right coordinate of the sprite in the texture pages minus the left coordinates")


it's because the corners without the alpha are not pow by 2 o something like that?

Your a master...that works and I apreciate that, but i need to know the "why?" thing jaja
The uv coordinates you're working with are coordinates on the texture page.
You can see these pages in the global game settings, when you go to the graphics tab of the windows tab.
Multiple images are grouped together there.
Empty space of images are not necessarily included in the texture pages.
I guess that might affect the uv coordinates you're working with so that my last solution acts as though there was no empty space.

The 2 in the scale array was just so that "radio" would actually signify the radius with respect to the image dimensions, rather than the diameter.
You can work with 1 instead of 2 just fine, but you'll have to divide radio by 2 then as well.
 

Momfus

Member
asdas25
The uv coordinates you're working with are coordinates on the texture page.
You can see these pages in the global game settings, when you go to the graphics tab of the windows tab.
Multiple images are grouped together there.
Empty space of images are not necessarily included in the texture pages.
I guess that might affect the uv coordinates you're working with so that my last solution acts as though there was no empty space.

The 2 in the scale array was just so that "radio" would actually signify the radius with respect to the image dimensions, rather than the diameter.
You can work with 1 instead of 2 just fine, but you'll have to divide radio by 2 then as well.

Thanks...with the texture page, if a have different groups of textures in my games that i load ...i have to make some changes there so GMS know what texture pages is located or is make automatically?

I made an example where i have 3 sprites onliny...if I have more, there is any chance that draw pixels of other sprite or i don't have to worry about it?

Sorry for the questions....i'm new with shaders, and i really read a lot before ask here but the game maker manual have explain very little that things (and i read the tech blog too).

I will mark this like solve anyway because now i can make it.
 

jo-thijs

Member
asdas25



Thanks...with the texture page, if a have different groups of textures in my games that i load ...i have to make some changes there so GMS know what texture pages is located or is make automatically?

I made an example where i have 3 sprites onliny...if I have more, there is any chance that draw pixels of other sprite or i don't have to worry about it?

Sorry for the questions....i'm new with shaders, and i really read a lot before ask here but the game maker manual have explain very little that things (and i read the tech blog too).

I will mark this like solve anyway because now i can make it.
You normally shouldn't worry about what texture page is used, I just mentioned it to show what coordinate system is used
and why the radius needs to be so small and why uv coordinates make sense to use here.

Things should be dealt with so that you don't have to worry about drawing pixels of other sprites.
I should do some tests to be certain how it works though...

Also, questions are no problem, that's what the GMC is for!
 

Momfus

Member
You normally shouldn't worry about what texture page is used, I just mentioned it to show what coordinate system is used
and why the radius needs to be so small and why uv coordinates make sense to use here.

Things should be dealt with so that you don't have to worry about drawing pixels of other sprites.
I should do some tests to be certain how it works though...

Also, questions are no problem, that's what the GMC is for!

Thanks a lot!!! Really...now i can continue with the project and the best of all...i have a new skill to use in others projects. I can also make a little border in the gray circle.

Thanks again!
 
Top