ฉันจะวาดโครงร่างรอบ ๆ แบบจำลอง 3 มิติได้อย่างไร


47

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

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


คุณใช้ OpenGL หรือไม่ ถ้าเป็นเช่นนั้นคุณควรค้นหาใน google วิธีวาดโครงร่างของโมเดลด้วย OpenGL
oxysoft

1
หากคุณอ้างถึงภาพที่คุณใส่ไว้ในนั้นฉันสามารถพูดได้อย่างมั่นใจ 95% ว่าภาพเหล่านั้นเป็นภาพวาด 2D สไปรท์ไม่ใช่แบบจำลอง 3 มิติ
Panda Pajama

3
@PandaPajama: ไม่พวกนั้นเกือบจะเป็นแบบจำลอง 3 มิติ มีความสะเพร่าอยู่บ้างในสิ่งที่ควรเป็นเส้นแข็งในบางเฟรมที่ฉันไม่คาดหวังจากสไปรต์ที่วาดด้วยมือและนั่นก็คือลักษณะของโมเดล 3 มิติในเกม ฉันคิดว่าฉันไม่สามารถรับประกันได้ 100% สำหรับภาพเฉพาะเหล่านั้น แต่ฉันไม่สามารถจินตนาการได้ว่าทำไมทุกคนจะพยายามแกล้งทำ
CA McCann

เกมไหนเป็นพิเศษ? มันดูงดงาม
Vegard

@Vegard สิ่งมีชีวิตที่มีหัวผักกาดที่ด้านหลังของมันคือ Bulbasaur จากเกมโปเกมอน
Damian Yerrick

คำตอบ:


28

ฉันไม่คิดว่าคำตอบอื่นใดที่นี่จะได้ผลในโปเกมอน X / Y ฉันไม่รู้แน่ชัดว่าทำอย่างไร แต่ฉันคิดวิธีที่ดูเหมือนว่าพวกเขาทำอะไรในเกม

ในPokémon X / Y โครงร่างจะถูกวาดทั้งรอบขอบภาพเงาและบนขอบที่ไม่ใช่เงาอื่น ๆ (เช่นที่หูของ Raichu พบกับศีรษะของเขาในภาพหน้าจอต่อไปนี้)

Raichu

เมื่อมองไปที่ตาข่ายของ Raichu ในเครื่องปั่นคุณสามารถเห็นหู (เน้นด้วยสีส้มด้านบน) เป็นเพียงวัตถุแยกต่างหากที่ไม่ได้เชื่อมต่อซึ่งตัดกับส่วนหัวทำให้เกิดการเปลี่ยนแปลงอย่างฉับพลันในพื้นผิวปกติ

จากนั้นฉันพยายามสร้างโครงร่างโดยยึดตามบรรทัดฐานซึ่งต้องแสดงผลเป็นสองรอบ:

บัตรผ่านครั้งแรก : แสดงโมเดล (พื้นผิวและเฉดสีเทา) โดยไม่แสดงโครงร่างและทำให้บรรทัดฐานของพื้นที่กล้องเป็นเป้าหมายการเรนเดอร์ที่สอง

รอบที่สอง : ทำการกรองการตรวจจับขอบแบบเต็มหน้าจอเหนือบรรทัดฐานจากรอบแรก

ภาพสองภาพแรกด้านล่างแสดงเอาท์พุทของการผ่านครั้งแรก ที่สามคือร่างโดยตัวเองและสุดท้ายคือผลรวมสุดท้าย

Dratini

นี่คือส่วนย่อย OpenGL ที่ฉันใช้สำหรับการตรวจจับขอบในรอบที่สอง มันเป็นสิ่งที่ดีที่สุดที่ฉันสามารถทำได้ แต่อาจมีวิธีที่ดีกว่า มันอาจไม่ได้รับการปรับให้เหมาะสมเช่นกัน

// first render target from the first pass
uniform sampler2D uTexColor;
// second render target from the first pass
uniform sampler2D uTexNormals;

uniform vec2 uResolution;

in vec2 fsInUV;

out vec4 fsOut0;

void main(void)
{
  float dx = 1.0 / uResolution.x;
  float dy = 1.0 / uResolution.y;

  vec3 center = sampleNrm( uTexNormals, vec2(0.0, 0.0) );

  // sampling just these 3 neighboring fragments keeps the outline thin.
  vec3 top = sampleNrm( uTexNormals, vec2(0.0, dy) );
  vec3 topRight = sampleNrm( uTexNormals, vec2(dx, dy) );
  vec3 right = sampleNrm( uTexNormals, vec2(dx, 0.0) );

  // the rest is pretty arbitrary, but seemed to give me the
  // best-looking results for whatever reason.

  vec3 t = center - top;
  vec3 r = center - right;
  vec3 tr = center - topRight;

  t = abs( t );
  r = abs( r );
  tr = abs( tr );

  float n;
  n = max( n, t.x );
  n = max( n, t.y );
  n = max( n, t.z );
  n = max( n, r.x );
  n = max( n, r.y );
  n = max( n, r.z );
  n = max( n, tr.x );
  n = max( n, tr.y );
  n = max( n, tr.z );

  // threshold and scale.
  n = 1.0 - clamp( clamp((n * 2.0) - 0.8, 0.0, 1.0) * 1.5, 0.0, 1.0 );

  fsOut0.rgb = texture(uTexColor, fsInUV).rgb * (0.1 + 0.9*n);
}

และก่อนที่จะเรนเดอร์พาสครั้งแรกฉันจะล้างเรนเดอร์เป้าหมายของเวกเตอร์ให้หันหน้าออกจากกล้อง

glDrawBuffer( GL_COLOR_ATTACHMENT1 );
Vec3f clearVec( 0.0, 0.0, -1.0f );
// from normalized vector to rgb color; from [-1,1] to [0,1]
clearVec = (clearVec + Vec3f(1.0f, 1.0f, 1.0f)) * 0.5f;
glClearColor( clearVec.x, clearVec.y, clearVec.z, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

ฉันอ่านที่ไหนสักแห่ง (ฉันจะใส่ลิงค์ไว้ในคอมเม้นต์) ว่า Nintendo 3DS ใช้ฟังก์ชั่นคงที่แทนที่จะใช้ตัวแปลงสีดังนั้นฉันเดาว่านี่จะไม่ใช่วิธีที่มันทำในเกม แต่ตอนนี้ฉัน ฉันเชื่อว่าวิธีการของฉันใกล้พอ


ข้อมูลเกี่ยวกับฮาร์ดแวร์ Nintendo 3DS: ลิงก์
KTC

ทางออกที่ดีมาก! คุณคิดอย่างไรในส่วนลึกใน shader ของคุณ? (ในกรณีที่เครื่องบินอยู่ตรงหน้าอีกทั้งคู่มีสภาพเหมือนกันดังนั้นจะไม่มีการวาดโครงร่าง)
58

@ingham กรณีนั้นเกิดขึ้นบ่อยครั้งในตัวละครออแกนิกที่ฉันไม่จำเป็นต้องจัดการและดูเหมือนว่าเกมจริงไม่ได้จัดการมันเหมือนกัน ในเกมจริงบางครั้งคุณสามารถเห็นโครงร่างหายไปเมื่อบรรทัดฐานเหมือนกัน แต่ฉันไม่คิดว่าคนทั่วไปจะสังเกตเห็นมัน
KTC

ฉันสงสัยเล็กน้อยเกี่ยวกับ 3DS ที่สามารถต่อสายเคเบิลเพื่อเรียกใช้เอฟเฟ็กต์แบบเต็มหน้าจอแบบ shader ได้เช่นเดียวกับที่ใช้ มันรองรับ shader เป็นพื้นฐาน (ถ้ามี)
ธารา

17

เอฟเฟกต์นี้เป็นเรื่องธรรมดาโดยเฉพาะอย่างยิ่งในเกมที่ใช้เอฟเฟ็กต์การแรเงา cel แต่จริงๆแล้วเป็นสิ่งที่สามารถใช้งานได้อย่างอิสระจากสไตล์การแรเงา cel

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

เทคนิคง่าย ๆ คือการสร้างภาพเงาเฉพาะขอบร่าง สิ่งนี้สามารถทำได้ง่ายๆเหมือนกับการเรนเดอร์โมเดลดั้งเดิมด้วย stencil write จากนั้นเรนเดอร์อีกครั้งในโหมด wireframe หนาซึ่งไม่มีค่า stencil เท่านั้น ดูที่นี่สำหรับตัวอย่างการใช้งาน

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

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

คุณสามารถค้นหาการสนทนารายละเอียดเพิ่มเติมและเอกสารด้วยตัวอย่างต่าง ๆ บนอินเทอร์เน็ต ตัวอย่างเช่น:


1
ฉันสามารถยืนยันได้ว่าวิธี stencil (จาก flipcode.com) ใช้งานได้และดูดีจริงๆ คุณสามารถกำหนดความหนาในพิกัดหน้าจอเพื่อให้ความหนาของโครงร่างไม่ได้ขึ้นอยู่กับขนาดของแบบจำลอง (หรือกับรูปร่างของแบบจำลอง)
Vegard

1
เทคนิคหนึ่งที่คุณไม่ได้กล่าวถึงคือเอฟเฟ็กต์การแรเงาขอบหลังการโพสต์มักใช้ร่วมกับ cel-shading ซึ่งมองหาพิกเซลที่มีค่าสูงdz/dxและ / หรือdz/dy
bcrist

8

วิธีที่ง่ายที่สุดในการทำเช่นนี้โดยทั่วไปกับฮาร์ดแวร์รุ่นเก่าก่อนพิกเซล / แฟรกเมนต์ส่วนและยังคงใช้บนมือถือคือการทำซ้ำแบบจำลองย้อนกลับลำดับจุดสุดยอดที่คดเคี้ยวเพื่อให้แบบจำลองแสดงภายใน (หรือหากคุณต้องการ ทำสิ่งนี้ในเครื่องมือสร้างสินทรัพย์ 3 มิติของคุณพูด Blender โดยพลิกบรรทัดฐานของพื้นผิว - สิ่งเดียวกัน) จากนั้นขยายสำเนาที่ซ้ำกันทั้งหมดรอบ ๆ จุดศูนย์กลางและในที่สุดสี / พื้นผิวนี้จะเป็นสีดำสนิท ผลลัพธ์นี้จะแสดงโครงร่างรอบโมเดลดั้งเดิมของคุณหากเป็นโมเดลที่เรียบง่ายเช่นคิวบ์ สำหรับแบบจำลองที่ซับซ้อนมากขึ้นที่มีรูปแบบแบบเว้า (เช่นในภาพด้านล่าง) จำเป็นต้องปรับแต่งแบบจำลองที่ซ้ำกันด้วยตนเองเพื่อให้ค่อนข้าง "อ้วนขึ้น" กว่ารุ่นเดิมเช่นMinkowski Sumในแบบ 3 มิติ คุณสามารถเริ่มต้นด้วยการกดจุดสุดยอดแต่ละจุดออกมาเล็กน้อยตามปกติเพื่อสร้างตาข่ายโครงร่างดังที่การแปลง Shrink / Fatten ของ Blender

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

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

ป้อนคำอธิบายรูปภาพที่นี่.


1
คุณช่วยอธิบายได้ไหมว่า "ขยายส่วนที่ซ้ำกันทั้งหมดรอบ ๆ กึ่งกลาง" เป็นไปตามภาพนี้ได้อย่างไรเนื่องจากการปรับขนาดรอบศูนย์อย่างง่ายจะไม่ทำงานกับแขนและส่วนอื่น ๆ ที่ไม่ได้มีศูนย์กลาง หลุมในนั้น
Kromster พูดว่าสนับสนุน Monica

@KromStern ในบางกรณีเซตย่อยของจุดยอดต้องถูกปรับขนาดด้วยมือเพื่อรองรับ แก้ไขคำตอบแล้ว
วิศวกร

1
เป็นเรื่องปกติที่จะเขยิบจุดยอดออกไปตามพื้นผิวในพื้นที่ของตนตามปกติ แต่สิ่งนี้อาจทำให้เส้นโครงร่างที่ขยายขยายออกไปตามขอบแข็ง
DMGregory

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

6

สำหรับรุ่นที่ราบรื่น (สำคัญมาก) เอฟเฟกต์นี้ค่อนข้างง่าย ในการแยกส่วน / พิกเซลของคุณคุณจะต้องมีปกติของส่วนที่แรเงา หากใกล้เคียงกับฉากตั้งฉาก ( dot(surface_normal,view_vector) <= .01- คุณอาจต้องเล่นกับขีด จำกัด นั้น) จากนั้นให้สีชิ้นส่วนสีดำแทนที่จะเป็นสีปกติ

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

ไฮไลต์จะอยู่ที่ส่วนใดส่วนหนึ่งของพื้นผิวที่มีการเปลี่ยนจากด้านหน้าไปด้านหลังรวมถึง "ขอบด้านใน" (เช่นขาบนโปเกมอนสีเขียวหรือหัวของมัน - เทคนิคอื่น ๆ จะไม่เพิ่มโครงร่างใด ๆ )

วัตถุที่มีขอบแข็งและไม่เรียบ (เช่นลูกบาศก์) จะไม่ได้รับไฮไลต์ในตำแหน่งที่ต้องการด้วยวิธีการนี้ นั่นหมายความว่าวิธีการนี้ไม่ใช่ตัวเลือกในบางกรณี ฉันไม่รู้ว่ารุ่นโปเกมอนนั้นราบรื่นหรือไม่


5

วิธีที่พบมากที่สุดที่ฉันเห็นสิ่งนี้คือการส่งเรนเดอร์ตัวที่สองในโมเดลของคุณ โดยพื้นฐานแล้วให้ทำซ้ำและพลิกบรรทัดฐานแล้วดันเข้าไปในจุดสุดยอด ใน shader ให้ปรับยอดจุดยอดแต่ละจุดตามปกติ ใน pixel / shader shader ให้วาดสีดำ นั่นจะทำให้คุณมีโครงร่างภายนอกและภายในเช่นรอบริมฝีปากตาและอื่น ๆ นี่คือการโทรที่ค่อนข้างถูกถ้าไม่มีอะไรที่ถูกกว่าการโพสต์โพสต์ขึ้นอยู่กับจำนวนรุ่นและความซับซ้อนของพวกเขา Guilty Gear Xrd ใช้วิธีนี้เพราะง่ายต่อการควบคุมความหนาของเส้นผ่านสีจุดสุดยอด

วิธีที่สองของการทำเส้นด้านในที่ฉันเรียนรู้จากเกมเดียวกัน ในแผนที่ UV จัดตำแหน่งพื้นผิวของคุณตามแนวแกน u หรือ v โดยเฉพาะในพื้นที่ที่คุณต้องการเส้นด้านใน ลากเส้นสีดำตามแนวแกนใดแกนหนึ่งแล้วเลื่อนพิกัด UV ของคุณเข้าหรือออกจากเส้นนั้นเพื่อสร้างเส้นด้านใน

ดูวิดีโอจาก GDC สำหรับคำอธิบายที่ดีกว่า: https://www.youtube.com/watch?v=yhGjCzxJV3E


5

อีกวิธีหนึ่งที่จะทำให้เค้าร่างคือการใช้แบบจำลองเวกเตอร์ปกติของเรา เวกเตอร์ปกติคือเวกเตอร์ที่ตั้งฉากกับพื้นผิวของมัน (ชี้ให้ห่างจากพื้นผิว) เคล็ดลับที่นี่คือการแยกแบบตัวละครของคุณเป็นสองส่วน จุดยอดที่หันหน้าเข้าหากล้องและจุดยอดที่หันออกจากกล้อง เราจะเรียกพวกเขาว่า FRONT และ BACK ตามลำดับ

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

ป้อนคำอธิบายรูปภาพที่นี่

Shader "Custom/OutlineShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Outline("Outline Thickness", Range(0.0, 0.3)) = 0.002
        _OutlineColor("Outline Color", Color) = (0,0,0,1)
    }

    CGINCLUDE
    #include "UnityCG.cginc"

    sampler2D _MainTex;
    half4 _MainTex_ST;

    half _Outline;
    half4 _OutlineColor;

    struct appdata {
        half4 vertex : POSITION;
        half4 uv : TEXCOORD0;
        half3 normal : NORMAL;
        fixed4 color : COLOR;
    };

    struct v2f {
        half4 pos : POSITION;
        half2 uv : TEXCOORD0;
        fixed4 color : COLOR;
    };
    ENDCG

    SubShader 
    {
        Tags {
            "RenderType"="Opaque"
            "Queue" = "Transparent"
        }

        Pass{
            Name "OUTLINE"

            Cull Front

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                half3 norm = mul((half3x3)UNITY_MATRIX_IT_MV, v.normal);
                half2 offset = TransformViewToProjection(norm.xy);
                o.pos.xy += offset * o.pos.z * _Outline;
                o.color = _OutlineColor;
                return o;
            }

            fixed4 frag(v2f i) : COLOR
            {
                fixed4 o;
                o = i.color;
                return o;
            }
            ENDCG
        }

        Pass 
        {
            Name "TEXTURE"

            Cull Back
            ZWrite On
            ZTest LEqual

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.color = v.color;
                return o;
            }

            fixed4 frag(v2f i) : COLOR 
            {
                fixed4 o;
                o = tex2D(_MainTex, i.uv.xy);
                return o;
            }
            ENDCG
        }
    } 
}

บรรทัดที่ 41: การตั้งค่า“ Cull Front” บอกให้ shader ทำการเลือกสรรบริเวณด้านหน้าของจุดยอด หมายความว่าเราจะไม่สนใจจุดยอดหันหน้าทั้งหมดในบัตรนี้ เราถูกทิ้งไว้กับด้านหลังที่เราต้องการจัดการเล็กน้อย

บรรทัดที่ 51-53: คณิตศาสตร์ของจุดยอดเคลื่อนที่ตามเวกเตอร์ปกติ

บรรทัดที่ 54: การตั้งค่าสีจุดยอดเป็นสีที่เราเลือกซึ่งกำหนดไว้ในคุณสมบัติเฉดสี

ลิงค์ที่มีประโยชน์: http://wiki.unity3d.com/index.php/Silhouette-Outlined_Diffuse


ปรับปรุง

ตัวอย่างอื่น

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

   Shader "Custom/CustomOutline" {
            Properties {
                _Color ("Color", Color) = (1,1,1,1)
                _Outline ("Outline Color", Color) = (0,0,0,1)
                _MainTex ("Albedo (RGB)", 2D) = "white" {}
                _Glossiness ("Smoothness", Range(0,1)) = 0.5
                _Size ("Outline Thickness", Float) = 1.5
            }
            SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200

                // render outline

                Pass {
                Stencil {
                    Ref 1
                    Comp NotEqual
                }

                Cull Off
                ZWrite Off

                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #include "UnityCG.cginc"
                    half _Size;
                    fixed4 _Outline;
                    struct v2f {
                        float4 pos : SV_POSITION;
                    };
                    v2f vert (appdata_base v) {
                        v2f o;
                        v.vertex.xyz += v.normal * _Size;
                        o.pos = UnityObjectToClipPos (v.vertex);
                        return o;
                    }
                    half4 frag (v2f i) : SV_Target
                    {
                        return _Outline;
                    }
                    ENDCG
                }

                Tags { "RenderType"="Opaque" }
                LOD 200

                // render model

                Stencil {
                    Ref 1
                    Comp always
                    Pass replace
                }


                CGPROGRAM
                // Physically based Standard lighting model, and enable shadows on all light types
                #pragma surface surf Standard fullforwardshadows
                // Use shader model 3.0 target, to get nicer looking lighting
                #pragma target 3.0
                sampler2D _MainTex;
                struct Input {
                    float2 uv_MainTex;
                };
                half _Glossiness;
                fixed4 _Color;
                void surf (Input IN, inout SurfaceOutputStandard o) {
                    // Albedo comes from a texture tinted by color
                    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                    o.Albedo = c.rgb;
                    // Metallic and smoothness come from slider variables
                    o.Smoothness = _Glossiness;
                    o.Alpha = c.a;
                }
                ENDCG
            }
            FallBack "Diffuse"
        }

ทำไมการใช้บัฟเฟอร์ stencil ในตัวอย่างที่อัพเดต?
ธารา

อ่าฉันเข้าใจแล้ว ตัวอย่างที่ 2 ใช้วิธีการที่จะสร้างโครงร่างภายนอกเท่านั้นซึ่งแตกต่างจากตัวอย่างแรก คุณอาจต้องการพูดถึงสิ่งนั้นในคำตอบของคุณ
ธารา

0

หนึ่งในวิธีที่ยอดเยี่ยมในการสร้างฉากของคุณบนพื้นผิวFramebufferเพื่อสร้างพื้นผิวนั้นในขณะที่ทำการกรอง Sobelในทุกพิกเซลซึ่งเป็นเทคนิคที่ง่ายสำหรับการตรวจจับขอบ วิธีนี้คุณไม่เพียง แต่สามารถทำให้ฉากเป็นพิกเซล (การตั้งค่าความละเอียดต่ำให้กับพื้นผิว Framebuffer) แต่ยังสามารถเข้าถึงทุกพิกเซลเพื่อทำให้ Sobel ทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.