luxe-colorpicker/materials/shaders.emsl
2021-11-27 12:55:32 +01:00

146 lines
4.1 KiB
Text

input View {
mat4 mvp,
mat4 proj,
mat4 proj_inverse,
mat4 view,
mat4 world, //geometry.world atm
float2 fov, //fov.x, fov.y
float2 resolution,
float4 target_region,
float4 target_region_size
}
input ColorWheel {
float outer_distance,
float inner_distance
}
input ColorTriangle {
float hue,
float size,
float value_gamma,
float saturation_gamma
}
input TransparencyGrid {
float2 grid_size,
float4 one_color,
float4 other_color
}
stage vertex vert(
input { View view },
vertex in { #0 float4 pos, #1 float4 color, #2 float2 uv },
fragment out { float4 color, float2 uv, float4 cs_pos})
{
out.color = in.color;
out.uv = in.uv;
stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0);
out.cs_pos = stage.pos;
}
stage fragment frag_color_ring(
input { ColorWheel wheel },
fragment in { float4 color, float2 uv })
{
float TAU = 6.2831853071795864769252867665590057683943387987502116419498891846;
float2 centered_coords = in.uv - 0.5;
float center_dist = length(centered_coords);
float change = dFdx(in.uv.x); //this assumes the object is unrotated and uniformly scaled
float alpha = clamp(min(center_dist - input.wheel.inner_distance, -center_dist + input.wheel.outer_distance - change) / change, 0.0, 1.0);
float angle = atan(centered_coords.y, centered_coords.x);
float normalized_angle = mod(angle / TAU + 0.25, 1.0);
float3 hue = hue2rgb(normalized_angle);
float4 color = float4(float3(hue), alpha);
if(color.a <= 0.0) {
discard;
return;
}
stage.color[0] = color;
}
stage fragment frag_color_triangle(
input { ColorTriangle triangle },
fragment in { float4 color, float2 uv })
{
float TAU = 6.283185307179586;
float cos30 = 0.866025403784438; //cos(30°)
float tan60 = 1.732050807568877;
float tan60sq = 3.0;
float sin30 = 0.5;
float size = input.triangle.size;
float2 centered_coords = in.uv - sin30;
float2 down = float2(0.0, -1.0);
float2 top_right = float2(cos30, sin30);
float2 top_left = float2(-cos30, sin30);
float down_dist = dot(down, centered_coords) + size;
float top_right_dist = dot(top_right, centered_coords) + size;
float top_left_dist = dot(top_left, centered_coords) + size;
float dist = min(min(top_right_dist, top_left_dist), down_dist);
float change = length(float2(dFdx(in.uv.x), dFdy(in.uv.y))); //this assumes the object is uniformly scaled (rotation is fine)
float alpha = clamp(dist/change, 0.0, 1.0);
float hue = input.triangle.hue;
float saturation = down_dist / (down_dist + top_right_dist);
saturation = pow(saturation, input.triangle.saturation_gamma);
float value = 1.0 - (top_left_dist / (size * tan60sq));
value = pow(value, input.triangle.value_gamma);
float3 color_rgb = hsv2rgb(float3(hue, saturation, value));
//color_rgb = float3(fract(saturation)); //debug
float4 color = float4(color_rgb, alpha);
if(color.a <= 0.0) {
discard;
return;
}
stage.color[0] = color;
}
stage fragment frag_transparency_grid(
input { TransparencyGrid trans_grid, View view },
fragment in { float4 color, float2 uv, float4 cs_pos })
{
float2 uv = in.cs_pos.xy / in.cs_pos.w;
uv.x = uv.x * (input.view.resolution.x / input.view.resolution.y);
float2 grid = floor(uv * input.trans_grid.grid_size);
float3 grid_color = float3(0);
float grid_sum = grid.x + grid.y;
float grid_mod = mod(grid_sum, 2.0);
if(grid_mod == 0.0){
grid_color = input.trans_grid.one_color.rgb;
} else {
grid_color = input.trans_grid.other_color.rgb;
}
stage.color[0] = float4(grid_color, 1.0 - in.color.a);
}
float3 hsv2rgb(float3 hsv){
float3 rgb = hue2rgb(hsv.x); //apply hue
rgb = mix(float3(1.0), rgb, hsv.y); //apply saturation
rgb = rgb * hsv.z; //apply value
return rgb;
}
float3 hue2rgb(float hue) {
hue = fract(hue); //only use fractional part
float r = abs(hue * 6.0 - 3.0) - 1.0; //red
float g = 2.0 - abs(hue * 6.0 - 2.0); //green
float b = 2.0 - abs(hue * 6.0 - 4.0); //blue
float3 rgb = float3(r,g,b); //combine components
rgb = clamp(rgb, 0.0, 1.0); //clamp between 0 and 1
return rgb;
}