ฟิลเตอร์ที่กำหนดเองหรือที่เรียกว่า CSS Shader ก่อนหน้านี้ช่วยให้คุณใช้ความสามารถของ Shader ของ WebGL กับเนื้อหา DOM ได้ เนื่องจากในการใช้งานปัจจุบัน Shader ที่ใช้แทบจะเหมือนกับใน WebGL คุณจึงต้องถอยหลังสักก้าวและทำความเข้าใจคำศัพท์ 3 มิติและไปป์ไลน์กราฟิกสักเล็กน้อย
เราได้แนบไฟล์บันทึกวิดีโอของงานนำเสนอที่ฉันเพิ่งแสดงที่ LondonJS ในวิดีโอนี้ เราจะอธิบายภาพรวมของคําศัพท์ 3 มิติที่คุณต้องเข้าใจ ประเภทตัวแปรต่างๆ ที่คุณจะพบ และวิธีเริ่มเล่นกับตัวกรองที่กําหนดเองในวันนี้ นอกจากนี้ คุณควรดาวน์โหลดสไลด์เพื่อดูการสาธิตด้วยตนเอง
ข้อมูลเบื้องต้นเกี่ยวกับ Shader
ก่อนหน้านี้เราได้เขียนข้อมูลเบื้องต้นเกี่ยวกับโปรแกรมเปลี่ยนสีซึ่งจะอธิบายรายละเอียดเกี่ยวกับโปรแกรมเปลี่ยนสีและวิธีใช้จากมุมมอง WebGL หากคุณไม่เคยจัดการกับเชดเดอร์ คุณควรอ่านข้อมูลเกี่ยวกับเชดเดอร์ก่อนดำเนินการต่อ เนื่องจากแนวคิดและภาษาของฟิลเตอร์ที่กำหนดเองจำนวนมากขึ้นอยู่กับคำศัพท์เชดเดอร์ WebGL ที่มีอยู่
ทีนี้มาเปิดใช้ตัวกรองที่กำหนดเองและดําเนินการต่อกันเลย
การเปิดใช้ตัวกรองที่กำหนดเอง
ตัวกรองที่กำหนดเองพร้อมใช้งานทั้งใน Chrome และ Canary รวมถึง Chrome สำหรับ Android เพียงไปที่ about:flags
แล้วค้นหา "CSS Shaders" จากนั้นเปิดใช้และรีสตาร์ทเบราว์เซอร์ ตอนนี้คุณก็พร้อมลุยแล้ว
ไวยากรณ์
ตัวกรองที่กำหนดเองจะขยายชุดตัวกรองที่คุณใช้กับองค์ประกอบ DOM อยู่แล้วได้ เช่น blur
หรือ sepia
Eric Bidelman ได้เขียนเครื่องมือทดสอบที่ยอดเยี่ยมสำหรับกรณีดังกล่าว ซึ่งคุณควรลองดู
หากต้องการใช้ตัวกรองที่กำหนดเองกับองค์ประกอบ DOM คุณจะใช้ไวยากรณ์ต่อไปนี้
.customShader {
-webkit-filter:
custom(
url(vertexshader.vert)
mix(url(fragment.frag) normal source-atop),
/* Row, columns - the vertices are made automatically */
4 5,
/* We set uniforms; we can't set attributes */
time 0)
}
คุณจะเห็นว่าเราประกาศ Vertex และ Fragment Shader, จำนวนแถวและคอลัมน์ที่เราต้องการให้แยกองค์ประกอบ DOM ออกเป็น และ Uniform ที่ต้องการส่งผ่าน
สิ่งสุดท้ายที่ควรชี้ให้เห็นคือเราใช้ฟังก์ชัน mix()
กับ ฟร็กเมนต์ เชดเดอร์ที่มีโหมดการผสม (normal
) และโหมดคอมโพสิท (source-atop
) มาพิจารณาฟร็กเมนต์ เชดเดอร์กันเพื่อดูว่าเหตุใดเราจึงต้องใช้ฟังก์ชัน mix()
การผลักพิกเซล
หากคุณคุ้นเคยกับโปรแกรมเปลี่ยนสีของ WebGL จะเห็นว่าตัวกรองที่กำหนดเองจะแตกต่างออกไปเล็กน้อย สาเหตุหนึ่งคือเราไม่สร้างพื้นผิวที่โปรแกรมเปลี่ยนชิ้นส่วนของเราใช้เพื่อเติมพิกเซล แต่ระบบจะแมปเนื้อหา DOM ที่มีการใช้ฟิลเตอร์กับพื้นผิวโดยอัตโนมัติ ซึ่งหมายความว่าจะมีผล 2 อย่างดังนี้
- เราไม่สามารถค้นหาค่าสีของพิกเซลแต่ละค่าของพื้นผิว DOM ได้เนื่องจากเหตุผลด้านความปลอดภัย
- เราไม่ได้ตั้งค่าสีพิกเซลสุดท้ายด้วยตนเอง (อย่างน้อยก็ในการใช้งานปัจจุบัน) กล่าวคือ
gl_FragColor
อยู่นอกเหนือขอบเขต แต่ระบบจะถือว่าคุณต้องการแสดงผลเนื้อหา DOM และสิ่งที่คุณจะทําได้คือจัดการพิกเซลของ DOM โดยอ้อมผ่านcss_ColorMatrix
และcss_MixColor
ซึ่งหมายความว่า Hello World ของโปรแกรมเปลี่ยนรูปแบบเศษเสี้ยวจะมีลักษณะดังนี้
void main() {
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
css_MixColor = vec4(0.0, 0.0, 0.0, 0.0);
// umm, where did gl_FragColor go?
}
พิกเซลแต่ละพิกเซลของเนื้อหา DOM จะคูณด้วย css_ColorMatrix
ซึ่งในกรณีข้างต้นจะไม่มีการดําเนินการใดๆ เนื่องจากเป็นเมทริกซ์เอกลักษณ์และจะไม่เปลี่ยนแปลงค่า RGBA ใดๆ หากต้องการเก็บเฉพาะค่าสีแดงไว้ เราจะใช้ css_ColorMatrix
ดังนี้
// keep only red and alpha
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0);
คุณจะเห็นเมื่อคุณคูณค่าพิกเซล 4 มิติ (RGBA) กับเมทริกซ์ คุณจะได้รับค่าพิกเซลที่ดัดแปลงจากอีกด้านหนึ่ง และในกรณีนี้ ค่าที่ลบองค์ประกอบสีเขียวและน้ำเงินเป็น 0
css_MixColor
ส่วนใหญ่จะใช้เป็นสีฐานที่คุณต้องการผสมเข้ากับเนื้อหา DOM การผสมจะทำผ่านโหมดผสมผสานที่คุณคุ้นเคยจากแพ็กเกจอาร์ตเวิร์ก เช่น การวางซ้อน หน้าจอ การไล่สี การแรเงาอย่างหนัก และอื่นๆ
ตัวแปรทั้ง 2 อย่างนี้มีวิธีมากมายในการดัดแปลงพิกเซล คุณควรดูข้อกำหนดเฉพาะของเอฟเฟกต์ฟิลเตอร์เพื่อให้เข้าใจวิธีการทำงานของโหมดผสมและโหมดคอมโพสิตได้ดียิ่งขึ้น
การสร้าง Vertex
ใน WebGL เราจะรับผิดชอบอย่างเต็มที่ในการสร้างจุด 3 มิติของเมช แต่ในตัวกรองที่กำหนดเอง สิ่งที่คุณต้องทำคือระบุจำนวนแถวและคอลัมน์ที่ต้องการ แล้วเบราว์เซอร์จะแบ่งเนื้อหา DOM ออกเป็นสามเหลี่ยมหลายรูปโดยอัตโนมัติ
จากนั้นระบบจะส่งแต่ละจุดยอดไปยังเวิร์กเชดเวอร์เทกซ์เพื่อดำเนินการ ซึ่งหมายความว่าเราสามารถเริ่มย้ายจุดยอดเหล่านั้นไปรอบๆ ในอวกาศ 3 มิติได้ตามต้องการ คุณสามารถสร้างเอฟเฟกต์เจ๋งๆ ได้เร็วๆ นี้
การทำภาพเคลื่อนไหวด้วย Shader
การใช้ภาพเคลื่อนไหวในโปรแกรมเปลี่ยนสีคือสิ่งที่ทำให้โปรแกรมเปลี่ยนสีสนุกและน่าสนใจ โดยเพียงใช้การเปลี่ยน (หรือภาพเคลื่อนไหว) ใน CSS เพื่ออัปเดตค่าแบบเดียวกัน ดังนี้
.shader {
/* transition on the filter property */
-webkit-transition: -webkit-filter 2500ms ease-out;
-webkit-filter: custom(
url(vshader.vert)
mix(url(fshader.frag) normal source-atop),
1 1,
time 0);
}
.shader:hover {
-webkit-filter: custom(
url(vshader.vert)
mix(url(fshader.frag) normal source-atop),
1 1,
time 1);
}
สิ่งที่ควรสังเกตในโค้ดด้านบนคือเวลาจะลดลงจาก 0
เป็น 1
ในระหว่างการเปลี่ยน ในโปรแกรมเปลี่ยนสี เราสามารถประกาศค่าคงที่ time
และใช้ค่าปัจจุบันของค่าคงที่นั้น ดังนี้
uniform float time;
uniform mat4 u_projectionMatrix;
attribute vec4 a_position;
void main() {
// copy a_position to position - attributes are read only!
vec4 position = a_position;
// use our time uniform from the CSS declaration
position.x += time;
gl_Position = u_projectionMatrix * position;
}
เริ่มเล่นเลย
ฟิลเตอร์ที่กำหนดเองเป็นเครื่องมือที่สนุกและสร้างเอฟเฟกต์ที่น่าทึ่งได้ ซึ่งหากไม่มีฟิลเตอร์เหล่านี้ คุณอาจสร้างเอฟเฟกต์เหล่านั้นได้ยาก (หรือเป็นไปไม่ได้ในบางกรณี) เราเพิ่งเริ่มใช้งานฟีเจอร์นี้และทุกอย่างก็เปลี่ยนแปลงไปมาก แต่การเพิ่มฟีเจอร์เหล่านี้จะทำให้โปรเจ็กต์ของคุณดูมีสีสันขึ้น ลองใช้ดูเลย