ทั้งหมดเกี่ยวกับวัตถุ OpenGL
โมเดลมาตรฐานสำหรับอ็อบเจ็กต์ OpenGL มีดังนี้
วัตถุมีสถานะ คิดว่าเป็นไฟล์struct
. ดังนั้นคุณอาจมีวัตถุที่กำหนดไว้เช่นนี้:
struct Object
{
int count;
float opacity;
char *name;
};
วัตถุมีค่าบางอย่างเก็บไว้ในนั้นและจะมีรัฐ วัตถุ OpenGL ก็มีสถานะเช่นกัน
กำลังเปลี่ยนสถานะ
ใน C / C ++ หากคุณมีอินสแตนซ์ประเภทObject
คุณจะเปลี่ยนสถานะดังต่อไปนี้: obj.count = 5;
คุณจะอ้างอิงอินสแตนซ์ของวัตถุโดยตรงรับสถานะเฉพาะที่คุณต้องการเปลี่ยนแปลงและใส่ค่าลงไป
ใน OpenGL คุณจะไม่ทำสิ่งนี้
ด้วยเหตุผลเดิมที่ดีกว่าไม่ได้อธิบายไว้ในการเปลี่ยนสถานะของอ็อบเจ็กต์ OpenGL คุณต้องผูกมันกับบริบทก่อน สิ่งนี้ทำได้ด้วยบางส่วนจากการglBind*
โทร
เทียบเท่า C / C ++ มีดังนี้:
Object *g_objs[MAX_LOCATIONS] = {NULL};
void BindObject(int loc, Object *obj)
{
g_objs[loc] = obj;
}
พื้นผิวมีความน่าสนใจ พวกเขาเป็นตัวแทนของกรณีพิเศษของการผูกมัด การglBind*
เรียกจำนวนมากมีพารามิเตอร์ "target" สิ่งนี้แสดงถึงตำแหน่งที่แตกต่างกันในบริบท OpenGL ที่สามารถผูกวัตถุประเภทนั้นได้ ตัวอย่างเช่นคุณสามารถผูกอ็อบเจ็กต์ framebuffer สำหรับการอ่าน ( GL_READ_FRAMEBUFFER
) หรือสำหรับการเขียน ( GL_DRAW_FRAMEBUFFER
) สิ่งนี้มีผลต่อวิธีที่ OpenGL ใช้บัฟเฟอร์ นี่คือสิ่งที่loc
พารามิเตอร์ด้านบนแสดงถึง
พื้นผิวมีความพิเศษเนื่องจากเมื่อคุณผูกเข้ากับเป้าหมายเป็นครั้งแรกพวกเขาจะได้รับข้อมูลพิเศษ เมื่อคุณผูกพื้นผิวเป็นครั้งแรกGL_TEXTURE_2D
คุณกำลังตั้งค่าสถานะพิเศษในพื้นผิว คุณกำลังบอกว่าพื้นผิวนี้เป็นพื้นผิว 2 มิติ และจะเป็นพื้นผิว 2 มิติเสมอ สถานะนี้ไม่สามารถเปลี่ยนแปลงได้ตลอดไป ถ้าคุณมีพื้นผิวที่ถูกผูกไว้ครั้งแรกในฐานะที่GL_TEXTURE_2D
คุณต้องเสมอผูกเป็นGL_TEXTURE_2D
; พยายามผูกมันเนื่องจากGL_TEXTURE_1D
จะทำให้เกิดข้อผิดพลาด (ขณะรันไทม์)
เมื่อวัตถุถูกผูกไว้แล้วสถานะของมันสามารถเปลี่ยนแปลงได้ สิ่งนี้ทำได้ผ่านฟังก์ชันทั่วไปเฉพาะสำหรับวัตถุนั้น พวกเขาก็ใช้ตำแหน่งที่แสดงถึงวัตถุที่จะแก้ไขเช่นกัน
ใน C / C ++ จะมีลักษณะดังนี้:
void ObjectParameteri(int loc, ObjectParameters eParam, int value)
{
if(g_objs[loc] == NULL)
return;
switch(eParam)
{
case OBJECT_COUNT:
g_objs[loc]->count = value;
break;
case OBJECT_OPACITY:
g_objs[loc]->opacity = (float)value;
break;
default:
//INVALID_ENUM error
break;
}
}
สังเกตว่าฟังก์ชันนี้ตั้งค่าสิ่งที่เกิดขึ้นเป็นloc
ค่าที่ถูกผูกไว้ในปัจจุบันอย่างไร
glTexParameter
สำหรับวัตถุพื้นผิวรัฐเนื้อหลักเปลี่ยนฟังก์ชั่น ฟังก์ชันอื่น ๆ เท่านั้นที่เปลี่ยนสถานะพื้นผิวคือglTexImage
ฟังก์ชันและรูปแบบต่างๆ ( glCompressedTexImage
, glCopyTexImage
ล่าสุดglTexStorage
) ต่าง ๆSubImage
รุ่นที่เปลี่ยนเนื้อหาของเนื้อ แต่พวกเขาไม่ได้ในทางเทคนิคเปลี่ยนของรัฐ Image
ฟังก์ชั่นการจัดเก็บข้อมูลการจัดสรรพื้นผิวและกำหนดรูปแบบพื้นผิวของ; SubImage
ฟังก์ชั่นเพียงคัดลอกพิกเซลรอบ ๆ นั่นไม่ถือว่าเป็นสถานะของพื้นผิว
อนุญาตให้ฉันทำซ้ำ: นี่เป็นฟังก์ชันเดียวที่แก้ไขสถานะพื้นผิว glTexEnv
ปรับเปลี่ยนสถานะสภาพแวดล้อม มันไม่ส่งผลกระทบต่อสิ่งที่เก็บไว้ในวัตถุพื้นผิว
พื้นผิวที่ใช้งานอยู่
สถานการณ์ของพื้นผิวมีความซับซ้อนมากขึ้นอีกครั้งด้วยเหตุผลทางมรดกที่ดีที่สุดที่ยังไม่เปิดเผย นี่คือที่glActiveTexture
มา
สำหรับพื้นผิวที่มีไม่ได้เป็นเพียงเป้าหมาย ( GL_TEXTURE_1D
, GL_TEXTURE_CUBE_MAP
ฯลฯ ) นอกจากนี้ยังมีเนื้อหน่วย ในตัวอย่าง C / C ++ ของเราสิ่งที่เรามีคือ:
Object *g_objs[MAX_OBJECTS][MAX_LOCATIONS] = {NULL};
int g_currObject = 0;
void BindObject(int loc, Object *obj)
{
g_objs[g_currObject][loc] = obj;
}
void ActiveObject(int currObject)
{
g_currObject = currObject;
}
สังเกตว่าตอนนี้เราไม่เพียง แต่มีรายการ 2 มิติObject
เท่านั้น แต่เรายังมีแนวคิดของวัตถุปัจจุบัน เรามีฟังก์ชั่นในการตั้งค่าวัตถุปัจจุบันเรามีแนวคิดเกี่ยวกับจำนวนสูงสุดของวัตถุปัจจุบันและฟังก์ชันการจัดการวัตถุทั้งหมดของเราจะได้รับการปรับให้เลือกจากวัตถุปัจจุบัน
เมื่อคุณเปลี่ยนวัตถุที่ใช้งานอยู่คุณจะเปลี่ยนชุดเป้าหมายทั้งหมด ดังนั้นคุณสามารถผูกสิ่งที่เข้ากับวัตถุปัจจุบัน 0 เปลี่ยนเป็นวัตถุปัจจุบัน 4 และจะแก้ไขวัตถุที่แตกต่างกันโดยสิ้นเชิง
การเปรียบเทียบกับวัตถุพื้นผิวนี้สมบูรณ์แบบ ... เกือบ
ดูglActiveTexture
ไม่ใช้จำนวนเต็ม จะใช้เวลาการแจงนับ ซึ่งในทางทฤษฎีหมายความว่ามันสามารถใช้อะไรจากการGL_TEXTURE0
GL_TEXTURE31
แต่มีสิ่งหนึ่งที่คุณต้องเข้าใจ:
นี่คือความผิด!
ช่วงที่เกิดขึ้นจริงที่สามารถใช้เวลาอยู่ภายใต้glActiveTexture
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
นั่นคือจำนวนสูงสุดของมัลติเท็กซ์เจอร์พร้อมกันที่การใช้งานอนุญาต สิ่งเหล่านี้แบ่งออกเป็นกลุ่มที่แตกต่างกันสำหรับขั้นตอนการสร้างเงา ตัวอย่างเช่นบนฮาร์ดแวร์คลาส GL 3.x คุณจะได้รับพื้นผิวจุดสุดยอด 16 พื้นผิวส่วนเงา 16 ส่วนและพื้นผิวรูปทรงเรขาคณิต 16 แบบ ดังนั้นGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
จะเป็น 48
แต่ไม่มีผู้แจงนับ 48 คน ซึ่งเป็นเหตุผลที่glActiveTexture
ไม่ใช้ตัวแจงนับ ที่ถูกต้องวิธีการเรียกร้องglActiveTexture
ดังต่อไปนี้:
glActiveTexture(GL_TEXTURE0 + i);
ซึ่งi
เป็นตัวเลขระหว่าง 0 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
และ
การแสดงผล
แล้วทั้งหมดนี้เกี่ยวข้องกับการเรนเดอร์อย่างไร?
เมื่อใช้เฉดสีคุณตั้งค่าเครื่องแบบแซมเปิลของคุณเป็นหน่วยภาพพื้นผิว (หน่วยภาพglUniform1i(samplerLoc, i)
อยู่ที่ไหนi
) glActiveTexture
ที่แสดงถึงหมายเลขที่คุณใช้กับ ตัวอย่างจะเลือกเป้าหมายตามประเภทตัวอย่าง ดังนั้นsampler2D
จะเลือกจากGL_TEXTURE_2D
เป้าหมาย นี่เป็นสาเหตุหนึ่งที่ทำให้แซมเปิลมีประเภทต่างๆ
ตอนนี้ฟังดูน่าสงสัยเช่นคุณสามารถมี GLSL samplers สองตัวโดยประเภทต่างๆที่ใช้หน่วยภาพพื้นผิวเดียวกัน แต่คุณทำไม่ได้ OpenGL ห้ามสิ่งนี้และจะทำให้คุณมีข้อผิดพลาดเมื่อคุณพยายามแสดงผล
GL_TEXTURE0 + i
- ฉันหมายถึงการตรวจสอบค่า enum เพื่อดูว่าถูกต้องหรือไม่ และย่อหน้าสุดท้าย - ไม่รู้ว่าถูกกฎหมายหรือไม่ ยอดเยี่ยม! ฉันบุ๊กมาร์กคำตอบทั้งหมดของคุณเพื่อให้สามารถอ้างอิงได้อีกครั้ง