Converting X, Z coords to RGB using GLSL shaders












0















I have a Three js scene that contains a 100x100 plane centred at the origin (ie. min coord: (-50,-50), max coord: (50,50)). I am trying to have the plane appear as a colour wheel by using the x and z coords in a custom glsl shader. Using this guide (see HSB in polar coordinates, towards the bottom of the page) I have gotten my
Shader Code with Three.js Scene
but it is not quite right.



I have played around tweaking all the variables that make sense to me, but as you can see in the screenshot the colours change twice as often as what they should. My math intuition says just divide the angle by 2 but when I tried that it was completely incorrect.



I know the solution is very simple but I have tried for a couple hours and I haven't got it.



How do I turn my shader that I currently have into one that makes exactly 1 full colour rotation in 2pi radians?



EDIT: here is the relevant shader code in plain text



varying vec3 vColor;
const float PI = 3.1415926535897932384626433832795;
uniform float delta;
uniform float scale;
uniform float size;

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main()
{
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
float r = 0.875;
float g = 0.875;
float b = 0.875;
if (worldPosition.y > 0.06 || worldPosition.y < -0.06) {
vec2 toCenter = vec2(0.5) - vec2((worldPosition.z+50.0)/100.0, (worldPosition.x+50.0)/100.0);
float angle = atan(worldPosition.z/worldPosition.x);
float radius = length(toCenter) * 2.0;
vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));
} else {
vColor = vec3(r,g,b);
}
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size * (scale/length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}









share|improve this question


















  • 1





    In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

    – prisoner849
    Nov 20 '18 at 13:16













  • I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

    – S. Aye
    Nov 20 '18 at 21:39
















0















I have a Three js scene that contains a 100x100 plane centred at the origin (ie. min coord: (-50,-50), max coord: (50,50)). I am trying to have the plane appear as a colour wheel by using the x and z coords in a custom glsl shader. Using this guide (see HSB in polar coordinates, towards the bottom of the page) I have gotten my
Shader Code with Three.js Scene
but it is not quite right.



I have played around tweaking all the variables that make sense to me, but as you can see in the screenshot the colours change twice as often as what they should. My math intuition says just divide the angle by 2 but when I tried that it was completely incorrect.



I know the solution is very simple but I have tried for a couple hours and I haven't got it.



How do I turn my shader that I currently have into one that makes exactly 1 full colour rotation in 2pi radians?



EDIT: here is the relevant shader code in plain text



varying vec3 vColor;
const float PI = 3.1415926535897932384626433832795;
uniform float delta;
uniform float scale;
uniform float size;

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main()
{
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
float r = 0.875;
float g = 0.875;
float b = 0.875;
if (worldPosition.y > 0.06 || worldPosition.y < -0.06) {
vec2 toCenter = vec2(0.5) - vec2((worldPosition.z+50.0)/100.0, (worldPosition.x+50.0)/100.0);
float angle = atan(worldPosition.z/worldPosition.x);
float radius = length(toCenter) * 2.0;
vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));
} else {
vColor = vec3(r,g,b);
}
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size * (scale/length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}









share|improve this question


















  • 1





    In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

    – prisoner849
    Nov 20 '18 at 13:16













  • I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

    – S. Aye
    Nov 20 '18 at 21:39














0












0








0


1






I have a Three js scene that contains a 100x100 plane centred at the origin (ie. min coord: (-50,-50), max coord: (50,50)). I am trying to have the plane appear as a colour wheel by using the x and z coords in a custom glsl shader. Using this guide (see HSB in polar coordinates, towards the bottom of the page) I have gotten my
Shader Code with Three.js Scene
but it is not quite right.



I have played around tweaking all the variables that make sense to me, but as you can see in the screenshot the colours change twice as often as what they should. My math intuition says just divide the angle by 2 but when I tried that it was completely incorrect.



I know the solution is very simple but I have tried for a couple hours and I haven't got it.



How do I turn my shader that I currently have into one that makes exactly 1 full colour rotation in 2pi radians?



EDIT: here is the relevant shader code in plain text



varying vec3 vColor;
const float PI = 3.1415926535897932384626433832795;
uniform float delta;
uniform float scale;
uniform float size;

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main()
{
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
float r = 0.875;
float g = 0.875;
float b = 0.875;
if (worldPosition.y > 0.06 || worldPosition.y < -0.06) {
vec2 toCenter = vec2(0.5) - vec2((worldPosition.z+50.0)/100.0, (worldPosition.x+50.0)/100.0);
float angle = atan(worldPosition.z/worldPosition.x);
float radius = length(toCenter) * 2.0;
vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));
} else {
vColor = vec3(r,g,b);
}
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size * (scale/length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}









share|improve this question














I have a Three js scene that contains a 100x100 plane centred at the origin (ie. min coord: (-50,-50), max coord: (50,50)). I am trying to have the plane appear as a colour wheel by using the x and z coords in a custom glsl shader. Using this guide (see HSB in polar coordinates, towards the bottom of the page) I have gotten my
Shader Code with Three.js Scene
but it is not quite right.



I have played around tweaking all the variables that make sense to me, but as you can see in the screenshot the colours change twice as often as what they should. My math intuition says just divide the angle by 2 but when I tried that it was completely incorrect.



I know the solution is very simple but I have tried for a couple hours and I haven't got it.



How do I turn my shader that I currently have into one that makes exactly 1 full colour rotation in 2pi radians?



EDIT: here is the relevant shader code in plain text



varying vec3 vColor;
const float PI = 3.1415926535897932384626433832795;
uniform float delta;
uniform float scale;
uniform float size;

vec3 hsb2rgb( in vec3 c ){
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
6.0)-3.0)-1.0,
0.0,
1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix( vec3(1.0), rgb, c.y);
}

void main()
{
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
float r = 0.875;
float g = 0.875;
float b = 0.875;
if (worldPosition.y > 0.06 || worldPosition.y < -0.06) {
vec2 toCenter = vec2(0.5) - vec2((worldPosition.z+50.0)/100.0, (worldPosition.x+50.0)/100.0);
float angle = atan(worldPosition.z/worldPosition.x);
float radius = length(toCenter) * 2.0;
vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));
} else {
vColor = vec3(r,g,b);
}
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = size * (scale/length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}






colors three.js glsl rgb






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 '18 at 3:30









S. AyeS. Aye

82




82








  • 1





    In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

    – prisoner849
    Nov 20 '18 at 13:16













  • I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

    – S. Aye
    Nov 20 '18 at 21:39














  • 1





    In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

    – prisoner849
    Nov 20 '18 at 13:16













  • I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

    – S. Aye
    Nov 20 '18 at 21:39








1




1





In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

– prisoner849
Nov 20 '18 at 13:16







In the book of shaders, there is color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it uses TWO_PI define, that is PI * 2, whereas in your code you use just PI: vColor = hsb2rgb(vec3((angle/(PI))+0.5,radius,1.0));.

– prisoner849
Nov 20 '18 at 13:16















I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

– S. Aye
Nov 20 '18 at 21:39





I know, I noticed that. When I try 2PI it is much worse though. there are no reddish hues everything is blue/green.

– S. Aye
Nov 20 '18 at 21:39












1 Answer
1






active

oldest

votes


















0














I have discovered that the guide I was following was incorrect. I wasn't thinking about my math properly but I now know what the problem was.



atan has a range from -PI/2 to PI/2 which only accounts for half of a circle. When worldPosition.x is negative atan will not return the correct angle since it is out of range of the function. The angle needs to be adjusted based on what quadrant it is in the plane.



Q1: do nothing
Q2: add PI to the angle
Q3: add PI to the angle
Q4: add 2PI to the angle



After this normalize the angle (divide by 2PI) then pass it to the hsb2rgb function.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385809%2fconverting-x-z-coords-to-rgb-using-glsl-shaders%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    I have discovered that the guide I was following was incorrect. I wasn't thinking about my math properly but I now know what the problem was.



    atan has a range from -PI/2 to PI/2 which only accounts for half of a circle. When worldPosition.x is negative atan will not return the correct angle since it is out of range of the function. The angle needs to be adjusted based on what quadrant it is in the plane.



    Q1: do nothing
    Q2: add PI to the angle
    Q3: add PI to the angle
    Q4: add 2PI to the angle



    After this normalize the angle (divide by 2PI) then pass it to the hsb2rgb function.






    share|improve this answer




























      0














      I have discovered that the guide I was following was incorrect. I wasn't thinking about my math properly but I now know what the problem was.



      atan has a range from -PI/2 to PI/2 which only accounts for half of a circle. When worldPosition.x is negative atan will not return the correct angle since it is out of range of the function. The angle needs to be adjusted based on what quadrant it is in the plane.



      Q1: do nothing
      Q2: add PI to the angle
      Q3: add PI to the angle
      Q4: add 2PI to the angle



      After this normalize the angle (divide by 2PI) then pass it to the hsb2rgb function.






      share|improve this answer


























        0












        0








        0







        I have discovered that the guide I was following was incorrect. I wasn't thinking about my math properly but I now know what the problem was.



        atan has a range from -PI/2 to PI/2 which only accounts for half of a circle. When worldPosition.x is negative atan will not return the correct angle since it is out of range of the function. The angle needs to be adjusted based on what quadrant it is in the plane.



        Q1: do nothing
        Q2: add PI to the angle
        Q3: add PI to the angle
        Q4: add 2PI to the angle



        After this normalize the angle (divide by 2PI) then pass it to the hsb2rgb function.






        share|improve this answer













        I have discovered that the guide I was following was incorrect. I wasn't thinking about my math properly but I now know what the problem was.



        atan has a range from -PI/2 to PI/2 which only accounts for half of a circle. When worldPosition.x is negative atan will not return the correct angle since it is out of range of the function. The angle needs to be adjusted based on what quadrant it is in the plane.



        Q1: do nothing
        Q2: add PI to the angle
        Q3: add PI to the angle
        Q4: add 2PI to the angle



        After this normalize the angle (divide by 2PI) then pass it to the hsb2rgb function.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 30 '18 at 21:46









        S. AyeS. Aye

        82




        82






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385809%2fconverting-x-z-coords-to-rgb-using-glsl-shaders%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            The term 'EXEC' is not recognized as the name of a cmdlet Powershell

            NPM command prompt closes immediately [closed]

            Error binding properties and functions in emscripten