ساخت تصاویر 3D با WebGL
ساخت تصاویر 3D با WebGL

ساخت تصاویر 3D با WebGL

در این آموزش قصد داریم افکت سه بعدی برای تصاویر با WebGL بسازیمWebGL به ما برای ایجاد افکت های گرافیکی تعاملی کمک میکند. به همین دلیل برای ساخت افکت 3D از آن استفاده میکنیم. معمولا برای اینچنین افکت ها از کتابخانه هایی مانند Three.js و یا Pixi.js استفاده می کنند که ویژگی های قدرتمندی دارند. اما امروز ما قصد استفاده از این کتابخانه ها را نداریم.

شروع

در ابتدا صفحه خود را برای نمایش تصویر و سایه ها ایجاد می کنیم

let vertices = new Float32Array([
	  -1, -1,
	  1, -1,
	  -1, 1,
	  1, 1,
	])
let buffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );

آماده سازی تصویر

برای این افکت، نیاز داریم یک تصویر عمیق ایجاد کنیم. برای این کار باید بسته به موقعیت Z آیتم ها ( یعنی دور و یا نزدیک بودنشان ) قسمت هایی از تصویر را جدا کنیم. در نتیجه پس زمینه را از پیش زمینه جدا میکنیم. 

برای این کار می توانیم تصویر را در فتوشاپ باز کنیم و مناطق خاکستری را بر روی عکس اصلی به روش زیر بکشیم:

هرچه المانهای تصویر از دوربین فاصله بیشتری داشته باشند، مناطق تیره تری خواهیم داشت و هرچه فاصله آنها به دوربین نزدیکتر باشند، مناطق روشنتری خواهیم داشت.

Shaders

منطق رندر بیشتر در Shaders اتفاق می افتد. همانطور که در اسناد وب MDN شرح داده شده است:

shader یک برنامه است که با استفاده از OpenGL ES Shading Language (GLSL) نوشته شده است. که اطلاعاتی راجع به رئوس هایی که یک شکل را تشکیل می دهند و داده های مورد نیاز برای ارائه پیکسل ها روی صفحه را تولید می کند. یعنی موقعیت پیکسل ها و رنگ آنها. دو تابع shader هنگام ترسیم محتوای WebGL وجود دارد: shader vertex و shader fragment.

یک منبع عالی برای کسب اطلاعات بیشتر در مورد Shaders ، کتاب Shaders است. 

vertex در Shaders برای نمایش رئوس استفاده می شود.

attribute vec2 position;
    void main() {
    gl_Position = vec4( position, 0, 1 );
}

جالبترین قسمت در fragment اتفاق می افتد. بیایید دو تصویر را در آن لود کنیم

void main(){
    vec4 depth = texture2D(depthImage, uv);
    gl_FragColor = texture2D(originalImage, uv); // just showing original photo
} 

به یاد داشته باشید ، تصویر نقشه عمق سیاه و سفید است. برای Shaders ، رنگ فقط یک عدد است: 1 سفید و 0 رنگ سیاه است. متغیر uv یک نقشه دو بعدی است که اطلاعاتی در باره اینکه کدام پیکسل باید نمایش داده شود ذخیره می کند. با استفاده از این دو مورد می توان از اطلاعات عمق استفاده کرد تا پیکسل های عکس اصلی را کمی جابجا کنیم.

بیایید حرکت موس را دخیل کنیم

vec4 depth = texture2D(depthImage, uv);
gl_FragColor = texture2D(originalImage, uv + mouse);

که تا اینجا بدین شکل میشود:

و حالا عمق تصویر را اضافه می کنیم

vec4 depth = texture2D(depthImage, uv);
gl_FragColor = texture2D(originalImage, uv + mouse*depth.r);

که نتیجه آن بشکل زیر است :

از آنجا که بافت سیاه و سفید است ، فقط می توانیم کانال قرمز (deep.r) را بگیریم و آن را به مقدار موقعیت ماوس روی صفحه ضرب کنیم. یعنی هرچه پیکسل روشن تر باشد ، با ماوس حرکت بیشتری می کند. از طرف دیگر ، پیکسل های تیره در جای خود ثابت قرار می گیرند. این بسیار ساده است ، اما منجر به یک توهم سه بعدی خوب از یک تصویر می شود. 

البته ، Shaders  قادر به انجام کارهای دیوانه وار دیگری نیز هستند، امیدواریم این آزمایش کوچک "جعل" حرکت سه بعدی را دوست داشته باشید.