Converting X, Z coords to RGB using GLSL shaders
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
add a comment |
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
1
In the book of shaders, there iscolor = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it usesTWO_PIdefine, that is PI * 2, whereas in your code you use justPI: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
add a comment |
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
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
colors three.js glsl rgb
asked Nov 20 '18 at 3:30
S. AyeS. Aye
82
82
1
In the book of shaders, there iscolor = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it usesTWO_PIdefine, that is PI * 2, whereas in your code you use justPI: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
add a comment |
1
In the book of shaders, there iscolor = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it usesTWO_PIdefine, that is PI * 2, whereas in your code you use justPI: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
add a comment |
1 Answer
1
active
oldest
votes
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 30 '18 at 21:46
S. AyeS. Aye
82
82
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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

1
In the book of shaders, there is
color = hsb2rgb(vec3((angle/TWO_PI)+0.5,radius,1.0));, it usesTWO_PIdefine, that is PI * 2, whereas in your code you use justPI: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