Sök…


Grunderna i textureringen

En struktur är en form av datalagring som tillåter bekväm åtkomst, inte bara till specifika datainmatningar, utan också till sampelpunkter som blandar (interpolerar) flera poster tillsammans.

I OpenGL kan strukturer användas för många saker, men oftast är det att kartlägga en bild till en polygon (till exempel en triangel). För att kartlägga strukturen till en triangel (eller annan polygon) måste vi berätta för varje toppunkt vilken del av strukturen den motsvarar. Vi tilldelar en texturskoordinat till varje topp av en polygon och den interpoleras sedan mellan alla fragment i den polygonen. Texturkoordinater sträcker sig vanligtvis från 0 till 1 i x- och y-axeln, som visas på bilden nedan:

texturkoordinater

Strukturkoordinaterna för den här triangeln skulle se ut så här:

GLfloat texCoords[] = {
    0.0f, 0.0f,  // Lower-left corner  
    1.0f, 0.0f,  // Lower-right corner
    0.5f, 1.0f   // Top-center corner
};

Sätt de koordinaterna i VBO (vertexbuffertobjekt) och skapa ett nytt attribut för skuggaren. Du bör redan ha minst ett attribut för toppunktpositionerna så skapa ett annat för texturkoordinaterna.


Generera konsistens

Det första som ska göras är att generera ett texturobjekt som kommer att refereras av ett ID som kommer att lagras i en osignerad int- struktur :

GLuint texture;
glGenTextures(1, &texture); 

Efter det måste den bindas så att alla efterföljande texturkommandon konfigurerar denna textur:

glBindTexture(GL_TEXTURE_2D, texture); 

Laddar bild

För att ladda en bild kan du skapa din egen bildläsare eller använda ett bildbelastningsbibliotek som SOIL (Simple OpenGL Image Library) i c ++ eller TWL: s PNGDecoder i java.

Ett exempel på att ladda bild med SOIL skulle vara:

int width, height;
unsigned char* image = SOIL_load_image("image.png", &width, &height, 0, SOIL_LOAD_RGB); 

Nu kan du tilldela denna bild till texturobjektet:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

Efter det bör du ta bort texturobjektet:

glBindTexture(GL_TEXTURE_2D, 0); 

Radera parameter för texturkoordinater

Som ses ovan har det nedre vänstra hörnet av strukturen UV (st) -koordinaterna (0, 0) och det övre högra hörnet av strukturen har koordinaterna (1, 1), men strukturens koordinater kan vara i valfritt område. För att hantera detta måste det definieras hur texturkoordinaterna lindas till strukturen.

Wrap-parametern för texturkoordinaten kan ställas in med glTextureParameter med GL_TEXTURE_WRAP_S , GL_TEXTURE_WRAP_T och GL_TEXTURE_WRAP_R .

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

De möjliga parametrarna är:

  • GL_CLAMP_TO_EDGE gör att texturkoordinaterna fastklämmas till intervallet [1 / 2N, 1 - 1 / 2N] , där N är storleken på texturen i riktningen.

  • GL_CLAMP_TO_BORDER gör samma sak som GL_CLAMP_TO_EDGE , men i de fall GL_CLAMP_TO_EDGE den hämtade texeldata med den färg som anges av GL_TEXTURE_BORDER_COLOR .

  • GL_REPEAT gör att heltalets del av texturkoordinaten ignoreras. Konsistensen är kaklat .

upprepa textur

  • GL_MIRRORED_REPEAT : Om heltalets del av texturkoordinaten är jämn, ignoreras den. I motsats till, om heltalets del av texturkoordinaten är udda, är texturkoordinaten inställd på 1 - frac (s) . frakt (er) är bråkdelen av texturkoordinaten. Det gör att strukturen speglas varannan gång.

spegel konsistens

  • GL_MIRROR_CLAMP_TO_EDGE får textkoordinaten att upprepas som för GL_MIRRORED_REPEAT för en reptition av strukturen, vid vilken punkt koordinaten ska klämmas fast som i GL_CLAMP_TO_EDGE .

Observera att standardvärdet för GL_TEXTURE_WRAP_S , GL_TEXTURE_WRAP_T och GL_TEXTURE_WRAP_R är GL_REPEAT .


Applicera strukturer

Det sista att göra är att binda strukturen innan dragningen:

glBindTexture(GL_TEXTURE_2D, texture);

Textur och Framebuffer

Du kan fästa en bild i en struktur till en bildbuffer, så att du kan återge direkt till den strukturen.

glGenFramebuffers (1, &framebuffer);
glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER,
                       GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE_2D,
                       texture,
                       0);

Obs! Du kan inte läsa och skriva från samma struktur i samma renderingsuppgift, eftersom det kallar odefinierat beteende. Men du kan använda: glTextureBarrier() mellan återgivna samtal för detta.

Läs textdata

Du kan läsa texturdata med funktionen glGetTexImage :

char *outBuffer = malloc(buf_size);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

glGetTexImage(GL_TEXTURE_2D,
              0,
              GL_RGBA,
              GL_UNSIGNED_BYTE,
              outBuffer);

Obs! Texturtyp och format är bara till exempel och kan vara olika.

Använda PBO: er

Om du binda en buffert till GL_PIXEL_UNPACK_BUFFERdata parametern i glTexImage2D är en förskjutning i denna buffert.

Detta betyder att glTexImage2D inte behöver vänta på att all data kopieras ur programminnet innan den kan återgå, vilket reducerar omkostnaderna i huvudtråden.

glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width*height*3, NULL, GL_STREAM_DRAW);
void* mappedBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

//write data into the mapped buffer, possibly in another thread.
int width, height;
unsigned char* image = SOIL_load_image("image.png", &width, &height, 0, SOIL_LOAD_RGB);
memcpy(mappedBuffer, image, width*height*3);
SOIL_free_image(image);

// after reading is complete back on the main thread
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

Men där PBO: er verkligen lyser är när du behöver läsa resultatet av en render tillbaka till applikationsminnet. För att läsa pixeldata till en buffert binder den till GL_PIXEL_PACK_BUFFER då kommer glGetTexImage för glGetTexImage att vara en förskjutning i den bufferten:

glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, buf_size, NULL, GL_STREAM_COPY);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

glGetTexImage(GL_TEXTURE_2D,
              0,
              GL_RGBA,
              GL_UNSIGNED_BYTE,
              null);
//ensure we don't try and read data before the transfer is complete
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

// then regularly check for completion
GLint result;
glGetSynciv(sync, GL_SYNC_STATUS, sizeof(result), NULL, &result);
if(result == GL_SIGNALED){
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
    void* mappedBuffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);

    //now mapped buffer contains the pixel data

    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

}

Använda strukturer i GLSL-skuggare

Korsskärmarna accepterar endast texturkoordinaterna som ett toppskyddsattribut och vidarebefordrar koordinaterna till fragmentskäraren. Som standard garanterar det också att fragmentet får den korrekt interpolerade koordinaten baserat på dess position i en triangel:

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoordIn;

out vec2 texCoordOut;

void main()
{
    gl_Position = vec4(position, 1.0f);
    texCoordOut = texCoordIn;
}

Fragmentet shader accepterar sedan texCoord utgångsvariabeln som en inmatningsvariabel. Du kan sedan lägga till en textur i fragmentet genom att förklara en uniform sampler2D . Att prova ett fragment av texturen använder vi en inbyggd funktion texture som har två parametrar. Den första är den textur vi vill ta prov från och den andra är koordinaten för denna textur:

in vec2 texCoordOut;

out vec4 color;

uniform sampler2D image;

void main()
{
    color = texture(image, texCoordOut);
}

Observera att image inte är den direkta textur-ID här. Det är id för texturenheten som kommer att samplas. I sin tur är strukturer inte bundna till program direkt; de är bundna till texturenheter. Detta uppnås genom att först göra texturenheten aktiv med glActiveTexture , och sedan ringa glBindTexture kommer att påverka denna speciella texturenhet. Eftersom standardkonstruktionsenheten är texturenhet 0 , kan program som använder en struktur dock göras enklare att undvika detta samtal.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow