| |
|
// MMJ's Cel Shader - v1.02
|
//
|
// ----------------------------------------------------------------
|
// Special thanks go out to Maruke for his CComic shader,
|
// and for allowing me to release this shader based upon his work.
|
// ----------------------------------------------------------------
|
//
|
// Shader Level settings will change the "mode" used
|
//
|
// 1 - Pencil Mode
|
// 2 - 1/3 Strength
|
// 3 - 2/3 Strength
|
// 4 - Full Strength
|
//
|
// -----------
|
// MegaManJuno
|
|
uniform sampler2D OGL2Texture;
|
uniform vec4 OGL2Param;
|
|
vec3 RGB2HSL(in vec3 cRGB) {
|
float vH, vS, vL, cR, cG, cB, vMin, vMax, dMax, dR, dG, dB;
|
|
cR = cRGB[0]; cG = cRGB[1]; cB = cRGB[2];
|
|
vMin = min(min(cR, cG), cB); vMax = max(max(cR, cG), cB);
|
dMax = vMax - vMin;
|
|
vL = (vMax + vMin) / 2.0;
|
|
// gray, no chroma
|
if(dMax == 0.0) {
|
vH = 0.0; vS = 0.0;
|
|
// chromatic data
|
} else {
|
if(vL < 0.5) { vS = dMax / (vMax + vMin); }
|
else { vS = dMax / (2.0 - vMax - vMin); }
|
|
dR = (((vMax - cR) / 6.0) + (dMax / 2.0)) / dMax;
|
dG = (((vMax - cG) / 6.0) + (dMax / 2.0)) / dMax;
|
dB = (((vMax - cB) / 6.0) + (dMax / 2.0)) / dMax;
|
|
if (cR >= vMax) { vH = dB - dG; }
|
else if(cG >= vMax) { vH = (1.0 / 3.0) + dR - dB; }
|
else if(cB >= vMax) { vH = (2.0 / 3.0) + dG - dR; }
|
|
if (vH < 0.0) { vH += 1.0; }
|
else if(vH > 1.0) { vH -= 1.0; }
|
}
|
return vec3(vH, vS, vL);
|
}
|
|
float Hue2RGB(in float v1, in float v2, in float vH) {
|
float v3;
|
|
if (vH < 0.0) { vH += 1.0; }
|
else if(vH > 1.0) { vH -= 1.0; }
|
|
if ((6.0 * vH) < 1.0) { v3 = v1 + (v2 - v1) * 6.0 * vH; }
|
else if((2.0 * vH) < 1.0) { v3 = v2; }
|
else if((3.0 * vH) < 2.0) { v3 = v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6.0; }
|
else { v3 = v1; }
|
|
return v3;
|
}
|
|
vec3 HSL2RGB(in vec3 vHSL) {
|
float cR, cG, cB, v1, v2;
|
|
if(vHSL[1] == 0.0) {
|
cR = vHSL[2]; cG = vHSL[2]; cB = vHSL[2];
|
|
} else {
|
if(vHSL[2] < 0.5) { v2 = vHSL[2] * (1.0 + vHSL[1] ); }
|
else { v2 = (vHSL[2] + vHSL[1] ) - (vHSL[1] * vHSL[2] ); }
|
|
v1 = 2.0 * vHSL[2] - v2;
|
|
cR = Hue2RGB(v1, v2, vHSL[0] + (1.0 / 3.0));
|
cG = Hue2RGB(v1, v2, vHSL[0] );
|
cB = Hue2RGB(v1, v2, vHSL[0] - (1.0 / 3.0));
|
}
|
return vec3(cR, cG, cB);
|
}
|
|
vec3 colorAdjust(in vec3 cRGB) {
|
vec3 cHSL;
|
float cr, sl, ml, ms, aw, ab;
|
|
cHSL = RGB2HSL(cRGB);
|
|
// absolute white level cutoff
|
aw = 0.9675; // default: 0.9675
|
|
// absolute black level cutoff
|
ab = 0.0325; // default: 0.0325
|
|
// number of shading levels (not counting absolute white and black levels)
|
sl = 7.0; // default: 7.0
|
|
// color range per shading level
|
cr = 1.0 / sl; // default: 1.0 / sl
|
|
// modification value for color adjustment
|
ml = mod(cHSL[2], cr); // default: mod(cHSL[2], cr)
|
|
// saturation modifier
|
ms = 1.2; // default: 1.2
|
|
// normal modes
|
if(OGL2Param.z > 0.0) {
|
if (cHSL[2] > aw) { cHSL[1] = 1.0; cHSL[2] = 1.0; }
|
else if(cHSL[2] > ab) { cHSL[1] *= ms; cHSL[2] += ((cr * (cHSL[2] + 0.6)) - ml); }
|
else { cHSL[1] = 0.0; cHSL[2] = 0.0; }
|
cHSL[2] = clamp(cHSL[2], float(int(cHSL[2] / cr) - 1) * cr, float(int(cHSL[2] / cr) + 1) * cr);
|
cRGB = HSL2RGB(cHSL);
|
|
// pencil mode
|
} else {
|
if (cHSL[2] + 0.2 > aw) { cRGB = vec3(1.0); }
|
else if(cHSL[2] > ab) { cRGB = vec3(cHSL[2] + ((cr * (cHSL[2] + 0.65)) - ml + 0.2)); }
|
else { cRGB = vec3(0.2); }
|
}
|
return cRGB;
|
}
|
|
void main(void) {
|
vec3 h, hz, o, c0, c2, c4, c6, c8, c9, cz, c1, c3, c5, c7;
|
float i, k, kz, mo;
|
|
// outline modifier
|
mo = 0.2; // default: mo = 0.2
|
|
c0 = texture2D(OGL2Texture, gl_TexCoord[3].xy).rgb;
|
c1 = texture2D(OGL2Texture, gl_TexCoord[2].xy).rgb;
|
c2 = texture2D(OGL2Texture, gl_TexCoord[3].zy).rgb;
|
c3 = texture2D(OGL2Texture, gl_TexCoord[1].xy).rgb;
|
c4 = texture2D(OGL2Texture, gl_TexCoord[0].xy).rgb;
|
c5 = texture2D(OGL2Texture, gl_TexCoord[1].zw).rgb;
|
c6 = texture2D(OGL2Texture, gl_TexCoord[3].xw).rgb;
|
c7 = texture2D(OGL2Texture, gl_TexCoord[2].zw).rgb;
|
c8 = texture2D(OGL2Texture, gl_TexCoord[3].zw).rgb;
|
|
c9 = (c0 * 5.0 + c1 * 10.0 + c2 * 5.0 + c3 * 10.0 + c4 * 4.0 + c5 * 10.0 + c6 * 5.0 + c7 * 10.0 + c8 * 5.0) / 64.0;
|
|
o = vec3(1.0); h = vec3(0.05); hz = h; k = 0.01; kz = 0.0035;
|
|
cz = (c4 + h) / (dot(o, c4) + k);
|
|
hz = (cz - ((c0 + h) / (dot(o, c0) + k))); i = kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c1 + h) / (dot(o, c1) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c2 + h) / (dot(o, c2) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c3 + h) / (dot(o, c3) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c5 + h) / (dot(o, c5) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c6 + h) / (dot(o, c6) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c7 + h) / (dot(o, c7) + k))); i += kz / (dot(hz, hz) + kz);
|
hz = (cz - ((c8 + h) / (dot(o, c8) + k))); i += kz / (dot(hz, hz) + kz);
|
|
i /= 8.0;
|
|
if(OGL2Param.z < 2.0) {
|
if(OGL2Param.z == 0.0) { // Pencil Mode
|
c9 = colorAdjust(c9) * i;
|
if(c9.r < 0.2) { c9.rgb = vec3(0.2); }
|
gl_FragColor.rgb = c9;
|
|
} else { // 1/3 strength
|
if(i < mo) { i = mo; }
|
c9 = min(o, min(c9, c9 + dot(o, c9)));
|
gl_FragColor.rgb = mix(c4, colorAdjust(c9), 0.33) * i;
|
}
|
|
} else {
|
if(OGL2Param.z == 2.0) { // 2/3 strength
|
if(i < mo) { i = mo; }
|
c9 = min(o, min(c9, c9 + dot(o, c9)));
|
gl_FragColor.rgb = mix(c4, colorAdjust(c9), 0.67) * i;
|
|
} else { // Full strength
|
if(i < mo) { i = mo; }
|
c9 = min(o, min(c9, c9 + dot(o, c9)));
|
gl_FragColor.rgb = colorAdjust(c9) * i;
|
}
|
}
|
}
|
|