7-纹理坐标包装

目录

概述

纹理包装模式用于指定纹理坐标超出[0.0, 1.1]范围时所发生的行为,用glTexParameter[i|f] [v]设置,这些模式可以为s、t、r坐标单独设置。GL_TEXTURE_WRAP_S和GL_TEXTURE_WRAP_T和GL_TEXTURE_WRAP_R分别定义s和t和r坐标超出[0.0, 1.0]范围时发生的行为。

包装模式选择:

纹理包装模式 描述
GL_REPEAT 重复纹理
GL_CLAMP_TO_EDGE 限定读取纹理的边缘
GL_MIRRORED_REPEAT 重复纹理和镜像

正常纹理坐标是[0, 1]之间,而右边的纹理坐标为[-1, 2],比正常的大了3倍,所以,一行的小方块数目为12个。

左边为正常纹理,右边为纹理坐标包装

纹理坐标包装的坐标设置:
    GLfloat vVertices[] = {
            -0.3f,  0.3f, 0.0f, 1.0f,  // Position 0
            -1.0f,  -1.0f,              // TexCoord 0
            -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
            -1.0f,  2.0f,              // TexCoord 1
            0.3f, -0.3f, 0.0f, 1.0f, // Position 2
            2.0f,  2.0f,              // TexCoord 2
            0.3f,  0.3f, 0.0f, 1.0f,  // Position 3
            2.0f,  -1.0f               // TexCoord 3
    };

正常纹理坐标:
    GLfloat vVertices[] = {
            -0.3f,  0.3f, 0.0f, 1.0f,  // Position 0
            0.0f,  0.0f,              // TexCoord 0
            -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
            0.0f,  1.0f,              // TexCoord 1
            0.3f, -0.3f, 0.0f, 1.0f, // Position 2
            1.0f,  1.0f,              // TexCoord 2
            0.3f,  0.3f, 0.0f, 1.0f,  // Position 3
            1.0f,  0.0f               // TexCoord 3
    };

7-纹理坐标包装

源码解析

#include <stdlib.h>
#include "esUtil.h"

typedef struct
{
    GLuint programObject;
    GLint samplerLoc;
    GLint offsetLoc;
    GLuint textureId;
} myUserData;

GLubyte *GenCheckImage(int width, int height, int checkSize)
{
    int x, y;
    GLubyte *pixels = (GLubyte *)malloc(width * height * 3);
    if (pixels == NULL) {
        return NULL;
    }
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            GLubyte rColor = 0;
            GLubyte bColor = 0;
            if ((x/checkSize)%2 == 0) {
                rColor = 255 * ((y/checkSize) % 2);
                bColor = 255 * (1 - ((y/checkSize) % 2));
            } else {
                bColor = 255 * ((y/checkSize) % 2);
                rColor = 255 * (1 - ((y/checkSize) % 2));
            }

            pixels[(y*width + x)*3] = rColor;
            pixels[(y*width + x)*3 + 1] = 0;
            pixels[(y*width + x)*3 + 2] = bColor;
        }
    }
    return pixels;
}

GLuint CreateTexture2D()
{
    GLuint textureId;
    int width = 256, height = 256;
    GLubyte *pixels;
    pixels = GenCheckImage(width, height, 64);
    if (pixels == NULL) {
        return 0;
    }
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
            0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return textureId;
}

int Init(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    char vShaderStr[] =
            "#version 300 es \n"
            "uniform float u_offset; \n"
            "layout(location = 0) in vec4 a_position; \n"
            "layout(location = 1) in vec2 a_texCoord; \n"
            "out vec2 v_texCoord; \n"
            "void main() \n"
            "{ \n"
            "   gl_Position = a_position; \n"
            "   gl_Position.x += u_offset; \n"
            "   v_texCoord = a_texCoord; \n"
            "} \n";

    char fShaderStr[] =
            "#version 300 es \n"
            "precision mediump float; \n"
            "in vec2 v_texCoord; \n"
            "layout(location = 0) out vec4 outColor; \n"
            "uniform sampler2D s_texture; \n"
            "void main() \n"
            "{ \n"
            "   outColor = texture(s_texture, v_texCoord); \n"
            "} \n";
    userData->programObject = myesLoadProgram(vShaderStr, fShaderStr);
    userData->samplerLoc = glGetUniformLocation(userData->programObject, "s_texture");
    userData->offsetLoc = glGetUniformLocation(userData->programObject, "u_offset");
    userData->textureId = CreateTexture2D();
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
    return GL_TRUE;
}

void Draw(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    GLfloat vVertices[] = {
            -0.3f,  0.3f, 0.0f, 1.0f,  // Position 0
            -1.0f,  -1.0f,              // TexCoord 0
            -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
            -1.0f,  2.0f,              // TexCoord 1
            0.3f, -0.3f, 0.0f, 1.0f, // Position 2
            2.0f,  2.0f,              // TexCoord 2
            0.3f,  0.3f, 0.0f, 1.0f,  // Position 3
            2.0f,  -1.0f               // TexCoord 3
    };
    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
    glViewport(0, 0, myesContext->width, myesContext->height);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(userData->programObject);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), vVertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), &vVertices[4]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, userData->textureId);
    glUniform1i(userData->samplerLoc, 0);
    // 这里是设置重复纹理
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glUniform1f(userData->offsetLoc, -0.7f);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

    // 这里是设置限定读取纹理的边缘
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glUniform1f(userData->offsetLoc, 0.0f);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

    // 这里是设置重复纹理和镜像
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    glUniform1f(userData->offsetLoc, 0.7f);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

void ShutDown(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    glDeleteTextures(1, &userData->textureId);
    glDeleteProgram(userData->programObject);
}

int myesMain(MYESContext *myesContext)
{
    myesContext->userData = malloc(sizeof(myUserData));
    myesCreateWindow(myesContext, "9_3_texturewrap", 320, 240, MY_ES_WINDOW_RGB);

    if (!Init(myesContext))
    {
        return GL_FALSE;
    }

    esRegisterDrawFunc(myesContext, Draw);
    esRegisterShutdownFunc(myesContext, ShutDown);

    return GL_TRUE;
}

参考

1. 纹理
https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/06%20Textures/
上一篇:4. 顶点着色器-mvp转换


下一篇:JavaWeb课设(高校人事管理入门级)