OpenGL ES 学习教程(四) 买来墙纸,给立方体贴上!

上一篇制作了一个 彩色的旋转的 Cube ,丑爆了!

我不喜欢这种纯色的界面,想象一下,上图如果是纯色的,嗯。高大的武士,蓝色的。敏捷的女刺客,红色的。感觉不好。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

如果想实现上图中的效果,那就要把 图片 贴到 人物模型上。这个一般是由美术同事们来完成 。

我们就来给昨天做好的 Cube ,贴上一张图片吧 ,就像给墙壁贴上墙纸。


首先来了解下 纹理坐标 和 顶点坐标

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

学术上,把一张图片 贴到 一个平面上,叫做纹理映射。

怎么映射呢?

看上图中,左边是顶点坐标(-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)
};
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
2、使用FreeImage读取图片的RGBA数据。

我写了一个 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);
}

3、在Shader 中添加 图片纹理变量。我们要在C++代码中把 读取出来的图片RGBA数据设置到Shader中。在GLProgram_Texture.h 文件中。

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值