openglesForC++实现两幅图像混合的效果

本文介绍如何使用C++通过OpenGLES在矩形上加载两幅图片作为纹理,展示不同混合效果。通过调整纹理坐标,实现图像移动。示例包括两种混合方式的 shader 实现,并提供了完整代码的下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本例将在一个矩形上加载两幅不同的图片作为纹理,然后采用不同的混合方式呈现不同的效果,并且可以通过改变纹理X,Y坐标,实现移动的效果

两幅原始图片:



shader实现:

	/// 初始化函数
	virtual bool    initialize()
	{
		const char* vs =
		{
			"precision lowp float; "//指定float精度
			"uniform   mat4 _MVP;"
			"attribute vec2 _position;"
			"attribute vec2 _uv;"
			"attribute vec4 _color;"
			"varying   vec4 _outColor;"//片元着色器中需要使用
			"varying   vec2 _outUV;"//片元着色器中需要使用

			"void main()"
			"{"
			"   vec4    pos =   vec4(_position,0,1);"
			"   _outColor   =   _color;"
			"   _outUV      =   _uv;"
			"   gl_Position =   _MVP * pos;"
			"}"
		};
		//实现了两幅图像混合的效果
		//gl_FragColor    =   tColor0  *tColor1和gl_FragColor    =   tColor0  +tColor1 gl_FragColor    =   tColor0*0.2  + tColor1*0.8
		const char* ps =
		{
			"precision  lowp float; "
			"uniform   sampler2D _texture;\n"
			"uniform   sampler2D _texture1;\n"
			"uniform   float    _uvAnim;\n"
			"varying   vec4      _outColor;\n"
			"varying   vec2      _outUV;\n"
			"void main()"
			"{"
			"   vec4    tColor0  =   texture2D(_texture,_outUV);\n"//纹理采样
			"   vec2    newUV = vec2(_uvAnim + _outUV.x,_outUV.y);"//不断变化采样纹理图的x坐标,使纹理看起来有移动的效果 ,同理也可以变换y坐标,使之纵向移动
			"   vec4    tColor1  =   texture2D(_texture1,newUV);\n"
			"   gl_FragColor    =   tColor0*0.2  + tColor1*0.8;\n"//两种纹理混合
			"}"
		};

		bool    res = createProgram(vs, ps);
		if (res)
		{
			_position = glGetAttribLocation(_programId, "_position");
			_color = glGetAttribLocation(_programId, "_color");
			_uv = glGetAttribLocation(_programId, "_uv");
			_texture = glGetUniformLocation(_programId, "_texture");
			_texture1 = glGetUniformLocation(_programId, "_texture1");
			_MVP = glGetUniformLocation(_programId, "_MVP");
			_uvAnim = glGetUniformLocation(_programId, "_uvAnim");


		}
		return  res;
	}
gl_FragColor    =   tColor0  *tColor1效果

gl_FragColor    =   tColor0  +tColor1效果

 gl_FragColor    =   tColor0*0.2  + tColor1*0.8效果

完整shader实现类:

#pragma once

#include <assert.h>

class    ShaderId
{
public:
	ShaderId()
	{
		_shaderId = -1;
	}
	int _shaderId;
};


/**
*   程序
*/
class   ProgramId
{
public:
	int         _programId;
	ShaderId    _vertex;
	ShaderId    _fragment;
public:
	ProgramId()
	{
		_programId = -1;
	}
public:
	/**
	*   加载函数
	*/
	bool    createProgram(const char* vertex, const char* fragment)
	{
		bool        error = false;
		do
		{
			if (vertex)
			{
				_vertex._shaderId = glCreateShader(GL_VERTEX_SHADER);
				glShaderSource(_vertex._shaderId, 1, &vertex, 0);
				glCompileShader(_vertex._shaderId);

				GLint   compileStatus;
				glGetShaderiv(_vertex._shaderId, GL_COMPILE_STATUS, &am
bool AnimationManager::Load(const std::string &fileName;) { float width; float height; const char * path = MakePath(fileName.c_str()); std::string fullFileName = std::string(path); // Á‡„ÛʇÂÏ ÚÂÍÒÚÛÛ - Á‡ÔËÒ˚‚‡ÂÏ Û͇Á‡ÚÂθ ̇ Ì ‚ "tex", ÍÓÚÓ˚È ËÒÔÓθÁÛÂÚÒˇ ‰‡Î // // ̇˜‡ÎÓ ·ÎÓ͇ - ˝ÚÓÚ ÍÓ‰ ÔË ÔÓÚËÓ‚‡ÌËË Ì‡‰Ó ÔÂÂÔËÒ‡Ú¸ // HGE *hge = hgeCreate(HGE_VERSION); GLuint tex = TextureLoad((fullFileName.substr(0, fullFileName.length() - 3) + "png").c_str(), width, height); if (tex == 0) { // ÂÒÎË ÚÂÍÒÚÛ‡ Ì ̇ȉÂ̇ - ÔÂ˚‚‡ÂÏ Á‡„ÛÁÍÛ, ‚ÓÁ‚‡˘‡ÂÏ "false" return false; } // ÍÓ̈ ·ÎÓ͇ TiXmlDocument doc; if (doc.LoadFile(path)) { // ÂÒÎË Ù‡ÈÎ ÒÛ˘ÂÒÚ‚ÛÂÚ - ˜ËÚ‡ÂÏ XML Ò ÓÔËÒ‡ÌËÂÏ ‡ÌËχˆËÈ TiXmlElement *root = doc.RootElement(); TiXmlElement *animation = root->FirstChildElement("Animation"); while (animation) { const char *id = animation->Attribute("id"); // ¬Õ»Ã¿Õ»≈ - ËÁ ‰‚Ûı Ë ·ÓΠ‡ÌËχˆËÈ Ò Ó‰Ë̇ÍÓ‚˚ÏË id - ·Û‰ÂÚ Á‡„ÛÊÂ̇ ÚÓθÍÓ ÔÂ‚‡ˇ if (_animations.find(id) == _animations.end()) { _animations[id] = new Animation(animation, tex, width, height); } animation = animation->NextSiblingElement("Animation"); } _textures.push_back(tex); printf("file loaded %s\n", path); return true; } else { // Ù‡ÈÎ ‡ÌËχˆËÈ Ì ̇ȉÂÌ ËÎË Â„Ó Ì ۉ‡ÎÓÒ¸ ÔÓ˜ËÚ‡Ú¸ // ‚˚„ÛʇÂÏ ÚÂÍÒÚÛÛ, ‚ÓÁ‚‡˘‡ÂÏ "false" // // ̇˜‡ÎÓ ·ÎÓ͇ - ˝ÚÓÚ ÍÓ‰ ÔË ÔÓÚËÓ‚‡ÌËË Ì‡‰Ó ÔÂÂÔËÒ‡Ú¸ //hge->Texture_Free(tex); // ÍÓ̈ ·ÎÓ͇ printf("file not found: %s\n", path); return false; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值