Texture

Texture бол зүгээр л зураг юм. Дотроо пикселүүдээс бүрдэнэ, пиксел бол RGBA гэсэн дөрвөн утгаар өнгийг кодлож хадгалсан цэг.
Улаан Ногоон Хөх Альфа гэсэн дөрвөн утга харгалзан 8 бит хэрэглэнэ, нийлээд 8*4 = 32 bit хэрэглэнэ. 8 bit-ээр 2^8 = 256 ширхэг төлөвийг илэрхийлж болно. тэгвэл RGB нь 256*256*256 буюу 16777216 ширхэг өнгийг нэг пиксел дээр дүрслэх боломжтой. Ийм олон өнгийн комбинац нь бидний нүдний харж чадах спектрийн хүрээн хангалттай юм.
Олон янзын зургийн формат байх бөгөөд зургийн файлын чанарыг хамгийн бага алдагдалтайгаар шахах алгоритмаараа хоорондоо ялгаатай. Тиймээс зургийн файлыг таниж форматын дагуу уншиж чадвартай програмчлалын сан ашиглах хэрэгтэй.



3D модел, 2D чарактер tile гэх мэт бүгдээрээ өөрсдийн деталиа дүрслэж харуулахын тулд зургийн файл хэрэглэдэг.

Texture Buffer
buffer бол график картны санах ойн дээр үүсгэсэн хэсэг зай юм. Текстурыг ашиглахын тулд өгөгдлийг нь график картруу хуулах хэрэгтэй. OpenGL-ийн функцүүдээр энэ санах ойруу маш түргэн хандах боломжтой.

SOIL санг ашиглаж зураг ачаалах
Эхлээд зургын файлыг файл системээс уншиж програмын үндсэн санах ойд хадгалж авах хэрэгтэй. img_width болон img_height хувьсагчидад зургийн өргөн болон өндөрийн уртын утгыг авна. Хэмжээс нь пикселийн тоогоор хэмжигдэнэ. 60 пикселийн өндөртэй 40 пикселийн өргөнтэй гэх мэт.

int img_width, img_height;
unsigned char* img = SOIL_load_image("texture.png", &img_width, &img_height, NULL, 0);

График картны санах ой дээр нь нэг хоосон slot авах хэрэгтэй. texture_id хувьсагч нь тэр slot-ийн дугаарыг илтгэнэ. slot дугаар буюу texture_id нь график картны санах ой дээрхи текстуруудыг дугаарлаж үүсгэх зориулалттай ID юм. glGenTexture нь үүсгэх текстурын тоо ширхэгийг оролтын параметр утга болгож аваад тэр тоон хэмжээгээр нь slot авч харгалзах дугааруудыг нь id болгон буцаана. texture_id нь массив байж болно.

glGenTextures(1, &texture_id);

текстуртэй ажиллахын тулд үүсгэсэн slot дээр тулж ажиллана шүү гэдгийгээ график картруу хэлж мэдэгдэх хэрэгтэй

glBindTexture(GL_TEXTURE_2D, texture_id);

мөн текстур зургийг ямар байдлаар хэрэглэх хэрэгтэй гэдгийг илтгэх параметр тохируулж өгнө.

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Ингээд текстур slot-оо тохируулсан бол slot-даа харгалзах GPU санах ойруу програмын үндсэн санах ой дээр байгаа текстурын өгөгдлийг хуулж хийнэ.

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img_width, img_height, 0, GL_RGB, GL_UNSIGNED_BYTE, img);

Ингээд texture_id буюу график картны санах ой дээрхи текстур зургийн id-г ашиглан програмчлалаа хийх боломжтой. Үүний тулд энэ текстурыг арай өндөр хурдаар хандах боломжтой текстур байгууламжруу тохируулж өгөх шаардлагатай. 0-р байгууламжийг хэрэглэнэ шүү гэдгийг зааж өгөх.

glActivateTexture(GL_TEXTURE0);

Энэ байгууламж дээр texture_id аа холбож өгөх хэрэгтэй.

glBindTexture(GL_TEXTURE_2D, texture_id);

Ингээд текстур зургаа текстур байгууламжтайгаа холбосон бол shader програмд ашиглахад бэлэн болсон гэсэн үг.
текстурээ shader програм буюу GPU дээр ажиллаж байгаа програмруу параметр болгон дамжуулах байдлаар ашиглана.

үндсэн програмаас GPU програмруу параметр дамжуулж ашигладаг хувьсагчийг uniform хувьсагч гэж нэрлэдэг.

uniform утга дамжуулахын тулд shader програмын параметр авах байрлалыг нь эхлэн мэдэх хэрэгтэй. mytexture нь shader програм дотор текстурыг төлөөлөн ашиглагдаж байгаа хувьсагчийн нэр юм. uniform_mytexture нь shader програмын оролтын параметр жагсаалтын аль байрлалд "mytexture" хувьсагч байгааг илтгэнэ.

uniform_mytexture = glGetUniformLocation(program_id, "mytexture")

юниформ утга дамжуулахдаа glUniform1i функц ашиглана. Энэ нь 1 ширхэг integer буюу бүхэл тоог дамжуулж байгааг илтгэж байна. uniform_mytexture буюу shader програмын текстур ашиглах параметр хувьсагчийн байрлалд texture unit-ийн дугаарыг дамжуулж өгнө. 0 гэж дамжуулсан байвал GL_TEXTURE0 дээр харгалзах текстурыг shader програм хэрэглэнэ гэдгийг илтгэнэ.

glUniform1i(uniform_mytexture, 0);


[сүүлд нэмэв]
SOIL ашиглан зургийн файл ачаалах
OpenGL-д SOIL хэмээх зураг ачаалах санг ашиглаж хэрхэн текстур зураг ачаалдаг код сниппет бичнэ.

#ifndef TEXTURE_H_
#define TEXTURE_H_

#include "common.h"

class Texture {
public:
    Texture(GLenum textureTarget, const std::string& fileName);
    ~Texture();

    bool Load2GPU();
    void DeleteFromGPU();

    void Bind(GLenum textureUnit);

    GLint width;
    GLint height;

    std::string fileName;
    GLenum textureTarget;
    GLuint textureID;
};

#endif /* TEXTURE_H_ */


#include "Texture.h"

Texture::Texture(GLenum textureTarget, const std::string& fileName) {
    this->textureTarget = textureTarget;
    this->fileName      = fileName;
}

Texture::~Texture() {
}

bool Texture::Load2GPU() {
    int channel = 0;
    unsigned char* image = SOIL_load_image
    (
        fileName.c_str(),
        &width,
        &height,
        &channel,
        SOIL_LOAD_AUTO
    );
    if (NULL==image) {
        return false;
    }
    textureID = SOIL_create_OGL_texture
    (
        image,
        width, height, channel,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_MIPMAPS         |
        SOIL_FLAG_INVERT_Y        |
        SOIL_FLAG_NTSC_SAFE_RGB   |
        SOIL_FLAG_COMPRESS_TO_DXT
    );
    SOIL_free_image_data(image);
    return true;
}

void Texture::DeleteFromGPU() {
    glDeleteTextures(1, &textureID);
}

void Texture::Bind(GLenum textureUnit) {
    glActiveTexture(textureUnit);
    glBindTexture(textureTarget, textureID);
}


Дээрхи классыг ашиглахдаа :
Texture *texture;

// үүсгэхдээ 
std::string path = "/data/images/picture.png";
texture = new Texture(GL_TEXTURE_2D, path.c_str());
texture->Load2GPU();

// дуудаж ашиглахдаа
glUseProgram(programID);
texture->Bind(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(programID,"utexture"), 0);

// хэрэглэж дууссаныхаа буюу классын устгагч функц ч юмуу
// аль нэг газраа нөөцийг чөлөөлөхдөө
texture->DeleteFromGPU();

Popular posts from this blog

Apache Spark + Cassandra. Hello World