gpt4 book ai didi

glsl - 在片段着色器中创建渐变颜色

转载 作者:行者123 更新时间:2023-12-01 07:17:37 24 4
gpt4 key购买 nike

我正在尝试像设计应用程序(例如 Photoshop)那样实现渐变色,但无法获得我想要的确切结果。

我的着色器创建了非常漂亮的“渐变”,但还包含与我想要切换的颜色不同的其他颜色。

它看起来不错,但是,我的目标是稍后添加混合功能并制作一种颜色校正着色器。但首先我必须得到正确的颜色。

这是我的片段着色器
http://player.thebookofshaders.com/?log=171119111216

uniform vec2 u_resolution;

void main() {

vec2 st = gl_FragCoord.xy/u_resolution.xy;

vec3 color1 = vec3(1.9,0.55,0);
vec3 color2 = vec3(0.226,0.000,0.615);

float mixValue = distance(st,vec2(0,1));
vec3 color = mix(color1,color2,mixValue);

gl_FragColor = vec4(color,mixValue);
}

这里是 comparison of the results in shader and design apps

提前致谢..

最佳答案

仅针对您的问题标题,您可能还想考虑在其他色彩空间中进行混合。您的代码在 RGB 空间中混合,但在不同的空间中会得到不同的结果。

例子



const gl = document.createElement("canvas").getContext("webgl");
gl.canvas.width = 100;
gl.canvas.height = 100;
gl.viewport(0, 0, 100, 100);

const vsrc = `
void main() {
gl_PointSize = 100.0;
gl_Position = vec4(0, 0, 0, 1);
}
`;
const fRGB = `
precision mediump float;

uniform vec3 color1;
uniform vec3 color2;

void main() {
vec2 st = gl_PointCoord;
float mixValue = distance(st, vec2(0, 1));

vec3 color = mix(color1, color2, mixValue);

gl_FragColor = vec4(color, 1);
}
`;
const fHSV = `
precision mediump float;

uniform vec3 color1;
uniform vec3 color2;

// from: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl

vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c) {
c = vec3(c.x, clamp(c.yz, 0.0, 1.0));
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
vec2 st = gl_PointCoord;
float mixValue = distance(st, vec2(0, 1));

vec3 hsv1 = rgb2hsv(color1);
vec3 hsv2 = rgb2hsv(color2);

// mix hue in toward closest direction
float hue = (mod(mod((hsv2.x - hsv1.x), 1.) + 1.5, 1.) - 0.5) * mixValue + hsv1.x;
vec3 hsv = vec3(hue, mix(hsv1.yz, hsv2.yz, mixValue));

vec3 color = hsv2rgb(hsv);

gl_FragColor = vec4(color, 1);
}

`;

const fHSL = `
precision mediump float;

uniform vec3 color1;
uniform vec3 color2;

const float Epsilon = 1e-10;

vec3 rgb2hcv(in vec3 RGB)
{
// Based on work by Sam Hocevar and Emil Persson
vec4 P = lerp(vec4(RGB.bg, -1.0, 2.0/3.0), vec4(RGB.gb, 0.0, -1.0/3.0), step(RGB.b, RGB.g));
vec4 Q = mix(vec4(P.xyw, RGB.r), vec4(RGB.r, P.yzx), step(P.x, RGB.r));
float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6. * C + Epsilon) + Q.z);
return vec3(H, C, Q.x);
}

vec3 rgb2hsl(in vec3 RGB)
{
vec3 HCV = rgb2hcv(RGB);
float L = HCV.z - HCV.y * 0.5;
float S = HCV.y / (1 - abs(L * 2. - 1.) + Epsilon);
return vec3(HCV.x, S, L);
}

vec3 hsl2rgb(vec3 c)
{
c = vec3(fract(c.x), clamp(c.yz, 0.0, 1.0));
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);
return c.z + c.y * (rgb - 0.5) * (1.0 - abs(2.0 * c.z - 1.0));
}

void main() {
vec2 st = gl_PointCoord;
float mixValue = distance(st, vec2(0, 1));

vec3 hsl1 = rgb2hsl(color1);
vec3 hsl2 = rgb2hsl(color2);

// mix hue in toward closest direction
float hue = (mod(mod((hsl2.x - hsl1.x), 1.) + 1.5, 1.) - 0.5) * mixValue + hsl1.x;
vec3 hsl = vec3(hue, mix(hsl1.yz, hsl2.yz, mixValue));

vec3 color = hsl2rgb(hsv);

gl_FragColor = vec4(color, 1);
}
`;

const fLAB = `
precision mediump float;

uniform vec3 color1;
uniform vec3 color2;

// from: https://code.google.com/archive/p/flowabs/source

vec3 rgb2xyz( vec3 c ) {
vec3 tmp;
tmp.x = ( c.r > 0.04045 ) ? pow( ( c.r + 0.055 ) / 1.055, 2.4 ) : c.r / 12.92;
tmp.y = ( c.g > 0.04045 ) ? pow( ( c.g + 0.055 ) / 1.055, 2.4 ) : c.g / 12.92,
tmp.z = ( c.b > 0.04045 ) ? pow( ( c.b + 0.055 ) / 1.055, 2.4 ) : c.b / 12.92;
return 100.0 * tmp *
mat3( 0.4124, 0.3576, 0.1805,
0.2126, 0.7152, 0.0722,
0.0193, 0.1192, 0.9505 );
}

vec3 xyz2lab( vec3 c ) {
vec3 n = c / vec3( 95.047, 100, 108.883 );
vec3 v;
v.x = ( n.x > 0.008856 ) ? pow( n.x, 1.0 / 3.0 ) : ( 7.787 * n.x ) + ( 16.0 / 116.0 );
v.y = ( n.y > 0.008856 ) ? pow( n.y, 1.0 / 3.0 ) : ( 7.787 * n.y ) + ( 16.0 / 116.0 );
v.z = ( n.z > 0.008856 ) ? pow( n.z, 1.0 / 3.0 ) : ( 7.787 * n.z ) + ( 16.0 / 116.0 );
return vec3(( 116.0 * v.y ) - 16.0, 500.0 * ( v.x - v.y ), 200.0 * ( v.y - v.z ));
}

vec3 rgb2lab(vec3 c) {
vec3 lab = xyz2lab( rgb2xyz( c ) );
return vec3( lab.x / 100.0, 0.5 + 0.5 * ( lab.y / 127.0 ), 0.5 + 0.5 * ( lab.z / 127.0 ));
}


vec3 lab2xyz( vec3 c ) {
float fy = ( c.x + 16.0 ) / 116.0;
float fx = c.y / 500.0 + fy;
float fz = fy - c.z / 200.0;
return vec3(
95.047 * (( fx > 0.206897 ) ? fx * fx * fx : ( fx - 16.0 / 116.0 ) / 7.787),
100.000 * (( fy > 0.206897 ) ? fy * fy * fy : ( fy - 16.0 / 116.0 ) / 7.787),
108.883 * (( fz > 0.206897 ) ? fz * fz * fz : ( fz - 16.0 / 116.0 ) / 7.787)
);
}

vec3 xyz2rgb( vec3 c ) {
vec3 v = c / 100.0 * mat3(
3.2406, -1.5372, -0.4986,
-0.9689, 1.8758, 0.0415,
0.0557, -0.2040, 1.0570
);
vec3 r;
r.x = ( v.r > 0.0031308 ) ? (( 1.055 * pow( v.r, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.r;
r.y = ( v.g > 0.0031308 ) ? (( 1.055 * pow( v.g, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.g;
r.z = ( v.b > 0.0031308 ) ? (( 1.055 * pow( v.b, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.b;
return r;
}

vec3 lab2rgb(vec3 c) {
return xyz2rgb( lab2xyz( vec3(100.0 * c.x, 2.0 * 127.0 * (c.y - 0.5), 2.0 * 127.0 * (c.z - 0.5)) ) );
}

void main() {
vec2 st = gl_PointCoord;
float mixValue = distance(st, vec2(0, 1));

vec3 lab1 = rgb2lab(color1);
vec3 lab2 = rgb2lab(color2);

vec3 lab = mix(lab1, lab2, mixValue);

vec3 color = lab2rgb(lab);

gl_FragColor = vec4(color, 1);
}
`;

function draw(gl, shaders, color1, color2, label) {
const programInfo = twgl.createProgramInfo(gl, shaders);
gl.useProgram(programInfo.program);
twgl.setUniforms(programInfo, {
color1: color1,
color2: color2,
});
gl.drawArrays(gl.POINTS, 0, 1);
const div = document.createElement("div");
const img = new Image();
img.src = gl.canvas.toDataURL();
div.appendChild(img);
const inner = document.createElement("span");
inner.textContent = label;
div.appendChild(inner);
document.body.appendChild(div);
}

const color1 = [1.0, 0.55, 0];
const color2 = [0.226, 0.000, 0.615];

draw(gl, [vsrc, fRGB], color1, color2, "rgb");
draw(gl, [vsrc, fHSV], color1, color2, "hsv");
draw(gl, [vsrc, fHSV], color1, color2, "hsl");
draw(gl, [vsrc, fLAB], color1, color2, "lab");
img { border: 1px solid black; margin: 2px; }
span { display: block; }
div { display: inline-block; text-align: center; }
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>


我还建议在渐变纹理中传递您的颜色。 Nx1 纹理和使用
color = texture2D(
rampTexture,
vec2((mixValue * (rampWidth - 1.) + .5) / rampWidth, 0.5)).rgb;

然后,您可以轻松地混合 2 种颜色、3 种颜色、20 种颜色。您也可以通过重复颜色等来分隔颜色。

例子:



const gl = document.createElement("canvas").getContext("webgl");
gl.canvas.width = 100;
gl.canvas.height = 100;
gl.viewport(0, 0, 100, 100);

const vsrc = `
void main() {
gl_PointSize = 100.0;
gl_Position = vec4(0, 0, 0, 1);
}
`;
const fsrc = `
precision mediump float;

uniform sampler2D rampTexture;
uniform float rampWidth;

void main() {
vec2 st = gl_PointCoord;
float mixValue = distance(st, vec2(0, 1));

vec3 color = texture2D(
rampTexture,
vec2((mixValue * (rampWidth - 1.) + .5) / rampWidth, 0.5)).rgb;

gl_FragColor = vec4(color, 1);
}
`;

const programInfo = twgl.createProgramInfo(gl, [vsrc, fsrc]);
gl.useProgram(programInfo.program);

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

function draw(gl, ramp, label) {
const width = ramp.length;
gl.bindTexture(gl.TEXTURE_2D, tex);
const level = 0;
const internalFormat = gl.RGB;
const height = 1;
const border = 0;
const format = gl.RGB;
const type = gl.UNSIGNED_BYTE;
const rampData = new Uint8Array([].concat(...ramp).map(v => v * 255));
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border,
format, type, rampData);
twgl.setUniforms(programInfo, {
rampTexture: tex,
rampWidth: width,
});
gl.drawArrays(gl.POINTS, 0, 1);
const div = document.createElement("div");
const img = new Image();
img.src = gl.canvas.toDataURL();
div.appendChild(img);
const inner = document.createElement("span");
inner.textContent = label;
div.appendChild(inner);
document.body.appendChild(div);
}

const color1 = [1.0, 0.55, 0];
const color2 = [0.226, 0.000, 0.615];
const r = [1, 0, 0];
const g = [0, 1, 0];
const b = [0, 0, 1];
const w = [1, 1, 1];

draw(gl, [color1, color2], "color1->color2");
draw(gl, [r, g], "red->green");
draw(gl, [r, g, b], "r->g->b");
draw(gl, [r, b, r, b, r], "r->b->r->b->r");
draw(gl, [g, b, b, b, g], "g->b->b->b->g");
img { border: 1px solid black; margin: 2px; }
span { display: block; }
div { display: inline-block; text-align: center; }
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>


注意:一维 256x1 纹理是 Chrome、Firefox 和 Android 渲染线性和径向渐变的方式。 See src

关于glsl - 在片段着色器中创建渐变颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47376499/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com