文章目录
  1. 1. 绘制一个纹理
  2. 2. 加入触摸事件以及填充纹理

自定义Node派生出来节点的绘制,并得到如下效果。

gridNode

绘制一个纹理

先从绘制一个纹理开始,具体的过程可以参考引擎的Sprite是如何绘制的。
我们定义一个从Node派生出来的类,并override draw函数,设置其绘制函数为onDraw。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#ifndef __ShaderDemo__GridNode__
#define __ShaderDemo__GridNode__

#include <stdio.h>
#include "cocos2d.h"

USING_NS_CC;


class GridNode : public Node {
public:

GridNode();
~GridNode();

virtual bool init(std::string fileName);
static GridNode* create(std::string fileName);

public:


void onDraw(const Mat4& transform, uint32_t flags);
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags);

private:

CustomCommand _command;
GLProgram* program;

//texture maybe not
GLuint _textureID;
std::string _textureName;

//vertexbuffer
GLsizei _bufferCount;
GLuint _vbo;
V2F_C4B_T2F* _buffer;

int _bufferCapacity;

bool _enable;
};


#endif /* defined(__ShaderDemo__GridNode__) */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//  GridNode.cpp

bool GridNode::init(std::string fileName)
{
if (!Node::init()) {
return false;
}

//program
program = new GLProgram;
program->initWithFilenames("gridnode.vert", "gridnode.frag");
program->link();
program->updateUniforms();

_textureName = fileName;
_textureID = Director::getInstance()->getTextureCache()->addImage(_textureName)->getName();

auto texture = Director::getInstance()->getTextureCache()->getTextureForKey(fileName);
auto size = texture->getContentSize();
setContentSize(size);

//setuo _buffer
//初始化本地的数据
setUpBuffer( Vec2(0,0),Vec2(0,size.height), Vec2(size.width,size.height), Vec2(size.width,0), Color4B(155,0,0,255));

//vbo
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW);
// vertex
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
// color
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
// texcoord
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));


reture true;
}


void GridNode::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
_command.init(_globalZOrder);
//_command.func = CC_CALLBACK_0(GridNode::onDraw, this, _modelViewTransform, flags);
_command.func = std::bind(&GridNode::onDraw, this, _modelViewTransform,flags);
renderer->addCommand(&_command);
}


void GridNode::onDraw(const Mat4& transform, uint32_t flags)
{

program->use();
program->setUniformsForBuiltins(transform);

glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacity, _buffer, GL_STREAM_DRAW);

//uniform "_enable" 是否开启
GLint enable = glGetUniformLocation(program->getProgram(), "_enable");
program->setUniformLocationWith1i(enable, _enable);

GL::bindTexture2D(_textureID);


GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_TEX_COORD);
// vertex
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
// color
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
// textrood
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
glDrawArrays(GL_TRIANGLES, 0, _bufferCount);
glBindBuffer(GL_ARRAY_BUFFER, 0);

CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferCount);
CHECK_GL_ERROR_DEBUG();

GL::bindTexture2DN(0, _textureID);
}

唯一需要注意的一点是纹理的坐标左上方为(0,0)点,要清楚本地顶点数据与其的对应关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//  GridNode.cpp

void GridNode::setUpBuffer(const Vec2 &lb, const Vec2 &lt, const Vec2 &rt, const Vec2& rb, const Color4B &color)
{
unsigned int vertex_count = 2*3;
ensureCapacity(vertex_count);

//l = left , r = right , t = top , b = bottom
V2F_C4B_T2F a = {lb, Color4B(color), Tex2F( 0.0, 1.0) };
V2F_C4B_T2F b = {lt, Color4B(color), Tex2F( 0.0, 0.0) };
V2F_C4B_T2F c = {rt, Color4B(color), Tex2F( 1.0, 0.0) };
V2F_C4B_T2F d = {rb, Color4B(color), Tex2F( 1.0, 1.0) };

//两个三角形
V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
V2F_C4B_T2F_Triangle triangle0 = {a, b, c};
V2F_C4B_T2F_Triangle triangle1 = {a, c, d};
triangles[0] = triangle0;
triangles[1] = triangle1;

_bufferCount += vertex_count;
}

加入触摸事件以及填充纹理

添加触摸事件监听,定义定义touchbegan与touchended

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// GridNode.cpp

bool GridNode::onTouchbegan(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
Vec2 pos = touch->getLocation();
if (pos.x > _position.x &&
pos.x < _position.x + _contentSize.width &&
pos.y > _position.y &&
pos.y < _position.y + _contentSize.height) {

return true;
}

return false;
}

void GridNode::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
Vec2 pos = touch->getLocation();
if (pos.x > _position.x &&
pos.x < _position.x + _contentSize.width &&
pos.y > _position.y &&
pos.y < _position.y + _contentSize.height) {

_enable = !_enable;
}
}

不赘述触摸监听的添加了,非常的容易。
最后编写自定义的shader实现效果。

vertex Shader没有什么特殊的,点,颜色,纹理。使用自带也可以。
fragment Shader中判断对像素点的透明度。找出大于零的传入我们的颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//  fragment Shader

varying vec2 v_texCoord;
varying vec4 v_color;

uniform bool _enable;

void main()
{
vec4 color = texture2D(CC_Texture0, v_texCoord);
if (_enable && color.a > 0.0)
color = v_color;
gl_FragColor = color;
}

Github:https://github.com/JackLN/ShaderDemo.git

文章目录
  1. 1. 绘制一个纹理
  2. 2. 加入触摸事件以及填充纹理