ตรวจสอบรูปแบบพื้นผิว OpenGL ที่สนับสนุนได้อย่างไร


10

ตัวอย่างเช่นวิธีตรวจสอบว่า videocard ของฉันไม่รองรับ "bgr8" และแปลงเป็นรูปแบบอื่นเช่น "rgba8" ในโหมดซอฟต์แวร์

UPDATE: ขออภัยในความสับสน คำถามนี้เพิ่มเติมเกี่ยวกับสถานการณ์เมื่อฉันตั้งค่าinternalFormatในglTexImage2Dเป็นอย่าง "bgra8" แต่ videodriver แปลงข้อมูลภายในเป็นรูปแบบอื่นเช่น "rgba8"

คำตอบ:


11

คำถามของคุณดูเหมือนจะสร้างความสับสนให้กับแนวคิดบางอย่างดังนั้นเรามาทำสิ่งต่าง ๆ จากด้านบน นี่คือนิยามของฟังก์ชันglTexImage2D:

void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );

มีสองสิ่งที่คุณอาจเรียกว่า "รูปแบบพื้นผิว" แรกคือinternalformatพารามิเตอร์ นี่คือรูปแบบที่แท้จริง ของภาพที่ OpenGL เก็บไว้ formatพารามิเตอร์อธิบายส่วนหนึ่งของรูปแบบของข้อมูลพิกเซลที่คุณให้กับdataพารามิเตอร์

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

รูปแบบของภาพพื้นผิวต้องไม่มี "bgr8" ไม่มีตัวระบุรูปแบบภาพ GL_BGR8 มีเป็น enum GL_BGR แต่ที่เป็นสำหรับรูปแบบการถ่ายโอนพิกเซลไม่ใช่รูปแบบภาพ

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

ไม่มีวิธีที่จะบอกได้ว่าพารามิเตอร์รูปแบบการถ่ายโอนพิกเซลชุดใดชุดหนึ่งตรงกับวิธีการใช้งาน OpenGL จะเก็บไว้ในรูปแบบภาพหรือไม่

มีวิธีบอกตอนนี้ และโดย "ตอนนี้" ฉันหมายถึงใน OpenGL 4.3 และ / หรือ ARB_internalformat_query2 มาถึงการ์ดกราฟิกใกล้บ้านคุณ:

GLenum format, type;
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &format);
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &type);

formatและtypeตอนนี้มีการใช้งานที่ต้องการformatและtypeสำหรับการglTex(Sub)ImageโทรไปยังGL_RGBA8รูปภาพ มีแยกต่างหากformatและtypeแบบสอบถามสำหรับการglReadPixelsดาวน์โหลด

มีคำสั่งอื่น ๆ ที่คุณสามารถทำให้

หากคุณไม่สามารถเข้าถึงสิ่งเหล่านี้คุณสามารถใช้กฎทั่วไปของหัวแม่มือที่ฮาร์ดแวร์ส่วนใหญ่จะปฏิบัติตาม:

  • จะเก็บข้อมูลพิกเซลสำหรับข้อมูล 8 บิตต่อช่องตามลำดับ BGRA ดังนั้นหากคุณต้องการเพื่อให้ตรงกับรูปแบบที่มีข้อมูลพิกเซลของคุณเพื่อให้เป็นไปอย่างรวดเร็วยิ่งขึ้นอัปโหลดข้อมูลพื้นผิวที่คุณต้องการใช้GL_BGRAสำหรับformatและGL_UNSIGNED_INT_8888หรือสำหรับGL_UNSIGNED_BYTEtype
  • จะไม่เก็บสี 24 บิตเป็น 24 บิต มันจะเอามันออกไปเป็น 32- บิต; อัลฟาจะถูกละเว้นเมื่อมันอ่านข้อมูล ดังนั้นหากคุณต้องการจับคู่รูปแบบให้ใช้GL_BGRA formatกับGL_RGB8รูปแบบรูปภาพทุกครั้งแม้ว่าคุณจะต้องใส่ข้อมูลจำลองในองค์ประกอบอัลฟา

4
ฉันพบว่ายังใช้รูปแบบที่ดีกว่า GL_BGRA ด้วย internalFormat GL_RGBA http.download.nvidia.com/developer/Papers/2005//
KindDragon

ฉันจะละเว้นจากการ rebranding พารามิเตอร์ internalFormat เป็น "รูปแบบภาพ" เพราะมันทำให้สับสน อาจเหมาะสมที่จะคิดว่า "internalFormat" เป็น "รูปแบบพิกเซลพื้นผิว" การรวมกันของพารามิเตอร์ "format" และ "type" คือ "รูปแบบพิกเซลแหล่งที่มา" (ซึ่งมักจะเป็นรูปภาพดังนั้นความคิดเห็นของฉัน) และแน่นอนว่ามีรูปแบบ GPU ซึ่งก็คือ BGRA สำหรับรูปแบบชนิดจำนวนเต็ม
StarShine

6

โดยทั่วไปฮาร์ดแวร์ส่วนใหญ่จะไม่สนับสนุนรูปแบบพื้นผิว 3 ส่วนประกอบดังนั้นในตัวอย่างเฉพาะนี้คุณสามารถใช้สมมติฐานที่ปลอดภัยว่ามีการแปลง พื้นผิว OpenGL 3 องค์ประกอบเป็นจริง 4 องค์ประกอบในฮาร์ดแวร์ แต่ด้วยส่วนประกอบ alpha ที่ละเว้น / ตั้งเป็น 255 / อะไรก็ตาม

https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (หน้า "ข้อผิดพลาดทั่วไป" นั้นเป็นทองคำ - บุ๊คมาร์คตอนนี้!)

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

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

จริงๆแล้วมันเป็นกฎง่ายๆที่มีประโยชน์ในการตรวจสอบสิ่งที่คุณทำใน OpenGL ด้วยเอกสาร D3D ถ้า D3D ไม่สามารถทำอะไรบางอย่างได้แสดงว่าเป็นสิ่งที่ไม่ดีในฮาร์ดแวร์ ไม่จริงเสมอไป แต่เป็นจุดเริ่มต้นที่มีประโยชน์

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