Saya mencoba memahami perbedaan antara menggunakan GL_INT_2_10_10_10_REV untuk normal data saya V.S. GLbyte . Saat ini saya sedang memuat normal saya ke dalam glm::vec4 dan saya mengemasnya seperti ini:

int32_t floatToSignedNormalizedByte(float x, float y, float z, float w)
{
    int32_t result = 0;
    const int16_t maxValue = static_cast<int16_t>(std::numeric_limits<int8_t>::max());
    const int16_t negativeValueScale = maxValue + 1;

    result |= static_cast<int8_t>(x < 0 ? x * negativeValueScale : x * maxValue);
    result |= static_cast<int8_t>(y < 0 ? y * negativeValueScale : y * maxValue) << 8;
    result |= static_cast<int8_t>(z < 0 ? z * negativeValueScale : z * maxValue) << 16;
    result |= static_cast<int8_t>(w < 0 ? w * negativeValueScale : w * maxValue) << 24;

    return result;
}

Dengan paket normal, saya kemudian akan menelepon:

//Location, component count, type, normalized, stride, offset
glVertexAttribPointer(location, 4, GL_BYTE, true, format.getVertexSize(),  format.getFieldOffset(field, dataBasePtr));

Pertanyaan saya adalah, mengingat cara saya mengemas normal, haruskah saya menggunakan GL_INT_2_10_10_10_REV sebagai tipe saya (menggantikan GL_BYTE)? Saya mengerti menggunakan GL_INT_2_10_10_10_REV berarti setiap komponen mendapat 10 bit, bukan 8 dan itu bagus karena saya hanya membutuhkan komponen xyz. Mana yang lebih baik dan mengapa? Jika saya menggunakan GL_INT_2_10_10_10_REV, saya kira jumlah komponen masih 4?

1
ChaoSXDemon 27 November 2017, 21:51

1 menjawab

Jawaban Terbaik

Mengapa

Seperti yang Anda katakan, menggunakan 10_10_10_2 akan memberi Anda 10 bit per komponen yang berarti (xyz) sementara menyisakan 2 bit untuk komponen w yang tidak berguna untuk vektor normal. Dengan 10 bit Anda memiliki 2^10 kemungkinan nilai diskrit untuk x, y dan z, bukan nilai 2^8 yang disediakan oleh 8 bit. Oleh karena itu, ini akan memberi Anda nilai yang lebih akurat untuk gradien normal dan halus. Anda juga bisa menggunakan nilai floating-point, tetapi ini akan membutuhkan lebih banyak memori dan kemungkinan akan lebih lambat. Ini menjawab bagian "mengapa saya harus melakukan ini".

Bagaimana

Adapun "bagaimana", fungsi pengemasan Anda saat ini mengubah setiap float menjadi bilangan bulat 8 bit. Anda perlu mengubah ini untuk mengubah komponen x, y dan z dalam bilangan bulat 10 bit dan mengemas bit-bit tersebut bersama-sama dengan 01 sebagai 2 bit terakhir (komponen w). Versi REV memungkinkan Anda untuk menentukan komponen dalam urutan terbalik (wzyx).

Info lebih lanjut tentang GL_INT_2_10_10_10_REV format simpul

Tabel 10.3 dan 10.4 dari spesifikasi OpenGL menjelaskan bagaimana komponen-komponen ini diletakkan dalam kata 32-bit:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             z               |              y              |         x         |

Table 10.3: Packed component layout for non-BGRA formats. Bit numbers are indicated for each component.

UNSIGNED_INT_2_10_10_10_REV:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             x               |              y              |         z         |

Table 10.4: Packed component layout for BGRA format. Bit numbers are indicated for each component.

Seperti yang Anda lihat, ada 4 komponen dalam format vertex ini.

Anda mungkin juga menemukan spesifikasi GL_ARB_vertex_type_2_10_10_10_rev bacaan yang menarik jika Anda ingin lebih banyak latar belakang:

Dua format data atribut simpul baru: format data simpul 2.10.10.10 bertanda dan format data simpul 2.10.10.10 tidak bertanda. Format data vertex ini menggambarkan aliran 4 komponen yang dapat digunakan untuk menyimpan normal atau atribut lainnya dalam bentuk terkuantisasi. Normal, tangen, binormal, dan atribut vertex lainnya sering kali dapat ditentukan pada presisi yang dikurangi tanpa memperkenalkan artefak yang terlihat, mengurangi jumlah memori dan bandwidth memori yang mereka konsumsi.

"Presisi berkurang" mengacu pada penggunaan bilangan bulat 10 bit alih-alih nilai setengah float (16 bit) atau float (32 bit) untuk normal. Memiliki lebih sedikit bit per simpul dapat memberikan kinerja yang lebih baik karena tahap perakitan simpul membutuhkan bandwidth memori yang lebih sedikit.

Pertanyaan ini juga memiliki info yang relevan: Menggunakan GL_INT_2_10_10_10_REV di glVertexAttribPointer( )

2
bernie 28 November 2017, 14:30