0

ScreenShot:

img

As you can see the pic above,I created the HSL color palette in iOS, and I draw central part with OpenGL shader,but it's rect, can we make it a circle, not crop, we need draw all color to a circle? I tried for a long time but all failed. Can you help me? Thanks a lot indeed!

Here is the code:

- (void)loadShaders {
// create shader program
program = glCreateProgram();

const GLchar *vertexProgram = "precision highp float; \n\
\n\
attribute vec4 position; \n\
varying vec2 uv; \n\
\n\
void main() \n\
{ \n\
gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, 0.0, 1.0); \n\
uv = position.xy; \n\
}";

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexProgram, NULL);
glCompileShader(vertexShader);
glAttachShader(program, vertexShader);

// https://gist.github.com/eieio/4109795
const GLchar *fragmentProgram = "precision highp float; \n\
varying vec2 uv; \n\
uniform float hue; \n\
vec3 hsb_to_rgb(float h, float s, float l) \n\
{ \n\
float c = l * s; \n\
h = mod((h * 6.0), 6.0); \n\
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0)); \n\
vec3 result; \n\
\n\
if (0.0 <= h && h < 1.0) { \n\
result = vec3(c, x, 0.0); \n\
} else if (1.0 <= h && h < 2.0) { \n\
result = vec3(x, c, 0.0); \n\
} else if (2.0 <= h && h < 3.0) { \n\
result = vec3(0.0, c, x); \n\
} else if (3.0 <= h && h < 4.0) { \n\
result = vec3(0.0, x, c); \n\
} else if (4.0 <= h && h < 5.0) { \n\
result = vec3(x, 0.0, c); \n\
} else if (5.0 <= h && h < 6.0) { \n\
result = vec3(c, 0.0, x); \n\
} else { \n\
result = vec3(0.0, 0.0, 0.0); \n\
} \n\
\n\
result.rgb += l - c; \n\
\n\
return result; \n\
} \n\
\n\
void main() \n\
{ \
gl_FragColor = vec4(hsb_to_rgb(hue, uv.x, uv.y), 1.0); \
}";

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentProgram, NULL);
glCompileShader(fragmentShader);
glAttachShader(program, fragmentShader);

// bind attribute locations
// this needs to be done prior to linking
glBindAttribLocation(program, ATTRIB_VERTEX, "position");

glLinkProgram(program);

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

}
genpfault
  • 51,148
  • 11
  • 85
  • 139
KittenYang
  • 11
  • 3

1 Answers1

0

I do not code for your platform but I do not see where or what are you rendering but I assuming single QUAD so no surprise you are seeing rectangle. If you do not want to add circular mesh then you can do this in fragment shader without change in rendering code.

So let assume your palette is centered around x0,y0 and have radiuses inner r0 and outer r1 so r0<r1.

  1. GL: render QUAD covering your palette disc
  2. Fragment: compute distance of fragment from palette center

    if not in range between inner and outer radius discard(); fragment.

    dd=(x-x0)*(x-x0)+(y-y0)*(y-y0);
    if ((dd<r0*r0)||(dd>r1*r1)) discard();
    
  3. Fragment: compute angle of fragment via atan(dy,dx)

    float ang=atan(y-y0,x-x0); // <-pi,+pi>
    
  4. Fragment: convert angle to RGB output fragment color

    so convert the ang range to what ever parameter you want to your palette (like hue and set the others to some default value) convert it to RGB and output it ... similar to these:

Spektre
  • 49,595
  • 11
  • 110
  • 380