运行环境:
mac 10.12.2
xcode Version 8.2.1
cocos2dx-x-3.13.1
代码:
新建cocos2dx项目,具体操作官网有教程。新建好后,
新建Test.cpp,代码如下:
//
// Test.cpp
// MutilTextures
//
// Created by zhufu on 2017/3/28.
//
//
#include "Test.h"
Test* Test::create()
{
Test* test = new(std::nothrow) Test();
if(test && test->init())
{
test->autorelease();
return test;
}
else
{
delete test;
test = nullptr;
return nullptr;
}
}
bool Test::init()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
initCommand();
loadShader();
loadTexture();
loadRectangle();
return true;
}
void Test::flipVertical(int width, int height, unsigned char* arr)
{
int index = 0, f_index, cycle=height/2;
char buf;
for (int i = 0; i < cycle; i++)
{
for (int j = 0; j < width*Test::Format_RGBA; j++)
{
//当前像素
index = i*width*Test::Format_RGBA + j;
//需要交换的像素
f_index = (height - 1 - i)*width*Test::Format_RGBA + j;
//缓存当前像素
buf = arr[index];
//交换像素
arr[index] = arr[f_index];
//交换回像素
arr[f_index] = buf;
}
}
}
void Test::loadShader()
{
_glProgram = new GLProgram();
_glProgram->initWithFilenames("shader/myVertexShader.vsh", "shader/myFragmentShader.fsh");
_glProgram->link();
}
void Test::loadTexture()
{
Image *image1 = new Image;
std::string imagePath1 = FileUtils::getInstance()->fullPathForFilename("boy.png");
image1->initWithImageFile(imagePath1);
unsigned char *imageData1 = image1->getData();
int width1 = image1->getWidth();
int height1 = image1->getHeight();
flipVertical(width1, height1, imageData1);
//别忘了释放image内存
// CC_SAFE_DELETE(image);
glGenTextures(1, &textureID1);
glBindTexture(GL_TEXTURE_2D, textureID1);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width1, height1, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData1);
Image *image2 = new Image;
std::string imagePath2 = FileUtils::getInstance()->fullPathForFilename("girl.png");
image2->initWithImageFile(imagePath2);
unsigned char *imageData2 = image2->getData();
int width2 = image2->getWidth();
int height2 = image2->getHeight();
flipVertical(width2, height2, imageData2);
glGenTextures(1, &textureID2);
glBindTexture(GL_TEXTURE_2D, textureID2);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData2);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Test::loadRectangle()
{
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
//make and bind VBO;
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//put the rectangle vertices(XYZ) and texture coordinates (UV) into the vbo
GLfloat textureData[] = {
// X Y Z U V
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 0.0f, 0.0f, 0.0f,
1.0f,-1.0f , 0.0f, 1.0f, 0.0f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(textureData), textureData, GL_STATIC_DRAW);
//connect the xyz to the "vert" arrribute of the vertex shader
glEnableVertexAttribArray(_glProgram->getAttribLocation("vert"));
glVertexAttribPointer(_glProgram->getAttribLocation("vert"), 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), nullptr);
glEnableVertexAttribArray(_glProgram->getAttribLocation("vertTexCoord"));
glVertexAttribPointer(_glProgram->getAttribLocation("vertTexCoord"), 2, GL_FLOAT, GL_TRUE, 5 * sizeof(GLfloat), (const GLvoid*)(3*sizeof(GLfloat)));
}
void Test::initCommand()
{
_command.init(getLocalZOrder());
_command.func = CC_CALLBACK_0(Test::onDraw, this);
}
void Test::draw(Renderer *renderer, const Mat4 &transform, uint32_t platform)
{
onDraw();
}
void Test::onDraw()
{
//clear everything
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
//bind the program (the shaders)
_glProgram->use();
//bind the texture and set the "tex" uniform in the fragment shader
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, textureID1);
GL::bindTexture2DN(0, textureID1);
GLuint tex1 = glGetUniformLocation(_glProgram->getProgram(), "texture1");
glUniform1i(tex1, 0);
// glActiveTexture(GL_TEXTURE1);
// glBindTexture(GL_TEXTURE_2D, textureID2);
GL::bindTexture2DN(1, textureID2);
GLuint tex2 =glGetUniformLocation(_glProgram->getProgram(), "texture2");
glUniform1i(tex2, 1);
//bind the vao
glBindVertexArray(_vao);
//draw the vao
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
新建Test.h,代码如下:
//
// Test.h
// MutilTextures
//
// Created by zhufu on 2017/3/28.
//
//
#ifndef Test_h
#define Test_h
#include
USING_NS_CC;
class Test : public Node
{
public:
enum Format {
Format_Grayscale = 1, /**< one channel: grayscale */
Format_GrayscaleAlpha = 2, /**< two channels: grayscale and alpha */
Format_RGB = 3, /**< three channels: red, green, blue */
Format_RGBA = 4 /**< four channels: red, green, blue, alpha */
};
static Test* create();
virtual bool init() override;
virtual void draw(Renderer* renderer, const Mat4 &transform, uint32_t platform) override;
void onDraw();
void loadShader();
void loadTexture();
void loadRectangle();
void initCommand();
void flipVertical(int width, int height, unsigned char* arr);
private:
GLuint textureID1;
GLuint textureID2;
GLProgram* _glProgram;
GLuint _vao;
CustomCommand _command;
};
#endif /* Test_h */
如图:
修改HelloWorldScene.cpp,
先
include "Test.h"
再修改CreateScene方法:
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
auto test = Test::create();
scene->addChild(test);
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
如图:
在Resources方位夹下新建shader文件夹,再在shader新建myVertexShader.vsh和myFragmentShader.fsh文件。
如图:
myVertexShader.vsh
attribute vec3 vert;
attribute vec2 vertTexCoord;
varying vec2 textureOut;
void main() {
// Pass the tex coord straight through to the fragment shader
textureOut = vertTexCoord;
gl_Position = vec4(vert, 1);
}
myFragmentShader.fsh
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 textureOut;
void main() {
vec4 col1 = texture2D(texture1, textureOut);
vec4 col2 = texture2D(texture2, textureOut);
gl_FragColor = mix(col1, col2, 0.5);
}
修改成:
还有,这次的图片要自己去找了。
接下来,可以开心地运行程序了。
运行效果: