pixiv, इलस्ट्रेटर और इलस्ट्रेशन में दिलचस्पी रखने वाले लोगों के लिए एक ऑनलाइन कम्यूनिटी सेवा है. इसकी मदद से, ये लोग अपने कॉन्टेंट के ज़रिए एक-दूसरे से बातचीत कर सकते हैं. इसकी मदद से, लोग अपने इलस्ट्रेशन पोस्ट कर सकते हैं. दुनिया भर में इसके 8.4 करोड़ से ज़्यादा उपयोगकर्ता हैं. साथ ही, मई 2023 तक इस पर 12 करोड़ से ज़्यादा कलाकृतियां पोस्ट की गई हैं.
pixiv Sketch, pixiv की ओर से उपलब्ध कराई जाने वाली सेवाओं में से एक है. इसका इस्तेमाल, वेबसाइट पर उंगलियों या स्टाइलस का इस्तेमाल करके आर्टवर्क बनाने के लिए किया जाता है. यह शानदार इलस्ट्रेशन बनाने के लिए कई तरह की सुविधाएं देता है. जैसे, कई तरह के ब्रश, लेयर, और बकेट पेंटिंग. साथ ही, यह लोगों को ड्रॉइंग की प्रोसेस को लाइव स्ट्रीम करने की सुविधा भी देता है.
इस केस स्टडी में, हम देखेंगे कि pixiv Sketch ने WebGL, WebAssembly, और WebRTC जैसी नई वेब प्लैटफ़ॉर्म सुविधाओं का इस्तेमाल करके, अपने वेब ऐप्लिकेशन की परफ़ॉर्मेंस और क्वालिटी को कैसे बेहतर बनाया.
वेब पर स्केचिंग ऐप्लिकेशन क्यों डेवलप करना चाहिए?
pixiv Sketch को पहली बार 2015 में वेब और iOS पर रिलीज़ किया गया था. वेब वर्शन के लिए, उनकी टारगेट ऑडियंस मुख्य रूप से डेस्कटॉप का इस्तेमाल करती थी. आज भी इलस्ट्रेशन कम्यूनिटी के लोग, डेस्कटॉप का सबसे ज़्यादा इस्तेमाल करते हैं.
डेस्कटॉप ऐप्लिकेशन के बजाय वेब वर्शन को डेवलप करने के लिए, pixiv ने ये दो मुख्य वजहें बताई हैं:
- Windows, Mac, Linux वगैरह के लिए ऐप्लिकेशन बनाना बहुत महंगा होता है. वेब ऐप्लिकेशन, डेस्कटॉप पर किसी भी ब्राउज़र पर काम करता है.
- वेब की पहुंच सभी प्लैटफ़ॉर्म पर सबसे ज़्यादा होती है. वेब, डेस्कटॉप और मोबाइल पर उपलब्ध है. साथ ही, यह हर ऑपरेटिंग सिस्टम पर काम करता है.
टेक्नोलॉजी
pixiv Sketch में, उपयोगकर्ताओं के लिए कई तरह के ब्रश उपलब्ध हैं. WebGL को अपनाने से पहले, सिर्फ़ एक तरह का ब्रश उपलब्ध था. ऐसा इसलिए, क्योंकि 2D कैनवस अलग-अलग ब्रश की जटिल बनावट को दिखाने के लिए बहुत सीमित था. जैसे, पेंसिल के खुरदुरे किनारे और स्केच के दबाव के हिसाब से चौड़ाई और रंग की तीव्रता में बदलाव.
WebGL का इस्तेमाल करके, अलग-अलग तरह के क्रिएटिव ब्रश
हालांकि, WebGL को अपनाने के बाद, वे ब्रश की बारीकियों में और ज़्यादा वैरायटी जोड़ पाए. साथ ही, उन्होंने उपलब्ध ब्रश की संख्या को सात तक बढ़ा दिया.

2D कैनवस कॉन्टेक्स्ट का इस्तेमाल करके, सिर्फ़ ऐसी लाइनें बनाई जा सकती थीं जिनका टेक्सचर सामान्य हो और चौड़ाई एक जैसी हो. जैसे, इस स्क्रीनशॉट में दिखाया गया है:

इन लाइनों को पाथ और स्ट्रोक बनाकर बनाया गया था. हालांकि, WebGL इन्हें पॉइंट स्प्राइट और शेडर का इस्तेमाल करके फिर से बनाता है. इन्हें कोड के इन सैंपल में दिखाया गया है
यहां दिए गए उदाहरण में, वर्टेक्स शेडर दिखाया गया है.
precision highp float;
attribute vec2 pos;
attribute float thicknessFactor;
attribute float opacityFactor;
uniform float pointSize;
varying float varyingOpacityFactor;
varying float hardness;
// Calculate hardness from actual point size
float calcHardness(float s) {
float h0 = .1 * (s - 1.);
float h1 = .01 * (s - 10.) + .6;
float h2 = .005 * (s - 30.) + .8;
float h3 = .001 * (s - 50.) + .9;
float h4 = .0002 * (s - 100.) + .95;
return min(h0, min(h1, min(h2, min(h3, h4))));
}
void main() {
float actualPointSize = pointSize * thicknessFactor;
varyingOpacityFactor = opacityFactor;
hardness = calcHardness(actualPointSize);
gl_Position = vec4(pos, 0., 1.);
gl_PointSize = actualPointSize;
}
यहां फ़्रैगमेंट शेडर के लिए सैंपल कोड का उदाहरण दिया गया है.
precision highp float;
const float strength = .8;
const float exponent = 5.;
uniform vec4 color;
varying float hardness;
varying float varyingOpacityFactor;
float fallOff(const float r) {
// w is for width
float w = 1. - hardness;
if (w < 0.01) {
return 1.;
} else {
return min(1., pow(1. - (r - hardness) / w, exponent));
}
}
void main() {
vec2 texCoord = (gl_PointCoord - .5) * 2.;
float r = length(texCoord);
if (r > 1.) {
discard;
}
float brushAlpha = fallOff(r) * varyingOpacityFactor * strength * color.a;
gl_FragColor = vec4(color.rgb, brushAlpha);
}
पॉइंट स्प्राइट का इस्तेमाल करने से, ड्राइंग के दबाव के हिसाब से लाइन की मोटाई और शेडिंग में बदलाव करना आसान हो जाता है. इससे, इन जैसी मोटी और पतली लाइनों को आसानी से दिखाया जा सकता है:


इसके अलावा, पॉइंट स्प्राइट का इस्तेमाल करने वाले ऐप्लिकेशन अब अलग-अलग शेडर का इस्तेमाल करके टेक्सचर जोड़ सकते हैं. इससे पेंसिल और फ़ेल्ट-टिप पेन जैसे टेक्सचर वाले ब्रश को बेहतर तरीके से दिखाया जा सकता है.
ब्राउज़र पर स्टाइलस इस्तेमाल करने की सुविधा
डिजिटल आर्टिस्ट के लिए, डिजिटल स्टाइलस का इस्तेमाल करना बेहद लोकप्रिय हो गया है. मॉडर्न ब्राउज़र, PointerEvent API के साथ काम करते हैं. इससे उपयोगकर्ता अपने डिवाइस पर स्टाइलस का इस्तेमाल कर पाते हैं: PointerEvent.pressure का इस्तेमाल करके, पेन के दबाव को मेज़र करें. साथ ही, PointerEvent.tiltX और PointerEvent.tiltY का इस्तेमाल करके, डिवाइस के हिसाब से पेन के ऐंगल को मेज़र करें.
पॉइंट स्प्राइट की मदद से ब्रश स्ट्रोक करने के लिए, PointerEvent को इंटरपोलेट किया जाना चाहिए. साथ ही, इसे ज़्यादा जानकारी वाली इवेंट सीक्वेंस में बदला जाना चाहिए. PointerEvent में, स्टाइलस के ओरिएंटेशन को पोलर कोऑर्डिनेट के तौर पर पाया जा सकता है. हालांकि, pixiv Sketch इनका इस्तेमाल करने से पहले, इन्हें स्टाइलस के ओरिएंटेशन को दिखाने वाले वेक्टर में बदल देता है.
function getTiltAsVector(event: PointerEvent): [number, number, number] {
const u = Math.tan((event.tiltX / 180) * Math.PI);
const v = Math.tan((event.tiltY / 180) * Math.PI);
const z = Math.sqrt(1 / (u * u + v * v + 1));
const x = z * u;
const y = z * v;
return [x, y, z];
}
function handlePointerDown(event: PointerEvent) {
const position = [event.clientX, event.clientY];
const pressure = event.pressure;
const tilt = getTiltAsVector(event);
interpolateAndRender(position, pressure, tilt);
}
एक से ज़्यादा ड्रॉइंग लेयर
लेयर, डिजिटल ड्रॉइंग के सबसे यूनीक कॉन्सेप्ट में से एक हैं. इनकी मदद से, उपयोगकर्ता एक-दूसरे के ऊपर इलस्ट्रेशन के अलग-अलग हिस्से बना सकते हैं. साथ ही, लेयर के हिसाब से बदलाव कर सकते हैं. pixiv Sketch, लेयर के फ़ंक्शन उपलब्ध कराता है. ये फ़ंक्शन, डिजिटल ड्राइंग वाले अन्य ऐप्लिकेशन में भी उपलब्ध होते हैं.
आम तौर पर, लेयर लागू करने के लिए कई <canvas> एलिमेंट का इस्तेमाल किया जाता है. साथ ही, drawImage() और कंपोज़िटिंग ऑपरेशनों का इस्तेमाल किया जाता है. हालांकि, यह समस्या पैदा कर सकता है, क्योंकि 2D कैनवस कॉन्टेक्स्ट के साथ, CanvasRenderingContext2D.globalCompositeOperation कंपोज़िशन मोड का इस्तेमाल करने के अलावा कोई और विकल्प नहीं है. यह मोड पहले से तय होता है और इससे स्केलेबिलिटी काफ़ी हद तक सीमित हो जाती है. WebGL का इस्तेमाल करके और शेडर लिखकर, डेवलपर ऐसे कंपोज़िशन मोड का इस्तेमाल कर सकते हैं जो एपीआई के ज़रिए पहले से तय नहीं किए गए हैं. आने वाले समय में, pixiv Sketch में लेयर की सुविधा को WebGL का इस्तेमाल करके लागू किया जाएगा. इससे यह सुविधा ज़्यादा बेहतर तरीके से काम करेगी और इसे आसानी से इस्तेमाल किया जा सकेगा.
लेयर कंपोज़िशन के लिए सैंपल कोड यहां दिया गया है:
precision highp float;
uniform sampler2D baseTexture;
uniform sampler2D blendTexture;
uniform mediump float opacity;
varying highp vec2 uv;
// for normal mode
vec3 blend(const vec4 baseColor, const vec4 blendColor) {
return blendColor.rgb;
}
// for multiply mode
vec3 blend(const vec4 baseColor, const vec4 blendColor) {
return blendColor.rgb * blendColor.rgb;
}
void main()
{
vec4 blendColor = texture2D(blendTexture, uv);
vec4 baseColor = texture2D(baseTexture, uv);
blendColor.a *= opacity;
float a1 = baseColor.a * blendColor.a;
float a2 = baseColor.a * (1. - blendColor.a);
float a3 = (1. - baseColor.a) * blendColor.a;
float resultAlpha = a1 + a2 + a3;
const float epsilon = 0.001;
if (resultAlpha > epsilon) {
vec3 noAlphaResult = blend(baseColor, blendColor);
vec3 resultColor =
noAlphaResult * a1 + baseColor.rgb * a2 + blendColor.rgb * a3;
gl_FragColor = vec4(resultColor / resultAlpha, resultAlpha);
} else {
gl_FragColor = vec4(0);
}
}
बकेट फ़ंक्शन का इस्तेमाल करके, किसी बड़े हिस्से को पेंट करना
pixiv Sketch के iOS और Android ऐप्लिकेशन में, बकेट सुविधा पहले से उपलब्ध थी. हालांकि, वेब वर्शन में यह सुविधा उपलब्ध नहीं थी. बकेट फ़ंक्शन के ऐप्लिकेशन वर्शन को C++ में लागू किया गया था.
C++ में कोडबेस पहले से उपलब्ध होने की वजह से, pixiv Sketch ने वेब वर्शन में बकेट फ़ंक्शन लागू करने के लिए, Emscripten और asm.js का इस्तेमाल किया.
bfsQueue.push(startPoint);
while (!bfsQueue.empty()) {
Point point = bfsQueue.front();
bfsQueue.pop();
/* ... */
bfsQueue.push(anotherPoint);
}
asm.js का इस्तेमाल करने से, परफ़ॉर्मेंस को बेहतर बनाने में मदद मिली. प्योर JavaScript और asm.js के एक्ज़ीक्यूशन टाइम की तुलना करने पर पता चलता है कि asm.js का इस्तेमाल करने पर, एक्ज़ीक्यूशन टाइम 67% कम हो जाता है. WASM का इस्तेमाल करने पर, यह और भी बेहतर हो सकता है.
टेस्ट की जानकारी:
- कैसे: बकेट फ़ंक्शन का इस्तेमाल करके, 1180x800 पिक्सल के एरिया को पेंट करें
- टेस्ट डिवाइस: MacBook Pro (M1 Max)
लागू करने का समय:
- Pure JavaScript: 213.8 मि॰से॰
- asm.js: 70.3 मि॰से॰
Emscripten और asm.js का इस्तेमाल करके, pixiv Sketch ने बकेट सुविधा को सफलतापूर्वक रिलीज़ किया. इसके लिए, उसने प्लैटफ़ॉर्म के हिसाब से ऐप्लिकेशन के वर्शन के कोडबेस का फिर से इस्तेमाल किया.
ड्राइंग करते समय लाइव स्ट्रीम करना
pixiv Sketch, ड्राइंग करते समय लाइव स्ट्रीम करने की सुविधा देता है. इसके लिए, pixiv Sketch LIVE वेब ऐप्लिकेशन का इस्तेमाल किया जाता है. यह WebRTC API का इस्तेमाल करता है. इसमें getUserMedia() से मिला माइक्रोफ़ोन ऑडियो ट्रैक और <canvas> एलिमेंट से मिला MediaStream वीडियो ट्रैक शामिल होता है.
const canvasElement = document.querySelector('#DrawCanvas');
const framerate = 24;
const canvasStream = canvasElement.captureStream(framerate);
const videoStreamTrack = canvasStream.getVideoTracks()[0];
const audioStream = await navigator.mediaDevices.getUserMedia({
video: false,
audio: {},
});
const audioStreamTrack = audioStream.getAudioTracks()[0];
const stream = new MediaStream();
stream.addTrack(audioStreamTrack.clone());
stream.addTrack(videoStreamTrack.clone());
मीटिंग में सामने आए नतीजे
WebGL, WebAssembly, और WebRTC जैसे नए एपीआई की मदद से, वेब प्लैटफ़ॉर्म पर एक जटिल ऐप्लिकेशन बनाया जा सकता है. साथ ही, इसे किसी भी डिवाइस पर स्केल किया जा सकता है. इस केस स्टडी में इस्तेमाल की गई टेक्नोलॉजी के बारे में ज़्यादा जानने के लिए, यहां दिए गए लिंक पर जाएं:
- WebGL
- WebGL की जगह इस्तेमाल होने वाले WebGPU के बारे में भी जानें
- WebAssembly
- WebRTC
- जैपनीज़ भाषा में ओरिजिनल लेख