टाइपस्क्रिप्ट में वेबजीएल

टाइपस्क्रिप्ट में वेबजीएल

यह लेख टाइपस्क्रिप्ट में वेबजीएल की व्याख्या करता है।

हम वेबजीएल की अवधारणा, इसकी न्यूनतम कॉन्फ़िगरेशन, रेंडरिंग, एक्सटेंशन्स और क्लास डिज़ाइन को क्रमबद्ध रूप से उदाहरण कोड के साथ प्रस्तुत करेंगे।

YouTube Video

टाइपस्क्रिप्ट में वेबजीएल

WebGL एक लो-लेवल एपीआई है जो आपको ब्राउज़र में सीधे GPU को नियंत्रित करने की अनुमति देता है।

TypeScript का उपयोग करके, आप WebGL में टाइप सेफ़्टी, कोड कम्प्लीशन, और संरचित कोडिंग के माध्यम से 'इम्प्लीमेंटेशन गलतियों' को काफी हद तक कम कर सकते हैं।

टाइपस्क्रिप्ट विशेष रूप से निम्नलिखित बिंदुओं में प्रभावी है:।

  • WebGL वस्तुओं के प्रकार स्पष्ट हो जाते हैं।
  • शेडर वेरिएबल्स को संभालने में गलतियाँ कम की जा सकती हैं।
  • संरचना को ट्रैक करना आसान हो जाता है।

WebGL की न्यूनतम कॉन्फ़िगरेशन

WebGL के साथ रेंडरिंग के लिए निम्नलिखित न्यूनतम आवश्यकताएँ हैं:।

  • <canvas> एलिमेंट
  • WebGL संदर्भ
  • वर्टेक्स शेडर
  • फ्रैगमेंट शेडर

पहले, चलिए एक ऐसी स्थिति बनाते हैं जहाँ स्क्रीन को इनिशियलाइज़ किया जा सके।

कैनवस और WebGL संदर्भ प्राप्त करना

सबसे पहले, canvas और WebGLRenderingContext प्राप्त करें।

यहाँ, हम null सुरक्षा पर ज़ोर देने के साथ टाइपस्क्रिप्ट में कोडिंग करते हैं।

 1const canvas = document.getElementById('gl') as HTMLCanvasElement | null;
 2
 3if (!canvas) {
 4	throw new Error('Canvas not found');
 5}
 6
 7const gl = canvas.getContext('webgl');
 8
 9if (!gl) {
10	throw new Error('WebGL not supported');
11}
  • इस बिंदु पर, gl सभी वेबजीएल संचालन के लिए प्रवेश बिंदु बन जाता है।

यह सुनिश्चित करने के लिए स्क्रीन को साफ़ करना कि वेबजीएल काम कर रहा है

रेंडरिंग से पहले जांचें कि बैकग्राउंड कलर भरा जा सकता है या नहीं।

यह प्रारंभिक जांच है जो सुनिश्चित करती है कि वेबजीएल सही से काम कर रहा है।

1gl.clearColor(0.1, 0.1, 0.1, 1.0);
2gl.clear(gl.COLOR_BUFFER_BIT);
  • इस बिंदु तक, कैनवस गहरे स्लेटी रंग से भर जाएगा।

शेडर क्या होता है?

WebGL में, ड्राइंग की प्रक्रिया को एक विशेष भाषा GLSL में वर्णित किया जाता है। GLSL में, आप मुख्य रूप से दो प्रकार के शेडर तैयार करते हैं: वर्टेक्स शेडर और फ्रैगमेंट शेडर

सबसे पहले, हम इन दोनों शेडरों का उपयोग करके एक 'न्यूनतम कार्यशील शेडर' बनाएंगे।

वर्टेक्स शेडर लिखना

वर्टेक्स शेडर यह निर्धारित करते हैं कि बिंदुओं या आकृतियों को कहाँ बनाना है।

निम्नलिखित सरल कोड है जो स्क्रीन के केंद्र में एक बिंदु बनाता है।

1const vertexShaderSource = `
2attribute vec2 a_position;
3
4void main() {
5	gl_Position = vec4(a_position, 0.0, 1.0);
6}
7`;
  • a_position वह निर्देशांक है जो JavaScript से पास किया जाता है।

फ्रैगमेंट शेडर लिखना

फ्रैगमेंट शेडर यह तय करते हैं कि स्क्रीन पर कौन सा रंग दिखाई देगा।

इस बार, यह सदैव लाल रंग आउटपुट करेगा।

1const fragmentShaderSource = `
2precision mediump float;
3
4void main() {
5	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
6}
7`;
  • WebGL में precision हमेशा निर्दिष्ट होना चाहिए।

शेडर्स को कम्पाइल करने के लिए फ़ंक्शन बनाना

चूंकि शेडर निर्माण की प्रक्रिया हमेशा समान होती है, इसे एक फ़ंक्शन बना लेते हैं।

 1function createShader(
 2	gl: WebGLRenderingContext,
 3	type: number,
 4	source: string
 5): WebGLShader {
 6	const shader = gl.createShader(type);
 7	if (!shader) {
 8		throw new Error('Failed to create shader');
 9	}
10
11	gl.shaderSource(shader, source);
12	gl.compileShader(shader);
13
14	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
15		throw new Error(gl.getShaderInfoLog(shader) ?? 'Shader compile error');
16	}
17
18	return shader;
19}
  • यह फ़ंक्शन निर्दिष्ट प्रकार का शेडर बनाता है, स्रोत कोड को कंपाइल करता है, असफल होने पर त्रुटि देता है, और सफल होने पर संकलित शेडर लौटाता है।

प्रोग्राम बनाना (शेडर्स का समूह)

वर्टेक्स और फ्रैगमेंट शेडर को एक में मिलाएं।

इसे WebGLProgram कहा जाता है।

 1const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
 2const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
 3
 4const program = gl.createProgram();
 5if (!program) {
 6	throw new Error('Failed to create program');
 7}
 8
 9gl.attachShader(program, vertexShader);
10gl.attachShader(program, fragmentShader);
11gl.linkProgram(program);
12
13if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
14	throw new Error(gl.getProgramInfoLog(program) ?? 'Program link error');
15}
  • यह कोड वर्टेक्स और फ्रैगमेंट शेडरों को एक ही प्रोग्राम में लिंक करता है और जांचता है कि क्या इन्हें रेंडरिंग के लिए इस्तेमाल किया जा सकता है।

वर्टेक्स डेटा तैयार करना

यहाँ, हम एक त्रिभुज को ड्रॉ करने के लिए वर्टेक्स डेटा तैयार करेंगे।

1// Vertex positions for a triangle in clip space (x, y)
2// Coordinates range from -1.0 to 1.0
3const vertices = new Float32Array([
4	0.0,  0.5,   // Top vertex
5	-0.5, -0.5,  // Bottom-left vertex
6	0.5, -0.5,   // Bottom-right vertex
7]);
  • WebGL में निर्देशांक प्रणाली -1.0 से 1.0 तक होती है।

बफ़र बनाना और उसे GPU पर ट्रांसफर करना

इसके बाद, वर्टेक्स डेटा की ऐरे को GPU द्वारा इस्तेमाल योग्य बनाने के लिए, हम डेटा को एक बफ़र का उपयोग करके ट्रांसफर करते हैं।

1const buffer = gl.createBuffer();
2if (!buffer) {
3	throw new Error('Failed to create buffer');
4}
5
6gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
7gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  • यह कोड वर्टेक्स डेटा को संग्रहित करने के लिए एक बफ़र बनाता है और उसके सामग्री को GPU पर ट्रांसफर करता है।

एट्रीब्यूट को बफ़र से जोड़ना

शेडर में a_position को पूर्व निर्मित बफ़र से जोड़ें।

 1const positionLocation = gl.getAttribLocation(program, 'a_position');
 2
 3gl.enableVertexAttribArray(positionLocation);
 4gl.vertexAttribPointer(
 5	positionLocation,
 6	2,
 7	gl.FLOAT,
 8	false,
 9	0,
10	0
11);

रेंडरिंग

अंत में, रेंडरिंग कमांड जारी करने के लिए प्रोग्राम का उपयोग करें।

1gl.useProgram(program);
2gl.drawArrays(gl.TRIANGLES, 0, 3);
  • जब आप यह प्रोग्राम चलाएँगे तो एक लाल त्रिभुज दिखाई देगा।

WebGL के साथ क्लास डिज़ाइन

WebGL एक imperative एपीआई है, इसलिए यदि सीधे लिखा जाए तो कोड बहुत जल्दी जटिल और फैला हुआ हो सकता है। क्लास डिज़ाइन के ज़रिए आप इनिशियलाइज़ेशन, रेंडरिंग, और रिसोर्स प्रबंधन को स्पष्ट रूप से अलग कर सकते हैं।

यहाँ, हम टाइपस्क्रिप्ट के फायदों का इस्तेमाल करते हुए डिज़ाइन को धीरे-धीरे कार्य विभाजन, पुन: उपयोग, और अनुरक्षणीयता पर केंद्रित करेंगे।

डिज़ाइन नीति (न्यूनतम लेकिन व्यावहारिक)

कक्षा को निम्नलिखित भूमिकाओं में बाँटा गया है।

  • GLApp संपूर्ण इनिशियलाइज़ेशन और रेंडरिंग को नियंत्रित करता है।
  • ShaderProgram शेडर्स का प्रबंधन करता है।
  • TriangleMesh वर्टेक्स डेटा का प्रबंधन करता है।

सबसे पहले, वह क्लास बनाते हैं जो सब कुछ नियंत्रित करेगी।

WebGL एप्लीकेशन के लिए एंट्री क्लास

GLApp कैनवस और WebGL संदर्भ का प्रबंधन करता है और रेंडरिंग के लिए प्रारंभिक बिंदु होता है।

 1export class GLApp {
 2	private gl: WebGLRenderingContext;
 3	private shader!: ShaderProgram;
 4	private mesh!: TriangleMesh;
 5
 6	constructor(private canvas: HTMLCanvasElement) {
 7		const gl = canvas.getContext('webgl');
 8		if (!gl) {
 9			throw new Error('WebGL not supported');
10		}
11		this.gl = gl;
12	}
13
14	initialize() {
15		this.gl.clearColor(0.1, 0.1, 0.1, 1.0);
16
17		this.shader = new ShaderProgram(this.gl);
18		this.mesh = new TriangleMesh(this.gl);
19	}
20
21	render() {
22		this.gl.clear(this.gl.COLOR_BUFFER_BIT);
23
24		this.shader.use();
25		this.mesh.draw(this.shader);
26	}
27}
  • यह क्लास वेबजीएल के इनिशियलाइज़ेशन और रेंडरिंग प्रक्रिया का प्रबंधन करती है, और शेडर्स तथा मेष का उपयोग कर स्क्रीन पर चित्रण के लिए जिम्मेदार है।
  • initialize और render को अलग करके भविष्य में दोबारा इनिशियलाइज़ेशन और एनीमेशन के लिए समर्थन आसान हो जाता है।

शेडर्स के प्रबंधन के लिए क्लास

अब, शेडर प्रबंधन के लिए एक क्लास बनाएँ, जिसमें शेडर निर्माण, लिंकिंग और उपयोग को एक ही जगह संकलित किया जाए। इससे रेंडरिंग पक्ष केवल 'उपयोग' पर ध्यान केंद्रित कर सकता है।

 1export class ShaderProgram {
 2	private program: WebGLProgram;
 3
 4	constructor(private gl: WebGLRenderingContext) {
 5		const vertexSource = `
 6		attribute vec2 a_position;
 7		void main() {
 8			gl_Position = vec4(a_position, 0.0, 1.0);
 9		}
10		`;
11
12		const fragmentSource = `
13		precision mediump float;
14		void main() {
15			gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
16		}
17		`;
18
19		const vs = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
20		const fs = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
21
22		const program = this.gl.createProgram();
23		if (!program) throw new Error('Program create failed');
24
25		this.gl.attachShader(program, vs);
26		this.gl.attachShader(program, fs);
27		this.gl.linkProgram(program);
28
29		if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
30			throw new Error(this.gl.getProgramInfoLog(program) ?? 'Link error');
31		}
32
33		this.program = program;
34	}
35
36	use() {
37		this.gl.useProgram(this.program);
38	}
39
40	getAttribLocation(name: string): number {
41		return this.gl.getAttribLocation(this.program, name);
42	}
43
44	private createShader(type: number, source: string): WebGLShader {
45		const shader = this.gl.createShader(type);
46		if (!shader) throw new Error('Shader create failed');
47
48		this.gl.shaderSource(shader, source);
49		this.gl.compileShader(shader);
50
51		if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
52			throw new Error(this.gl.getShaderInfoLog(shader) ?? 'Compile error');
53		}
54
55		return shader;
56	}
57}
  • यह क्लास वर्टेक्स और फ्रैगमेंट शेडर के निर्माण, लिंकिंग और उपयोग को एकीकृत करती है, जिससे रेंडरिंग पक्ष इन्हें सुरक्षित रूप से उपयोग कर सकता है।
  • getAttribLocation को सार्वजनिक करके इसे मेष (mesh) पक्ष से सुरक्षित रूप से संदर्भित किया जा सकता है।

मेष (वर्टेक्स डेटा) के प्रबंधन के लिए क्लास

हम वर्टेक्स डेटा के प्रबंधन के लिए भी एक क्लास बनाएंगे। मेष क्लास को ड्रॉ ऑब्जेक्ट के अनुसार विभाजित करके विस्तार करना आसान हो जाता है।

 1export class TriangleMesh {
 2	private buffer: WebGLBuffer;
 3	private vertexCount = 3;
 4
 5	constructor(private gl: WebGLRenderingContext) {
 6		const vertices = new Float32Array([
 7			0.0,  0.5,
 8			-0.5, -0.5,
 9			0.5, -0.5,
10		]);
11
12		const buffer = gl.createBuffer();
13		if (!buffer) throw new Error('Buffer create failed');
14
15		this.buffer = buffer;
16
17		gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
18		gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
19	}
20
21	draw(shader: ShaderProgram) {
22		const gl = this.gl;
23		const positionLoc = shader.getAttribLocation('a_position');
24
25		gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
26		gl.enableVertexAttribArray(positionLoc);
27		gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
28
29		gl.drawArrays(gl.TRIANGLES, 0, this.vertexCount);
30	}
31}
  • यह क्लास त्रिभुज के वर्टेक्स डेटा का प्रबंधन करती है और उसे शेडर से जोड़कर वास्तविक रेंडरिंग को संभालती है।
  • रेंडरिंग के लिए आवश्यक सभी जानकारी TriangleMesh के भीतर ही होती है।

प्रवेश बिंदु (उपयोग उदाहरण)

अंत में, ऐप लॉन्च करने के लिए क्लासों को मिलाएं।

1const canvas = document.getElementById('gl') as HTMLCanvasElement;
2
3const app = new GLApp(canvas);
4app.initialize();
5app.render();
  • इस संरचना के साथ, एनीमेशन या एक से अधिक मेष जोड़ना आसान हो जाता है।

टाइपस्क्रिप्ट में वेबजीएल लिखने के व्यावहारिक सुझाव

WebGL के साथ टाइपस्क्रिप्ट इस्तेमाल करने से निम्नलिखित फायदे मिलते हैं:।

  • WebGL प्रक्रियाओं को क्लासों में बदलकर, उन्हें भूमिका के आधार पर व्यवस्थित किया जा सकता है, जिससे अनुरक्षण और विस्तार आसान हो जाता है।
  • रेंडरिंग और शेडर प्रबंधन जैसी ज़िम्मेदारियों को अलग करके कोड पठनीयता बढ़ती है।
  • टाइपस्क्रिप्ट के टाइप कम्प्लीशन का लाभ उठाकर, WebGL एपीआई कॉल करने या पैरामीटर निर्दिष्ट करते वक्त होने वाली गलतियाँ कम की जा सकती हैं।

सारांश

टाइपस्क्रिप्ट के प्रयोग से, लो-लेवल WebGL प्रक्रियाएँ भी टाइप सुरक्षा और संरचना के साथ स्थिर रूप से संभाली जा सकती हैं। न्यूनतम कॉन्फ़िगरेशन से रेंडरिंग तक के प्रवाह को समझकर और इनिशियलाइज़ेशन, रेंडरिंग और रिसोर्स प्रबंधन जैसी भूमिकाओं को अलग करने के लिए क्लास डिज़ाइन लागू करके, आप पठनीयता और अनुरक्षणीयता बढ़ा सकते हैं। चरणबद्ध रूप से लागू करके, आप WebGL को एक व्यावहारिक ज्ञान के रूप में सीख सकते हैं, जो एक ब्लैक बॉक्स नहीं है और जिसे असल काम में लागू किया जा सकता है।

आप हमारे YouTube चैनल पर Visual Studio Code का उपयोग करके ऊपर दिए गए लेख के साथ आगे बढ़ सकते हैं। कृपया YouTube चैनल को भी देखें।

YouTube Video