ข้อมูลเบื้องต้นเกี่ยวกับตัวกรองที่กำหนดเอง (หรือที่เรียกว่า CSS Shaders)

ฟิลเตอร์ที่กำหนดเองหรือที่เรียกว่า 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 อย่างดังนี้

  1. เราไม่สามารถค้นหาค่าสีของพิกเซลแต่ละค่าของพื้นผิว DOM ได้เนื่องจากเหตุผลด้านความปลอดภัย
  2. เราไม่ได้ตั้งค่าสีพิกเซลสุดท้ายด้วยตนเอง (อย่างน้อยก็ในการใช้งานปัจจุบัน) กล่าวคือ 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;
}

เริ่มเล่นเลย

ฟิลเตอร์ที่กำหนดเองเป็นเครื่องมือที่สนุกและสร้างเอฟเฟกต์ที่น่าทึ่งได้ ซึ่งหากไม่มีฟิลเตอร์เหล่านี้ คุณอาจสร้างเอฟเฟกต์เหล่านั้นได้ยาก (หรือเป็นไปไม่ได้ในบางกรณี) เราเพิ่งเริ่มใช้งานฟีเจอร์นี้และทุกอย่างก็เปลี่ยนแปลงไปมาก แต่การเพิ่มฟีเจอร์เหล่านี้จะทำให้โปรเจ็กต์ของคุณดูมีสีสันขึ้น ลองใช้ดูเลย

แหล่งข้อมูลเพิ่มเติม