OpenGL SubTexturing

OpenGL SubTexturing

Επεξεργασία: Χρησιμοποιήστε το glPixelStorei. Το χρησιμοποιείτε για να ορίσετε GL_UNPACK_ROW_LENGTH στο πλάτος (σε pixel) ολόκληρης της εικόνας. Στη συνέχεια καλείτε το glTexImage2D (ή οτιδήποτε άλλο), περνώντας το έναν δείκτη στο πρώτο pixel της δευτερεύουσας εικόνας και στο πλάτος και το ύψος της δευτερεύουσας εικόνας.

Μην ξεχάσετε να επαναφέρετε το GL_UNPACK_ROW_LENGTH στο 0 όταν τελειώσετε με αυτό.

Δηλαδή:

glPixelStorei( GL_UNPACK_ROW_LENGTH, img_width );
char *subimg = (char*)m_data + (sub_x + sub_y*img_width)*4;
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, subimg );
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );

Ή, εάν είστε αλλεργικοί στα μαθηματικά του δείκτη:

glPixelStorei( GL_UNPACK_ROW_LENGTH, img_width );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, sub_x );
glPixelStorei( GL_UNPACK_SKIP_ROWS, sub_y );

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data );

glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );

Επεξεργασία2: Για λόγους πληρότητας, θα πρέπει να επισημάνω ότι εάν χρησιμοποιείτε OpenGL-ES, τότε δεν λαμβάνετε GL_UNPACK_ROW_LENGTH . Σε αυτήν την περίπτωση, θα μπορούσατε είτε (α) να εξαγάγετε την δευτερεύουσα εικόνα σε ένα νέο buffer μόνοι σας ή (β)...

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTES, NULL );

for( int y = 0; y < sub_height; y++ )
{
    char *row = m_data + ((y + sub_y)*img_width + sub_x) * 4;
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, y, sub_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row );
}

Για όσους έχουν κολλήσει με το OpenGL ES 1.1/2.0 το 2018 και αργότερα, έκανα μερικές δοκιμές με διαφορετικές μεθόδους για την ενημέρωση μέρους της υφής από δεδομένα εικόνας (η εικόνα έχει το ίδιο μέγεθος με την υφή).

Μέθοδος 1: Αντιγράψτε ολόκληρη την εικόνα με το glTexImage2D :

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels );

Μέθοδος 2: Αντιγράψτε ολόκληρη την εικόνα με το glTexSubImage2D :

glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels );

Μέθοδος 3: Αντιγράψτε μέρος της εικόνας, γραμμή προς γραμμή σε βρόχο:

auto *ptr = m_Pixels + (x + y * mWidth) * 4;
for( int i = 0; i < h; i++, ptr += mWidth * 4 ) {
    glTexSubImage2D( GL_TEXTURE_2D, 0, x, y+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr );
}

Μέθοδος 4: Αντιγράψτε ολόκληρο το πλάτος της εικόνας, αλλά κατακόρυφα αντιγράψτε μόνο μέρος που έχει αλλάξει:

auto *ptr = m_Pixels + (y * mWidth) * 4;
glTexSubImage2D( GL_TEXTURE_2D, 0, 0, y, mWidth, h, GL_RGBA, GL_UNSIGNED_BYTE, ptr );

Και εδώ είναι τα αποτελέσματα της δοκιμής που έγινε σε υπολογιστή, ενημερώνοντας κατά 100.000 φορές διάφορα μέρη της υφής που ήταν περίπου το 1/5 του μεγέθους ολόκληρης της υφής.

  • Μέθοδος 1 - 38,17 δευτ.
  • Μέθοδος 2 - 26,09 δευτ.
  • Μέθοδος 3 - 54,83 δευτερόλεπτα - πιο αργή
  • Μέθοδος 4 - 5,93 δευτερόλεπτα - νικητής

Δεν αποτελεί έκπληξη το γεγονός ότι η μέθοδος 4 είναι ταχύτερη, καθώς αντιγράφει μόνο μέρος της εικόνας και το κάνει με μία κλήση στη συνάρτηση glTex...().