ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

9-多重纹理

2021-05-15 18:04:44  阅读:157  来源: 互联网

标签:多重 userData 0.0 myesContext 纹理 char Header GL


目录

概述

1. 多重纹理

多重纹理用来组合多个纹理贴图。

void Draw(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    // 两个纹理共用同一组纹理坐标和顶点坐标了
    GLfloat vVertices[] = {
            -0.5f,  0.5f, 0.0f,  // Position 0
            0.0f,  0.0f,        // TexCoord 0
            -0.5f, -0.5f, 0.0f,  // Position 1
            0.0f,  1.0f,        // TexCoord 1
            0.5f, -0.5f, 0.0f,  // Position 2
            1.0f,  1.0f,        // TexCoord 2
            0.5f,  0.5f, 0.0f,  // Position 3
            1.0f,  0.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, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    // 激活纹理0:GL_TEXTURE0
    glActiveTexture(GL_TEXTURE0);
    // 绑定第一个纹理
    glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId);
    // 将0传给片段着色器,说明是GL_TEXTURE0
    glUniform1i(userData->baseMapLoc, 0);
    // 激活纹理1:GL_TEXTURE1
    glActiveTexture(GL_TEXTURE1);
    // 绑定第二个纹理
    glBindTexture(GL_TEXTURE_2D, userData->lightMapTexId);
    // 将1传给片段着色器,说明是GL_TEXTURE1
    glUniform1i(userData->lightMapLoc, 1);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

    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_baseMap;   \n"		// 纹理0
            "uniform sampler2D s_lightMap;  \n"		// 纹理1
            "void main()    \n"
            "{  \n"
            "   vec4 baseColor;     \n"
            "   vec4 lightColor;    \n"
            "   baseColor = texture(s_baseMap, v_texCoord); \n"		// 用同一组纹理坐标
            "   lightColor = texture(s_lightMap, v_texCoord);   \n"		// 用同一组纹理坐标
            "   outColor = baseColor * (lightColor + 0.25); \n"		// 两个纹理进行组合操作
            "}  \n";

2. assets文件的使用

2.1 新建assets文件夹

在app/src/main目录下新建assets文件夹,然后把文件放在这个文件夹中;

可以用7zip解压apk文件,看里面是否有assets文件夹,以及你放进去的文件。

也可以看app/app.iml文件,看assets文件夹是否在文件中有include进去。

2.2 assets文件打开以及使用

char* esLoadTGA(void *ioContext, const char *fileName, int *width, int *height)
{
    char *buffer;
    TGA_HEADER Header;
    int bytesRead;

    if (ioContext != NULL) {
        // 这个assetManager的值是在android_main函数传入进来的
        // myesContext.platformData =  (void *)pApp->activity->assetManager;
        AAssetManager *assetManager = (AAssetManager *)ioContext;
        if (assetManager != nullptr) {
            // 1. 打开文件夹;我这里如果只是单纯的打开文件,它会返回null的,不知道是什么原因;所以这里先打开文件夹
            AAssetDir *assetDir = AAssetManager_openDir(assetManager, "");
            if (assetDir != nullptr) {
                const char *filename = (const char *)NULL;
                // 2. 获取文件夹里面的文件的文件名
                while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
                    // 3. 然后打开文件
                    AAsset *asset =
                            AAssetManager_open(assetManager, filename, AASSET_MODE_BUFFER);
                    if (asset != nullptr) {
                        // 4. 如果是你想要打开的文件
                        if (strcmp(filename, fileName) == 0) {
							// 5. 读取tga文件的头
                            AAsset_read(asset, &Header, sizeof(TGA_HEADER));
                            *width = Header.Width;
                            *height = Header.Height;
                            esLogMessage("size of Header = %d", sizeof(TGA_HEADER));
                            esLogMessage("idsize = %d,MapType = %d,ImageType = %d,PaletteStart=%d,PaletteSize=%d,x = %d,y = %d,width = %d,height = %d",
                                    Header.IdSize,Header.MapType,Header.ImageType,Header.PaletteStart,Header.PaletteSize, Header.X, Header.Y, *width, Header.Height);
                            if (Header.ColorDepth == 8 ||
                                Header.ColorDepth == 24 || Header.ColorDepth == 32) {
                                esLogMessage("Header color depth");
                                // 根据图片的长和宽,以及位深,来分配buffer的大小
                                int bytesToRead = sizeof(char) * (*width)*(*height)*Header.ColorDepth / 8;
                                buffer = (char *)malloc(bytesToRead);
                                if (buffer) {
                                    esLogMessage("buffer not null");
                                    // 6. 读取tga文件的数据
                                    bytesRead = AAsset_read(asset, buffer, bytesToRead);
                                    // 最后关闭文件和文件夹
                                    AAsset_close(asset);
                                    AAssetDir_close(assetDir);
                                    // 返回文件数据
                                    return (buffer);
                                }
                            }
                        } else {
                            esLogMessage("not the file %s", filename);
                        }
                        AAsset_close(asset);
                    } else {
                        esLogMessage("Failed to open test file");
                    }
                }
                AAssetDir_close(assetDir);
            } else {
                esLogMessage("Failed to open root directory");
            }
        } else {
            esLogMessage("Asset Manager was invalid");
        }
    }

    return (NULL);
}

3. tga文件头格式

typedef struct
{
    byte  identsize;          // size of ID field that follows 18 byte header (0 usually)
    byte  colourmaptype;      // type of colour map 0=none, 1=has palette
    byte  imagetype;          // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed

    short colourmapstart;     // first colour map entry in palette
    short colourmaplength;    // number of colours in palette
    byte  colourmapbits;      // number of bits per palette entry 15,16,24,32

    short xstart;             // image x origin
    short ystart;             // image y origin
    short width;              // image width in pixels	图片宽度
    short height;             // image height in pixels	图片高度
    byte  bits;               // image bits per pixel 8,16,24,32	图片的位深
    byte  descriptor;         // image descriptor bits (vh flip bits)

    // pixel data follows header

} TGA_HEADER

源码解析

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

typedef struct
{
    GLuint programObject;
    GLuint baseMapLoc;
    GLuint lightMapLoc;
    GLuint baseMapTexId;
    GLuint lightMapTexId;
} myUserData;


GLuint LoadTexture(void *ioContext, char * fileName)
{
    int width, height;

    char *buffer = esLoadTGA(ioContext, fileName, &width, &height);
    GLuint texId;

    if (buffer == NULL) {
        esLogMessage("Error loading (%s) image.\n", fileName);
    }
    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    free(buffer);
    return texId;
}

int Init(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    char vShaderStr[] =
            "#version 300 es \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"
            "   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_baseMap;   \n"
            "uniform sampler2D s_lightMap;  \n"
            "void main()    \n"
            "{  \n"
            "   vec4 baseColor;     \n"
            "   vec4 lightColor;    \n"
            "   baseColor = texture(s_baseMap, v_texCoord); \n"
            "   lightColor = texture(s_lightMap, v_texCoord);   \n"
            "   outColor = baseColor * (lightColor + 0.25); \n"
            "}  \n";

    userData->programObject = myesLoadProgram(vShaderStr, fShaderStr);
    userData->baseMapLoc = glGetUniformLocation(userData->programObject, "s_baseMap");
    userData->lightMapLoc = glGetUniformLocation(userData->programObject, "s_lightMap");
    userData->baseMapTexId = LoadTexture(myesContext->platformData, "basemap.tga");
    userData->lightMapTexId = LoadTexture(myesContext->platformData, "lightmap.tga");
    if (userData->baseMapTexId == 0 || userData->lightMapTexId == 0) {
        return GL_FALSE;
    }
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
    return GL_TRUE;
}

void Draw(MYESContext *myesContext)
{
    myUserData *userData = (myUserData *)myesContext->userData;
    GLfloat vVertices[] = {
            -0.5f,  0.5f, 0.0f,  // Position 0
            0.0f,  0.0f,        // TexCoord 0
            -0.5f, -0.5f, 0.0f,  // Position 1
            0.0f,  1.0f,        // TexCoord 1
            0.5f, -0.5f, 0.0f,  // Position 2
            1.0f,  1.0f,        // TexCoord 2
            0.5f,  0.5f, 0.0f,  // Position 3
            1.0f,  0.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, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId);
    glUniform1i(userData->baseMapLoc, 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, userData->lightMapTexId);
    glUniform1i(userData->lightMapLoc, 1);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}


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

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

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

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

    return GL_TRUE;
}

问题

1. struct对齐问题

如果是按照下面这样定义的话,得到的sizeof(TGA_HEADER)是20个字节,比定义多了2个字节;得到的位深是错的,所以没有读取到图片的数据,所以得到的结果是一张黑黑的图片

typedef struct
{
    unsigned char IdSize, MapType, ImageType;
    unsigned short PaletteStart, PaletteSize;
    unsigned char PaletteEntryDepth;
    unsigned short X, Y, Width, Height;
    unsigned char ColorDepth, Descriptor;
} TGA_HEADER;

I/esUtil: size of Header = 20
    // width和height都是错的
    idsize = 0,MapType = 0,ImageType = 2,PaletteStart=0,PaletteSize=0,x = 0,y = 512,width = 512,height = 24
    not the file lightmap.tga
    Error loading (basemap.tga) image.
I/esUtil: not the file basemap.tga
I/esUtil: size of Header = 20
    idsize = 0,MapType = 0,ImageType = 2,PaletteStart=0,PaletteSize=0,x = 0,y = 256,width = 256,height = 24
    Error loading (lightmap.tga) image.

但是如果把PaletteEntryDepth去掉的话,得到的sizeof(TGA_HEADER)是18个字节,就正常了;就不知道是什么原因导致的

typedef struct
{
    unsigned char IdSize, MapType, ImageType;
    unsigned short PaletteStart, PaletteSize;
    //unsigned char PaletteEntryDepth;
    unsigned short X, Y, Width, Height;
    unsigned char ColorDepth, Descriptor;
} TGA_HEADER;
05-15 09:25:54.184  5805  5842 I esUtil  : Error loading (lightmap.tga) image.
05-15 09:28:21.042  6360  6416 I esUtil  : size of Header = 18
05-15 09:28:21.042  6360  6416 I esUtil  : idsize = 0,MapType = 0,ImageType = 2,PaletteStart=0,PaletteSize=0,x = 0,y = 0,width = 512,height = 512
05-15 09:28:21.042  6360  6416 I esUtil  : Header color depth
05-15 09:28:21.042  6360  6416 I esUtil  : buffer not null
05-15 09:28:21.050  6360  6416 I esUtil  : not the file basemap.tga
05-15 09:28:21.050  6360  6416 I esUtil  : size of Header = 18
05-15 09:28:21.050  6360  6416 I esUtil  : idsize = 0,MapType = 0,ImageType = 2,PaletteStart=0,PaletteSize=0,x = 0,y = 0,width = 256,height = 256
05-15 09:28:21.050  6360  6416 I esUtil  : Header color depth
05-15 09:28:21.050  6360  6416 I esUtil  : buffer not null

2. assets单独打开文件,会返回null

static esFile *esFileOpen ( void *ioContext, const char *fileName )
{
   esFile *pFile = NULL;

   if ( ioContext != NULL )
   {
      AAssetManager *assetManager = ( AAssetManager * ) ioContext;
       // 如果不先打开文件夹,就根据文件名打开文件的话,是会返回null的,不知道是什么原因
       // pFile = null,最后得到的也是一张黑图
      pFile = AAssetManager_open ( assetManager, fileName, AASSET_MODE_BUFFER );
   }

   return pFile;
}

效果图

basemap.tga图片

image

lightmap.tga图片

image

合并之后的效果图:

image

参考

1. Why does AAssetDir_getNextFileName always return null?
https://stackoverflow.com/questions/55911059/why-does-aassetdir-getnextfilename-always-return-null
2. TGA File Format
https://gshaw.ca/closecombat/formats/tga.html

标签:多重,userData,0.0,myesContext,纹理,char,Header,GL
来源: https://www.cnblogs.com/pyjetson/p/14772099.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有