টাইপস্ক্রিপ্টে ওয়েবজিএল
এই নিবন্ধটি টাইপস্ক্রিপ্টে ওয়েবজিএল ব্যাখ্যা করে।
আমরা ওয়েবজিএল-এর ধারণা, ন্যূনতম কনফিগারেশন, রেন্ডারিং, এক্সটেনশন এবং ক্লাস ডিজাইন উদাহরণসহ কোড দিয়ে ধাপে ধাপে পরিচয় করিয়ে দেবো।
YouTube Video
টাইপস্ক্রিপ্টে ওয়েবজিএল
WebGL হল একটি লো-লেভেল এপিআই, যা আপনাকে ব্রাউজারে সরাসরি GPU নিয়ন্ত্রণ করতে দেয়।
WebGL-এ টাইপ সেফটি, কোড কমপ্লিশন, এবং স্ট্রাকচার্ড কোডিং-এর মাধ্যমে TypeScript ব্যবহার করলে আপনি 'ইমপ্লিমেন্টেশন মিসটেক' অনেকটাই কমাতে পারবেন।
নীচের বিষয়গুলোতে টাইপস্ক্রিপ্ট বিশেষভাবে কার্যকর:।
- ওয়েবজিএল অবজেক্টগুলোর ধরন পরিষ্কার হয়।
- শেডার ভেরিয়েবল পরিচালনায় ভুল কমে যায়।
- গঠন (স্ট্রাকচার) অনুধাবন করা সহজ হয়।
ওয়েবজিএলের ন্যূনতম কনফিগারেশন
ওয়েবজিএল দিয়ে রেন্ডারিং করার জন্য নীচের ন্যূনতম অপরিহার্য বিষয়গুলো প্রয়োজন:।
<canvas>এলিমেন্টWebGLকনটেক্সট- ভার্টেক্স শেডার
- ফ্র্যাগমেন্ট শেডার
প্রথমে, এমন একটি অবস্থা তৈরি করি যেখানে স্ক্রীন ইনিশিয়ালাইজ করা যায়।
ক্যানভাস এবং ওয়েবজিএল কনটেক্সট পাওয়া
প্রথমে, ক্যানভাস এবং WebGLRenderingContext সংগ্রহ করুন।
এখানে, আমরা নাল সেফটি গুরুত্ব দিয়ে টাইপস্ক্রিপ্ট কোড ব্যবহার করছি।
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);- এ পর্যন্ত, ক্যানভাস গা dark ঁধুসর (ডার্ক গ্রে) রঙে পূর্ণ হবে।
শেডার কী?
ওয়েবজিএলে ড্রয়িং প্রসেস 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হচ্ছে জাভাস্ক্রিপ্ট থেকে পাঠানো কো-অর্ডিনেট।
ফ্র্যাগমেন্ট শেডার লেখা
ফ্র্যাগমেন্ট শেডার নির্ধারণ করে স্ক্রীনে কোন রঙ দেখা যাবে।
এবার এটি সবসময় লাল রঙে আউটপুট দিবে।
1const fragmentShaderSource = `
2precision mediump float;
3
4void main() {
5 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
6}
7`;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]);- ওয়েবজিএলের কো-অর্ডিনেট সিস্টেম
-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);- আপনি যখন এই প্রোগ্রাম চালাবেন, তখন একটি লাল ত্রিভুজ দেখা যাবে।
ওয়েবজিএল সহ ক্লাস ডিজাইন
ওয়েবজিএল একটি ইম্পারেটিভ এপিআই, তাই সরাসরি কোড লিখলে তা দ্রুত ফেঁপে যেতে পারে। ক্লাস ডিজাইনের মাধ্যমে আপনি ইনিশিয়ালাইজেশন, রেন্ডারিং এবং রিসোর্স ম্যানেজমেন্ট স্পষ্টভাবে আলাদা করতে পারেন।
এখানে, আমরা টাইপস্ক্রিপ্টের সুবিধা নিয়ে ডিজাইন ধাপে ধাপে এমনভাবে গড়ে তুলব যাতে বিষয়ের পৃথকীকরণ, পুনর্ব্যবহারযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা-তে জোর দেয়া হয়।
ডিজাইন নীতি (ন্যূনতম কিন্তু বাস্তবসম্মত)
শ্রেণিটি নিম্নলিখিত ভূমিকায় ভাগ করা হয়েছে।
GLAppসমগ্র ইনিশিয়ালাইজ এবং রেন্ডারিং নিয়ন্ত্রণ করে।ShaderProgramশেডার নিয়ন্ত্রণ করে।TriangleMeshভার্টেক্স তথ্য নিয়ন্ত্রণ করে।
প্রথমে, চলুন এমন একটি ক্লাস তৈরি করি যা সবকিছু নিয়ন্ত্রণ করে।
ওয়েবজিএল অ্যাপ্লিকেশনের এন্ট্রি ক্লাস
GLApp ক্যানভাস এবং ওয়েবজিএল কনটেক্সট পরিচালনা করে এবং রেন্ডারিংয়ের সূচনাবিন্দু হিসেবে কাজ করে।
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প্রকাশ করলে, মেশ পাশ থেকে নিরাপদে রেফারেন্স করা যায়।
মেশ (ভার্টেক্স ডাটা) নিয়ন্ত্রণের জন্য ক্লাস
আমরা ভার্টেক্স ডেটা ব্যবস্থাপনার জন্য একটি ক্লাসও তৈরি করব। ড্রয়িং অবজেক্ট অনুযায়ী মেশ ক্লাস ভাগ করে নিলে এক্সটেনশন সহজ হয়।
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-এর সাথে TypeScript ব্যবহার করলে নিচের সুবিধা পাওয়া যায়:।
- ওয়েবজিএল প্রসিডিউর ক্লাসে রূপান্তর করলে তা ভূমিকা অনুযায়ী সাজানো যায়, ফলে রক্ষণাবেক্ষণ ও সম্প্রসারণ সহজ হয়।
- রেন্ডারিং ও শেডার ম্যানেজমেন্টের মতো দায়িত্ব পৃথক করলে কোডের পাঠযোগ্যতা বাড়ে।
- টাইপস্ক্রিপ্টের টাইপ কমপ্লিশন ব্যবহার করে ওয়েবজিএল এপিআই ডাকা বা প্যারামিটার নির্ধারণের ভুল কমানো যায়।
সারসংক্ষেপ
টাইপস্ক্রিপ্ট ব্যবহার করলে, লো-লেভেল ওয়েবজিএল প্রসেসও টাইপ নিরাপত্তা ও কাঠামো দিয়ে স্থিতিশীল ভাবে পরিচালনা করা যায়। ন্যূনতম কনফিগারেশন থেকে রেন্ডারিং পর্যন্ত ফ্লো বোঝার মাধ্যমে এবং ক্লাস ডিজাইনে ইনিশিয়ালাইজেশন, রেন্ডারিং ও রিসোর্স ম্যানেজমেন্ট আলাদা করলে, পড়তে এবং রক্ষণাবেক্ষণ করতে সুবিধা হয়। ধাপে ধাপে করে বাস্তবসম্মতভাবে ওয়েবজিএল জানতে পারবেন, যা ব্ল্যাকবক্স নয় এবং প্রকৃত কাজে প্রয়োগযোগ্য।
আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।