OpenGL ES 学习教程(4):给立方体贴墙纸
发表于2017-11-22
上一篇制作了一个彩色的旋转的 Cube ,不是很好看,所以想换一个颜色,加入想去实现上图中的效果,那就要把图片贴到人物模型上,这个做设计的就可以搞定 。接下来就用上篇做好的 Cube,给立方体贴上一张墙纸。
首先来了解下 纹理坐标 和 顶点坐标
学术上,把一张图片贴到一个平面上,叫做纹理映射。
怎么映射呢?
看上图中,左边是顶点坐标(-1,1) 右边是纹理坐标 (0,1)
我们只要把纹理坐标的 (0,1) 对应到 顶点的 (-1,1) 就好了。
Tips:纹理坐标又称为 UV 坐标。
好,我搞来一张图片,把这个图片贴到 Cube上。
1、先来添加 Cube 对应 的 UV坐标。
glm::vec3 pos[] = { //Front glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(-1.0f, 1.0f, 1.0f), //back glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, -1.0f), glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, -1.0f), glm::vec3(-1.0f, 1.0f, -1.0f), //left glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(-1.0f, -1.0f, -1.0f), glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(-1.0f, 1.0f, -1.0f), //right glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(1.0f, -1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, -1.0f), //up glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, -1.0f), glm::vec3(-1.0f, 1.0f, 1.0f), glm::vec3(1.0f, 1.0f, -1.0f), glm::vec3(-1.0f, 1.0f, -1.0f), //down glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, -1.0f, 1.0f), glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(-1.0f, -1.0f, 1.0f), glm::vec3(1.0f, -1.0f, -1.0f), glm::vec3(-1.0f, -1.0f, -1.0f), }; glm::vec2 uv[] = { //front glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1), //back glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1), //left glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1), //right glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1), //top glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1), //down glm::vec2(0, 0), glm::vec2(1, 0), glm::vec2(1, 1), glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(0, 1) };
我写了一个 Texture2D 类,来读取图片数据。
void Texture2D::LoadTexture(const char* filename) { m_imageFilePath = std::string(filename); //1、获取图片格式; FREE_IMAGE_FORMAT imageformat = FreeImage_GetFileType(filename, 0); //2、根据获取到的格式来加载图片; FIBITMAP *bitmap = FreeImage_Load(imageformat, filename, 0); //3、转化为rag 24色; bitmap = FreeImage_ConvertTo32Bits(bitmap); //4、获取数据指针; BYTE *pixels = (BYTE*)FreeImage_GetBits(bitmap); //5、使用; int width = FreeImage_GetWidth(bitmap); int height = FreeImage_GetHeight(bitmap); //6、交换数据,获得正确的颜色 交换1和3 RGB 原来存储的是 BGR?; for (int i = 0; i < width * height * 4; i += 4) { BYTE r = pixels[i]; pixels[i] = pixels[i + 2]; pixels[i + 2] = r; } //1、产生一个纹理ID; glGenTextures(1, &m_textureId); //2、关联绑定这个纹理ID; glBindTexture(GL_TEXTURE_2D, m_textureId); //3、指定放大,缩小滤波方式,线性滤波,即放大缩小的插值方式; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //将图片rgb数据上传到OpenGL,在这一步才把数据从内存Copy到显存; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); //释放内存; FreeImage_Unload(bitmap); }
virtual bool Initialize() { const char* vertexShader= { "precision lowp float;" "uniform mat4 m_mvp;" "attribute vec3 m_position;" "attribute vec4 m_color;" "attribute vec2 m_uv;" "varying vec4 m_outColor;" "varying vec2 m_outUV;" "void main()" "{" " vec4 pos=vec4(m_position,1);" " gl_Position=m_mvp*pos;" " m_outColor=m_color;" " m_outUV=m_uv;" "}" }; const char* fragmentShader = { "precision lowp float;" "uniform sampler2D m_texture;" "varying vec4 m_outColor;" "varying vec2 m_outUV;" "void main()" "{" " gl_FragColor=m_outColor*texture2D(m_texture,m_outUV);" "}" }; bool ret = createProgram(vertexShader, fragmentShader); if (ret) { m_position = glGetAttribLocation(m_programId, "m_position"); m_color = glGetAttribLocation(m_programId, "m_color"); m_mvp = glGetUniformLocation(m_programId, "m_mvp"); m_uv = glGetAttribLocation(m_programId, "m_uv"); m_texture = glGetUniformLocation(m_programId, "m_texture"); } return ret; }
大概就是这样,然后如果要实现透明效果,不要忘记开启 Blend 。
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
示例工程下载:http://pan.baidu.com/s/1gdsIcpH