OpenGl ES---纹理

什么是纹理?
纹理:最通常就是装饰3D物体,像贴纸一样贴在物体表面,在OpenGl ES中除了装饰物体表面,还用来
作为数据的容器。
在OpenGL中,纹理实际上是一个可以被采样的复杂数据集合,是GPU使用的图像数据结构,分为:2D纹理,立方体纹理和3D纹理。
2D 纹理是 OpenGLES 中最常用和最常见的纹理形式,是一个图像数据的二维数组。纹理中的一个单独数据元素称为纹素或纹理像素。

纹理映射?
通过图元的顶点坐标指定恰当的纹理坐标,通过纹理坐标在纹理图中选定特定的纹理区域, 最后通过纹理坐标与顶点的映射关系,将特定的纹理区域映射到指定图元上。

纹理映射也称为纹理贴图,简单说:将纹理坐标所指定的纹理区域,映射到顶点坐标对应的区域。

纹理坐标系:
在这里插入图片描述
渲染坐标系或opengl ES坐标系:
在这里插入图片描述
4个纹理坐标分别为:
T0(0,0),T1(0,1),T2(1,1),T3(1,0);
4个纹理坐标对应的顶点坐标:
V0(-1,0.5),V1(-1,-0.5),V2(1,-0.5),V3(1,0.5)

由于OpenGLES绘制是以三角形为单位,设置绘制的2个三角形为V0V1V2和V0V2V3.
当我们调整纹理坐标的顺序,顶点坐标顺序不变,如T0T1T2T3–>T1T2T3T0,绘制后将得到一个顺时针
旋转90度的纹理贴图。因此可以通过纹理坐标和顶点坐标的对应关系实现纹理简单旋转。

纹理映射的简单实现
步骤:
1,生成纹理,编译链接着色器程序
2,确定纹理坐标及对应的顶点坐标
3,加载图像数据到纹理,加载纹理坐标和顶点坐标到着色器程序
4.绘制

生成纹理并加载图像数据到纹理

//生成一个纹理,将纹理 id 赋值给 m_TextureId
glGenTextures(1, &m_TextureId); 

//将纹理 m_TextureId 绑定到类型 GL_TEXTURE_2D 纹理
glBindTexture(GL_TEXTURE_2D, m_TextureId);

//设置纹理 S 轴(横轴)的拉伸方式为截取
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
//设置纹理 T 轴(纵轴)的拉伸方式为截取
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

//设置纹理采样方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//加载 RGBA 格式的图像数据
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);

对纹理采样的片元着色器脚本

#version 300 es                                     
precision mediump float;                            
in vec2 v_texCoord;                                 
layout(location = 0) out vec4 outColor;             
uniform sampler2D s_TextureMap; //声明采用器                     
void main()                                         
{
  // texture() 为内置的采样函数,v_texCoord 为顶点着色器传进来的纹理坐标
  // 根据纹理坐标对纹理进行采样,输出采样的 rgba 值(4维向量)                                                  
  outColor = texture(s_TextureMap, v_texCoord);      
}                                                   

实例1:

// 生成纹理,编译链接着色器程序
void TextureMapSample::Init()
{
	//create RGBA texture
	glGenTextures(1, &m_TextureId);
	glBindTexture(GL_TEXTURE_2D, m_TextureId);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glBindTexture(GL_TEXTURE_2D, GL_NONE);

	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_TextureMap;                     \n"
			"void main()                                         \n"
			"{                                                   \n"
			"  outColor = texture(s_TextureMap, v_texCoord);     \n"
			"}                                                   \n";

	m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);
	if (m_ProgramObj)
	{
		m_SamplerLoc = glGetUniformLocation(m_ProgramObj, "s_TextureMap");
	}
	else
	{
		LOGCATE("TextureMapSample::Init create program fail");
	}

}

// 加载图像数据、纹理坐标和顶点坐标数据,绘制实现纹理映射
void TextureMapSample::Draw(int screenW, int screenH)
{
	LOGCATE("TextureMapSample::Draw()");

	if(m_ProgramObj == GL_NONE || m_TextureId == GL_NONE) return;
	GLfloat verticesCoords[] = {
			-1.0f,  0.5f, 0.0f,  // Position 0
			-1.0f, -0.5f, 0.0f,  // Position 1
			1.0f, -0.5f, 0.0f,  // Position 2
			1.0f,  0.5f, 0.0f,  // Position 3
	};

	GLfloat textureCoords[] = {
			0.0f,  0.0f,        // TexCoord 0
			0.0f,  1.0f,        // TexCoord 1
			1.0f,  1.0f,        // TexCoord 2
			1.0f,  0.0f         // TexCoord 3
	};

	GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

	//upload RGBA image data
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, m_TextureId);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);
	glBindTexture(GL_TEXTURE_2D, GL_NONE);

	// Use the program object
	glUseProgram (m_ProgramObj);

	// Load the vertex position
	glVertexAttribPointer (0, 3, GL_FLOAT,
							GL_FALSE, 3 * sizeof (GLfloat), verticesCoords);
	// Load the texture coordinate
	glVertexAttribPointer (1, 2, GL_FLOAT,
							GL_FALSE, 2 * sizeof (GLfloat), textureCoords);

	glEnableVertexAttribArray (0);
	glEnableVertexAttribArray (1);

	// Bind the RGBA map
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, m_TextureId);

	// Set the RGBA map sampler to texture unit to 0
	glUniform1i(m_SamplerLoc, 0);

	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
}

结果:
在这里插入图片描述
实例2:
CoordSystemSample.h代码:


/**
 *
 * Created by 公众号:字节流动 on 2020/4/18.
 * https://github.com/githubhaohao/NDK_OpenGLES_3_0
 * 最新文章首发于公众号:字节流动,有疑问或者技术交流可以添加微信 Byte-Flow ,领取视频教程, 拉你进技术交流群
 *
 * */

#ifndef NDK_OPENGLES_3_0_COORDSYSTEMSAMPLE_H
#define NDK_OPENGLES_3_0_COORDSYSTEMSAMPLE_H


#include "detail/type_mat.hpp"
#include "detail/type_mat4x4.hpp"
#include "GLSampleBase.h"
#include <vector>
#include <map>

#define RENDER_IMG_NUM 3

class CoordSystemSample : public GLSampleBase
{
public:
    CoordSystemSample();

    virtual ~CoordSystemSample();

    virtual void LoadImage(NativeImage *pImage);
    virtual void LoadMultiImageWithIndex(int index, NativeImage *pImage);

    virtual void Init();
    virtual void Draw(int screenW, int screenH);
    //virtual void delay(int seconds);

    virtual void Destroy();

    virtual void UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY);

    void UpdateMVPMatrix(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio);
    void UpdateMVPMatrix1(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio);
    void UpdateMatrix(glm::mat4 &mvpMatrix, int angleXRotate, int angleYRotate, float scale, glm::vec3 transVec3, float ratio);
    void DrawArray();
    glm::mat4 transform(float height, float dip,float fov_x,float fov_y);
    glm::mat4 buildRotateX(float rad);
    glm::mat4 buildRotateY(float rad);
    glm::mat4 buildRotateZ(float rad);

private:
    GLuint m_TextureId;
    GLint m_SamplerLoc;
    GLint m_SamplerLoc1;
    GLint m_MVPMatLoc;
    GLint m_MVPMatLoc1;
    GLint m_Offset;
    GLint m_MVPMatLoc2;
    GLuint m_VaoId;
    GLuint m_VboIds[3];
    GLuint m_TextureIds[RENDER_IMG_NUM];
    NativeImage m_RenderImages[RENDER_IMG_NUM];
    glm::mat4 m_ModelMatrix;
    std::vector<glm::vec3> windowsTrans;
    std::map<GLfloat, glm::vec3> sorted;

    NativeImage m_RenderImage;
    glm::mat4 m_MVPMatrix;

    int m_AngleX;
    int m_AngleY;
    float m_ScaleX;
    float m_ScaleY;
    float m_FrameIndex;
    float m_Color;
    float m_offset;
    float m_time;
    int m_i;
    CoordSystemSample* m_pCoordSystemSample;

};
#endif //NDK_OPENGLES_3_0_COORDSYSTEMSAMPLE_H
    

CoordSystemSample.cpp代码:

/**
 *
 * Created by 公众号:字节流动 on 2020/4/18.
 * https://github.com/githubhaohao/NDK_OpenGLES_3_0
 * 最新文章首发于公众号:字节流动,有疑问或者技术交流可以添加微信 Byte-Flow ,领取视频教程, 拉你进技术交流群
 *
 * */

#include "gtc/matrix_transform.hpp"
#include "CoordSystemSample.h"
#include "../util/GLUtils.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <math.h>
#include "../glm/mat4x4.hpp"

#define DRAW_POINTS
#define POINTS_NUM           512
#define POINTS_PRE_TRIANGLES 3
#define TRIANGLES_PER_POINT  3

CoordSystemSample::CoordSystemSample()
{

    m_SamplerLoc = GL_NONE;
    m_MVPMatLoc = GL_NONE;

    m_TextureId = GL_NONE;
    m_VaoId = GL_NONE;

    m_AngleX = 0;
    m_AngleY = 0;

    m_ScaleX = 1.0f;
    m_ScaleY = 1.0f;
    m_offset =0.0f;
    m_time=0.0f;

    //m_pCoordSystemSample = new CoordSystemSample();
}

CoordSystemSample::~CoordSystemSample()
{
    NativeImageUtil::FreeNativeImage(&m_RenderImage);

}

void CoordSystemSample::Init()
{
    //create RGBA texture
    glGenTextures(1, &m_TextureId);
    glBindTexture(GL_TEXTURE_2D, m_TextureId);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, GL_NONE);

    char vShaderStr[] =
            "#version 300 es                            \n"
            "layout(location = 0) in vec4 a_position;   \n"
            "layout(location = 1) in vec2 a_texCoord;   \n"
            "uniform float u_Offset;\n"
            "uniform float t;\n"
            "out vec2 v_texCoord;                       \n"
            "void main()                                \n"
            "{                                          \n"
            "   gl_Position = a_position;               \n"
            "   gl_Position.y = gl_Position.y+u_Offset+t;               \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_TextureMap;                     \n"
            "void main()                                         \n"
            "{                                                   \n"
            "  outColor = texture(s_TextureMap, v_texCoord);     \n"
            "  //outColor = texelFetch(s_TextureMap,ivec2(int(v_texCoord.x * 404.0), int(v_texCoord.y * 336.0)), 0);\n"
            "}                                                   \n";

    m_ProgramObj = GLUtils::CreateProgram(vShaderStr, fShaderStr, m_VertexShader, m_FragmentShader);
    if (m_ProgramObj)
    {
        m_SamplerLoc = glGetUniformLocation(m_ProgramObj, "s_TextureMap");
    }
    else
    {
        LOGCATE("TextureMapSample::Init create program fail");
    }
};

void CoordSystemSample::LoadImage(NativeImage *pImage)
{
#if 0
    LOGCATE("CoordSystemSample::LoadImage pImage = %p", pImage->ppPlane[0]);
	if (pImage)
	{
		m_RenderImage.width = pImage->width;
		m_RenderImage.height = pImage->height;
		m_RenderImage.format = pImage->format;
		NativeImageUtil::CopyNativeImage(pImage, &m_RenderImage);
	}
#endif
}
void CoordSystemSample::LoadMultiImageWithIndex(int index, NativeImage *pImage)
{
    LOGCATE("TimeTunnelSample::LoadImage pImage = %p", pImage->ppPlane[0]);
    if (pImage)
    {
        m_RenderImage.width = pImage->width;
        m_RenderImage.height = pImage->height;
        m_RenderImage.format = pImage->format;
        NativeImageUtil::CopyNativeImage(pImage, &m_RenderImage);
    }
}

glm::mat4 CoordSystemSample::transform(float height, float dip,float fov_x,float fov_y)
{
    float distance= height/(tan(glm::radians(dip)));
    float radiansY=0.0;
    float radiansZ=0.0;
    LOGCATD("distance = %f",distance);
    //glm::mat4 Projection = glm::frustum(-0.699f, 0.699f, -0.3934f, 0.3934f, imagez, 100.0f);
    // glm::mat4 Projection = glm::perspective(glm::radians(fov_y), fov_x/fov_y,2.0f,200.0f); //描绘的是屏幕  任务:加一个横向fov 算出来高宽比
    glm::mat4 Projection = glm::perspective(glm::radians(4.0f), fov_x/fov_y,0.1f, 200.f);
    LOGCATD("aspect = %f",fov_x/fov_y);
    //透视投影矩阵 第1个参数为视锥上下面之间的夹角 第2个参数为宽高比  第3,第4分别为近界面和远界面的深度
    //glm::mat4 Projection = glm::pers pective(10.0f,854.0f/480.0f, imagez,100.0f);

    //摄像机位置:世界空间中一个指向摄像机位置的向量(即摄像机位置)
    glm::vec3 cameraPos = glm::vec3(-0.37, height, 1.31834);
    //摄像机方向:摄像机指向哪个方向(即中心坐标)
    glm::vec3 cameraTarget = glm::vec3(-0.37f+distance*sin(glm::radians(0.0)), 0.0f, -distance*cos(glm::radians(0.0))+1.31834);
    glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
    LOGCATD("cameraDirection[0]:%f,cameraDirection[1]:%f,cameraDirection[2]:%f,",cameraDirection[0],cameraDirection[1],cameraDirection[2]);
    glm::vec3 right = glm::vec3(cos(glm::radians(0.0)), 0.0, sin(glm::radians(0.0))); //右向量 水平倾角
    //glm::vec4 right_trans=glm::vec4(1.0f, 0.0f, 0.0f,1.0);
    glm::vec3 cameraUp = glm::normalize(glm::cross(cameraDirection,right ));
    LOGCATD("cameraUp[0]:%f,cameraUp[1]:%f,cameraUp[2]:%f,",cameraUp[0],cameraUp[1],cameraUp[2]);
    //glm::vec3 cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));
    glm::mat4 View = glm::lookAt(
            //glm::vec3(-0.087f, 0.380198f, 0.311671f), // Camera is at (0,0,1), in World Space  0.35628f
            cameraPos,
            //glm::vec3(0, 0, -distance), // and looks at the origin
            cameraTarget,
            cameraUp
            //glm::vec3(-tan(glm::radians(0.0f)), 1.0f, 0)  // Head is up (set to 0,-1,0 to look upside-down)
    ); //描绘的是人眼
    //将顶点的世界空间坐标装换为观察空间坐标
    //glm::lookAt函数有三个参数,eye表示摄像机所在的位置,center表示摄像机要看向的中心点的位置,up表示摄像机的三个方位向量中的up向量
    glm::mat4 Model = glm::mat4(1.0f);
    //LOGCATD("XXCC Model = %f",Model[0][0]);
    Model = glm::scale(Model, glm::vec3(1.0, 1.0, 1.0f)); //用于对物体进行缩放

    Model = glm::translate(Model, glm::vec3(0.0f, 0.0f, 0.0f)); //用于对物体进行位移

    m_MVPMatrix = Projection * View;
    return m_MVPMatrix = Projection * View * Model;       //* buildRotateY(glm::radians(0.0)) * buildRotateZ(glm::radians(2.0));
}

void CoordSystemSample::Draw(int screenW, int screenH)
{
    LOGCATE("TextureMapSample::Draw()");
    if(m_ProgramObj == GL_NONE || m_TextureId == GL_NONE) return;

    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0, 0.0, 0.0, 1.0);
    GLfloat verticesCoords[] = {
            -0.2f,  0.0f, 0.0f,  // Position 0
            -0.2f, -0.5f, 0.0f,  // Position 1
            0.2f, -0.5f, 0.0f,   // Position 2
            0.2f,  0.0f, 0.0f,    // Position 3
    };

    GLfloat textureCoords[] = {
            0.0f,  0.0f,        // TexCoord 0
            0.0f,  1.0f,        // TexCoord 1
            1.0f,  1.0f,        // TexCoord 2
            1.0f,  0.0f
    };
    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

    //upload RGBA image data
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_TextureId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);
    glBindTexture(GL_TEXTURE_2D, GL_NONE);

    // Use the program object
    glUseProgram (m_ProgramObj);

    // Load the vertex position
    glVertexAttribPointer (0, 3, GL_FLOAT,
                           GL_FALSE, 3 * sizeof (GLfloat), verticesCoords);
    // Load the texture coordinate
    glVertexAttribPointer (1, 2, GL_FLOAT,
                           GL_FALSE, 2 * sizeof (GLfloat), textureCoords);

    glEnableVertexAttribArray (0);
    glEnableVertexAttribArray (1);

    // Bind the RGBA map
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_TextureId);

    // Set the RGBA map sampler to texture unit to 0
    glUniform1i(m_SamplerLoc, 0);
    m_offset=0.0+m_time;
    m_time=m_time+0.02;
    if(m_time>1.0)
        m_time=0.0;
    GLUtils::setFloat(m_ProgramObj, "u_Offset", m_offset);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

    m_offset = m_offset+0.4+m_time;
    GLUtils::setFloat(m_ProgramObj, "u_Offset", m_offset);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

    m_offset = m_offset+0.45+m_time;
    GLUtils::setFloat(m_ProgramObj, "u_Offset", m_offset);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);

}

void CoordSystemSample::Destroy()
{
    if (m_ProgramObj)
    {
        glDeleteProgram(m_ProgramObj);
        m_ProgramObj = GL_NONE;
    }
    if (m_ProgramObj1)
    {
        glDeleteProgram(m_ProgramObj1);
        m_ProgramObj1 = GL_NONE;
    }
}


/**
 * @param angleX 绕X轴旋转度数
 * @param angleY 绕Y轴旋转度数
 * @param ratio 宽高比
 * */
glm::mat4 CoordSystemSample::buildRotateX(float rad)
{
    glm::mat4 xrot = glm::mat4(1.0, 0.0, 0.0, 0.0,
                               0.0, cos(rad), -sin(rad), 0.0,
                               0.0, sin(rad), cos(rad), 0.0,
                               0.0, 0.0, 0.0, 1.0);
    return xrot;
}
glm::mat4 CoordSystemSample::buildRotateY(float rad)
{
    glm::mat4 yrot = glm::mat4(cos(rad), 0.0, sin(rad), 0.0,
                               0.0, 1.0, 0.0, 0.0,
                               -sin(rad), 0.0, cos(rad), 0.0,
                               0.0, 0.0, 0.0, 1.0);
    return yrot;
}
glm::mat4 CoordSystemSample::buildRotateZ(float rad)
{
    glm::mat4 zrot = glm::mat4(cos(rad), -sin(rad), 0.0, 0.0,
                               sin(rad), cos(rad), 0.0, 0.0,
                               0.0, 0.0, 1.0, 0.0,
                               0.0, 0.0, 0.0, 1.0);
    return zrot;
}
float distance_z = -0.2f;
void CoordSystemSample::UpdateMVPMatrix(glm::mat4 &mvpMatrix, int angleX, int angleY, float ratio)
{

}

void CoordSystemSample::UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY)
{

}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值