HLSL shader จริง ๆ แล้วมีผลกระทบต่อการแสดงผลอย่างไร


11

ฉันเข้าใจไวยากรณ์ของ HLSL เช่นสมมติว่าฉันมีสิ่งนี้เป็น HLSL ของฉัน:

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.position.xy *= 0.7f;    // "shrink" the vertex on the x and y axes
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

และฉันรวบรวมมันเช่นนี้

D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

มันเป็นอย่างไร ... รู้ว่าจะเปลี่ยน ... ฉันสับสนเกี่ยวกับสิ่งที่เชื่อมโยงระหว่าง HLSL และพิกเซล / จุดยอดจริงบนหน้าจอ

นี่คือสิ่งที่ "ใช้" จริงเหรอ?

dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);

โปรดทราบว่าฉันเป็นผู้เริ่มต้นที่แท้จริงในสิ่งนี้ บางคนสามารถอธิบายสิ่งที่กำลังทำอยู่ได้ ฉันสมมติว่าจุดสุดยอดฟังก์ชั่น HLSL ผ่านทุกจุดสุดยอดแล้วเปลี่ยนเป็นสิ่งที่ฉันมีในฟังก์ชั่นและเอาท์พุทคือสิ่งที่มีการเปลี่ยนแปลง ... และในทำนองเดียวกันสำหรับ pixel shader?

ความสับสนอีกอย่างฉันรู้ว่าพิกเซลคืออะไรและฉันเข้าใจว่าจุดยอดคืออะไร ... แต่พิกเซลเชดเดอร์ทำอะไรกันแน่


ก็โอเคไม่มีใครทำเลย
bobobobo

คำตอบ:


10

มันเป็นอย่างไร ...... รู้ว่าจะเปลี่ยน .... ฉันสับสนตรงไปตรงมาระหว่าง HLSL และ Pixels / Vertex จริงบนหน้าจอ

มันทำงานได้อย่างคร่าวๆเช่นนี้: เมื่อคุณออกคำสั่งวาด (DrawPrimitives, DrawIndexedPrimitives ใน D3D, Draw in 10+, และอื่น ๆ ) ข้อมูลเรขาคณิตที่คุณผูกกับไพพ์ไลน์ (บัฟเฟอร์จุดสุดยอดของคุณ) จะถูกประมวลผล สำหรับทุกจุดยอด shader จุดสุดยอดจะถูกดำเนินการในการผลิตจุดสุดยอดการส่งออกในพื้นที่คลิป

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

นี่คือสิ่งที่จริง "ใช้" พวกเขา:

รหัสที่คุณโพสต์ก่อนจะรวบรวมเฉดสีจากนั้นผูกกับท่อที่พวกเขายังคงใช้งานสำหรับการเรียกสายที่ตามมาใด ๆ จนกว่าจะมีการเปลี่ยนแปลง ไม่ได้ทำให้พวกเขาถูกประหารชีวิต

บางคนสามารถอธิบายได้ว่ากำลังทำอะไรอยู่ฉันสมมติว่าฟังก์ชั่น Vertex HLSL ผ่านจุดสุดยอดทุกอัน (เช่นตำแหน่งอินพุต: ตำแหน่งและสี: สี) จากนั้นเปลี่ยนเป็นสิ่งที่ฉันมีในฟังก์ชั่น ... (เช่นเดียวกันกับ Pixel Shader)

ความสับสนอีกครั้งฉันรู้ว่าพิกเซลคืออะไรและฉันเข้าใจว่าจุดสุดยอดคืออะไร ..... แต่สิ่งที่ Pixel Shader ทำเช่นนั้น ......

เวอร์เท็กซ์เชดเดอร์มีหน้าที่ในการเปลี่ยนจุดยอดจากพื้นที่แบบจำลองเป็นพื้นที่คลิป

Pixel Shader รับผิดชอบการคำนวณสี / ความลึกสุดท้ายสำหรับพิกเซลโดยอิงตามคุณลักษณะจุดสุดยอดที่ถูกสอดแทรก


9

ฉันจะพยายามอธิบายว่าสิ่งต่าง ๆ ทำงานได้อย่างไรโดยไม่ต้องใช้ศัพท์แสงมากนัก

หากความเรียบง่ายของคุณไม่ใช่เรื่องของความเร็วการโต้ตอบพื้นผิว 3 มิติในคอมพิวเตอร์จะเป็นเพียงแค่จุดคลาวด์ขนาดใหญ่ในอวกาศหนาแน่นเพียงพอที่เราจะสามารถแสดงจุดแต่ละจุดได้โดยไม่ต้องมีช่องว่างระหว่างกัน

คุณต้องการจัดเก็บแบบจำลองเพียงครั้งเดียวในหน่วยความจำ แต่คุณต้องแสดงในขนาดต่างๆและจากมุมต่าง ๆ ดังนั้นเมื่อคุณสร้างแบบจำลอง 3 มิติคุณต้อง "แปลง" จุดทั้งหมดเมื่อคุณอ่านจากหน่วยความจำ ตัวอย่างเช่นในการเรนเดอร์โมเดล 50% ให้ใหญ่คุณจะต้องปรับตำแหน่งของคะแนนเป็นครึ่ง:

out.position = in.position * 0.5;
out.color = in.color;

นี่เป็น "จุดยอดที่ง่ายที่สุด" ที่ง่ายที่สุดที่จะนึกได้: ในไปสู่ตำแหน่งจุดสุดยอดจากหน่วยความจำและออกมาเป็นตำแหน่งจุดสุดยอดใหม่ครึ่งหนึ่ง - ใหญ่ จุดสุดยอดครึ่งขนาดใหญ่ไม่ได้ถูกเก็บไว้ในหน่วยความจำ - มันถูกใช้ในการเรนเดอร์ทันทีแล้วโยนทิ้งไป

แม้ว่าจะเป็นเปลือกขั้นต้นที่ขาดแนวคิดที่สำคัญนี้ในจิตวิญญาณอธิบายลักษณะของวิธีการที่ภาพยนตร์ทำกราฟิก

กราฟิกแบบอินเทอร์แอคทีฟ (เกม) ไม่สามารถทำได้อย่างง่าย ๆ เพราะพวกเขาต้องการที่จะเรนเดอร์กราฟิกหลายขนาดที่รวดเร็วกว่าภาพยนตร์

ในเกมเราไม่สามารถแสดงหนึ่งจุดสำหรับแต่ละพิกเซลบนหน้าจอรวมถึงบริการพิเศษเพื่อครอบคลุมช่องว่าง ดังนั้นการประนีประนอมช่องว่างระหว่างจุดสามจุดที่อยู่ใกล้เคียงจึงกลายเป็นรูปสามเหลี่ยมซึ่งด้วยเหตุผลทางเทคนิคต่างๆที่ต้องการให้มีขนาดใหญ่อย่างน้อย 10 พิกเซลบนหน้าจอ

สามเหลี่ยมสามมิติสามารถฉายลงบนหน้าจอ 2 มิติจากนั้นแบ่งออกเป็นสแต็กของ 1D บรรทัดซึ่งแต่ละภาพสามารถแบ่งออกเป็นสแต็ก 0D พิกเซล เราสามารถแบ่งและพิชิตปัญหาของการเรนเดอร์สามเหลี่ยมสามมิติเป็นปัญหาที่ง่ายกว่าในการเรนเดอร์พิกเซล 0D จำนวนมาก คอมพิวเตอร์สามารถแก้ปัญหาได้ง่ายขึ้นในเวลาน้อยลง

Pixel Shader เป็นโปรแกรมเล็ก ๆ ที่เรารันในแต่ละพิกเซลเพื่อสร้างจากการแยกส่วนสามเหลี่ยม

out.color = in.color;

นี่คือ "pixel shader" ที่ง่ายที่สุดที่สามารถเข้าใจได้: การผสมผสานสีของจุดยอดสามเหลี่ยมสามอันเข้าด้วยกันและออกไปเป็นสีเดียวกัน อินพุทมาจากเอาท์พุทของ "ยอดยอด" และเอาท์พุทจะถูกเขียนไปยังหน้าจอในหน่วยความจำ

ดังนั้น - "vertex shader" เป็นโปรแกรมที่ทำงานภายในชิป GPU อินพุตของมันคือ "บัฟเฟอร์จุดสุดยอด" ในหน่วยความจำ GPU และเอาต์พุตของมันจะถูกป้อนเข้าสู่ "pixel shader" โดยตรง "pixel shader" ยังเป็นโปรแกรมที่ทำงานภายในชิป GPU อินพุตของมันเป็นการผสมผสานของสามยอดจาก Shader ที่และเอาท์พุทของมันคือพิกเซลบนหน้าจอ



-2

ไม่ต้องกังวลกับการเปลี่ยนพิกเซลในขณะนี้ หากคุณเพิ่งเริ่มต้นอย่างสมบูรณ์คุณควรจะเป็น Hello world ของ GLSL / HLSL ที่มีจุดยอดและส่วนที่แตกเท่านั้น เมื่อคุณคุ้นเคยและคุณเริ่มเข้าใจการเคลื่อนไหวที่แปรปรวนและจากนั้นขยายขอบเขตของคุณ

ฉันขอแนะนำหนังสือเรียนเพื่อรับความเป็นมิตรกับการทำงานของ API หนังสือ OpenGL ยังทำหน้าที่ได้ดีซึ่งแสดงให้เห็นว่าสิ่งต่าง ๆ มีการเปลี่ยนแปลงในช่วงหลายปีที่ผ่านมาจากไปป์ไลน์คงที่ไปยังไปป์ไลน์ที่ตั้งโปรแกรมได้แบบไดนามิก

ไปแชมป์!


1
แฟรกเมนต์ตัวแบ่งส่วนเติมเต็มฟังก์ชั่นเดียวกับตัวแบ่งพิกเซล

1
ฉันไม่คิดว่าเราสามารถบอกได้จากคำถามว่า OP เป็นผู้เริ่มต้นในการเขียนโปรแกรมเกมทั้งหมดหรือไม่ - เขากล่าวเพียงว่าเขาเป็นผู้เริ่มต้นในการเขียนรหัส shader เรียนรู้การเขียน shaders เป็นเครื่องมือที่มีความสำคัญมากที่จะมีในเพิงพัฒนาเกมของฉันจะไม่เพียงปัดสวะพวกเขาจนกว่าคุณเท่านั้นที่มากระยะเริ่มต้นของการเรียนรู้การพัฒนาเกม
Olhovsky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.