PuzzleSDK
ShaderTest2.cpp
浏览该文件的文档.
1/****************************************************************************
2 Copyright (c) 2014-2016 Chukong Technologies Inc.
3 Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
4
5 http://www.cocos2d-x.org
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 THE SOFTWARE.
24 ****************************************************************************/
25
26#include "ShaderTest2.h"
27#include "ShaderTest.h"
28#include "../testResource.h"
29#include "cocos2d.h"
30#include "renderer/backend/Device.h"
31#include <tuple>
32
34
35#define SET_UNIFORM(ps, name, value) do { \
36decltype(value) __v = value; \
37auto __loc = (ps)->getUniformLocation(name); \
38(ps)->setUniform(__loc, &__v, sizeof(__v)); \
39} while(false)
40
41#define SET_TEXTURE(ps, name, idx, value) do { \
42auto * __v = value; \
43auto __loc = (ps)->getUniformLocation(name); \
44(ps)->setTexture(__loc, idx, __v); \
45} while(false)
46
47
48Shader2Tests::Shader2Tests()
49{
52}
53
54//
55// EffectSprite
56//
57static int tuple_sort( const std::tuple<ssize_t,Effect*,QuadCommand> &tuple1, const std::tuple<ssize_t,Effect*,QuadCommand> &tuple2 )
58{
59 return std::get<0>(tuple1) < std::get<0>(tuple2);
60}
61
62
63static void updateUniforms(backend::ProgramState *programState)
64{
65 float time = Director::getInstance()->getTotalFrames() * Director::getInstance()->getAnimationInterval();
66 Vec4 uTime(time / 10.0f, time, time * 2.0f, time * 4.0f);
67 Vec4 sinTime(time / 8.0f, time / 4.0f, time / 2.0f, sinf(time));
68 Vec4 cosTime(time / 8.0f, time / 4.0f, time / 2.0f, cosf(time));
69
70 SET_UNIFORM(programState, "u_Time", uTime);
71 SET_UNIFORM(programState, "u_SinTime", sinTime);
72 SET_UNIFORM(programState, "u_CosTime", cosTime);
73}
74
75class Effect;
76class EffectSprite : public Sprite
77{
78public:
79 static EffectSprite *create(const std::string& filename) {
80 auto ret = new (std::nothrow) EffectSprite;
81 if(ret && ret->initWithFile(filename)) {
82 ret->autorelease();
83 return ret;
84 }
85 CC_SAFE_RELEASE(ret);
86 return nullptr;
87 }
88
89 void setEffect(Effect* effect) {
90 if(_defaultEffect != effect) {
91 effect->setTarget(this);
92
93 CC_SAFE_RELEASE(_defaultEffect);
94 _defaultEffect = effect;
95 CC_SAFE_RETAIN(_defaultEffect);
96
97 setProgramState(_defaultEffect->getProgramState());
98 }
99 }
100 void addEffect(Effect *effect, ssize_t order) {
101 effect->retain();
102 effect->setTarget(this);
103
104 _effects.push_back(std::make_tuple(order,effect,QuadCommand()));
105
106 std::sort(std::begin(_effects), std::end(_effects), tuple_sort);
107 }
108
109 void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override
110 {
111#if CC_USE_CULLING
112 // Don't do calculate the culling if the transform was not updated
113 _insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
114
115 if(_insideBounds)
116#endif
117 {
118 // negative effects: order < 0
119 int idx=0;
120 for(auto &effect : _effects) {
121
122 if(std::get<0>(effect) >=0)
123 break;
124 auto* programState = std::get<1>(effect)->getProgramState();
125 if (programState)
126 {
127 QuadCommand &q = std::get<2>(effect);
128 q.init(_globalZOrder, _texture, _blendFunc, &_quad, 1, transform, flags);
129 updateUniforms(programState);
130 renderer->addCommand(&q);
131 }
132 idx++;
133 }
134
135 // normal effect: order == 0
136 _trianglesCommand.init(_globalZOrder, _texture, _blendFunc, _polyInfo.triangles, transform, flags);
137
138 updateUniforms(_trianglesCommand.getPipelineDescriptor().programState);
139 renderer->addCommand(&_trianglesCommand);
140
141 // positive effects: order >= 0
142 for(auto it = std::begin(_effects)+idx; it != std::end(_effects); ++it) {
143 QuadCommand &q = std::get<2>(*it);
144 auto* programState = std::get<1>(*it)->getProgramState();
145 updateUniforms(programState);
146 q.init(_globalZOrder, _texture, _blendFunc, &_quad, 1, transform, flags);
147 q.getPipelineDescriptor().programState = programState;
148 renderer->addCommand(&q);
149 idx++;
150 }
151 }
152 }
153protected:
155 {
156 _effects.reserve(2);
157 }
159 for(auto &tuple : _effects) {
160 std::get<1>(tuple)->release();
161 }
162 CC_SAFE_RELEASE(_defaultEffect);
163 }
164
165 std::vector<std::tuple<ssize_t,Effect*,QuadCommand>> _effects;
167};
168
169//
170// Effect
171//
172
173bool Effect::initProgramState(const std::string &fragmentFilename)
174{
175 auto fileUtiles = FileUtils::getInstance();
176 auto fragmentFullPath = fileUtiles->fullPathForFilename(fragmentFilename);
177 auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
178
179#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
180 _fragSource = fragSource;
181#endif
182 auto program = backend::Device::getInstance()->newProgram(positionTextureColor_vert, fragSource.c_str());
183 auto programState = new backend::ProgramState(program);
184 CC_SAFE_RELEASE(_programState);
185 CC_SAFE_RELEASE(program);
186 _programState = programState;
187
188 return _programState != nullptr;
189}
190
192{
193}
194
196{
197 CC_SAFE_RELEASE_NULL(_programState);
198}
199
200// Blur
201class EffectBlur : public Effect
202{
203public:
205 virtual void setTarget(EffectSprite *sprite) override;
206 void setBlurRadius(float radius);
207 void setBlurSampleNum(float num);
208
209protected:
210 bool init(float blurRadius = 10.0f, float sampleNum = 5.0f);
211
214};
215
217{
218 if (_programState == nullptr)
219 return;
220
221 Size size = sprite->getTexture()->getContentSizeInPixels();
222 SET_UNIFORM(_programState, "resolution", size);
223 SET_UNIFORM(_programState, "blurRadius", _blurRadius);
225}
226
227bool EffectBlur::init(float blurRadius, float sampleNum)
228{
229 initProgramState("Shaders/example_Blur.fsh");
230 _blurRadius = blurRadius;
231 _blurSampleNum = sampleNum;
232
233 return true;
234}
235
237{
238 _blurRadius = radius;
239}
240
242{
243 _blurSampleNum = num;
244}
245
246// Outline
247class EffectOutline : public Effect
248{
249public:
251
252 bool init()
253 {
254 initProgramState("Shaders/example_Outline.fsh");
255
256 Vec3 color(1.0f, 0.2f, 0.3f);
257 float radius = 0.01f;
258 float threshold = 1.75;
259
260 SET_UNIFORM(_programState, "u_outlineColor", color);
261 SET_UNIFORM(_programState, "u_radius", radius);
262 SET_UNIFORM(_programState, "u_threshold", threshold);
263 return true;
264 }
265};
266
267// Noise
268class EffectNoise : public Effect
269{
270public:
272
273protected:
274 bool init() {
275 initProgramState("Shaders/example_Noisy.fsh");
276 return true;
277 }
278
279 virtual void setTarget(EffectSprite* sprite) override
280 {
281 auto s = sprite->getTexture()->getContentSizeInPixels();
282 SET_UNIFORM(_programState, "resolution", Vec2(s.width, s.height));
283 }
284};
285
286// Edge Detect
288{
289public:
291
292protected:
293 bool init() {
294 initProgramState("Shaders/example_EdgeDetection.fsh");
295 return true;
296 }
297
298 virtual void setTarget(EffectSprite* sprite) override
299 {
300 auto s = sprite->getTexture()->getContentSizeInPixels();
301 SET_UNIFORM(_programState, "resolution", Vec2(s.width, s.height));
302 }
303};
304
305// Grey
307{
308public:
310
311protected:
312 bool init() {
313 initProgramState("Shaders/example_GreyScale.fsh");
314 return true;
315 }
316};
317
318// Sepia
319class EffectSepia : public Effect
320{
321public:
323
324protected:
325 bool init() {
326 initProgramState("Shaders/example_Sepia.fsh");
327 return true;
328 }
329};
330
331// bloom
332class EffectBloom : public Effect
333{
334public:
336
337protected:
338 bool init() {
339 initProgramState("Shaders/example_Bloom.fsh");
340 return true;
341 }
342
343 virtual void setTarget(EffectSprite* sprite) override
344 {
345 auto s = sprite->getTexture()->getContentSizeInPixels();
346 SET_UNIFORM(_programState, "resolution", Vec2(s.width, s.height));
347 }
348};
349
350// cel shading
352{
353public:
355
356protected:
357 bool init() {
358 initProgramState("Shaders/example_CelShading.fsh");
359 return true;
360 }
361
362 virtual void setTarget(EffectSprite* sprite) override
363 {
364 auto s = sprite->getTexture()->getContentSizeInPixels();
365 SET_UNIFORM(_programState, "resolution", Vec2(s.width, s.height));
366 }
367};
368
369// Lens Flare
371{
372public:
374
375protected:
376 bool init() {
377 initProgramState("Shaders/example_LensFlare.fsh");
378 return true;
379 }
380
381 virtual void setTarget(EffectSprite* sprite) override
382 {
383 auto s = sprite->getTexture()->getContentSizeInPixels();
384 SET_UNIFORM(_programState, "textureResolution", Vec2(s.width, s.height));
385 s = Director::getInstance()->getWinSize();
386 SET_UNIFORM(_programState, "resolution", Vec2(s.width, s.height));
387
388 }
389};
390
392{
393public:
395 static EffectNormalMapped* create(const std::string&normalMapFileName)
396 {
397 EffectNormalMapped *normalMappedSprite = new (std::nothrow) EffectNormalMapped();
398 if (normalMappedSprite && normalMappedSprite->init() && normalMappedSprite->initNormalMap(normalMapFileName))
399 {
400
401 normalMappedSprite->autorelease();
402 return normalMappedSprite;
403 }
404 CC_SAFE_DELETE(normalMappedSprite);
405 return nullptr;
406 }
407 void setKBump(float value);
408 void setLightPos(const Vec3& pos);
409 void setLightColor(const Color4F& color);
410 float getKBump()const{return _kBump;}
411protected:
412 bool init();
413 bool initNormalMap(const std::string&normalMapFileName);
414 virtual void setTarget(EffectSprite* sprite) override;
417 Color4F _lightColor;
418 float _kBump;
419};
420
422{
423 initProgramState("Shaders3D/Normal.frag");
424 _kBump = 2;
425 return true;
426}
427bool EffectNormalMapped::initNormalMap(const std::string& normalMapFileName)
428{
429 auto normalMapTexture = Director::getInstance()->getTextureCache()->addImage(normalMapFileName);
430 SET_TEXTURE(_programState, "u_normalMap", 1, normalMapTexture->getBackendTexture());
431 return true;
432}
434{
435 _sprite = sprite;
436 SET_UNIFORM(_programState, "u_kBump", _kBump);
437 SET_UNIFORM(_programState, "u_contentSize", Vec2(sprite->getContentSize().width, sprite->getContentSize().height));
438}
439
441{
442 _kBump = value;
443 SET_UNIFORM(_programState, "u_kBump", _kBump);
444
445}
446
448{
449 _lightPos = pos;
450 SET_UNIFORM(_programState, "u_lightPosInLocalSpace", Vec4(_lightPos.x, _lightPos.y, _lightPos.z, 1));
451}
452
453void EffectNormalMapped::setLightColor(const Color4F& color)
454{
455 _lightColor = color;
456 SET_UNIFORM(_programState, "u_diffuseL", Vec3(_lightColor.r, _lightColor.g, _lightColor.b));
457
458}
459
461{
462}
463
465{
466 if (ShaderTestDemo2::init()) {
467
468 auto layer = LayerColor::create(Color4B::BLUE);
469 this->addChild(layer);
470
471 auto s = Director::getInstance()->getWinSize();
472
473 auto itemPrev = MenuItemImage::create("Images/b1.png", "Images/b2.png",
474 [&](Ref *sender) {
475 _vectorIndex--;
476 if(_vectorIndex<0)
477 _vectorIndex = _effects.size()-1;
479 });
480
481 auto itemNext = MenuItemImage::create("Images/f1.png", "Images/f2.png",
482 [&](Ref *sender) {
483 _vectorIndex++;
484 if(_vectorIndex>=_effects.size())
485 _vectorIndex = 0;
487 });
488
489 auto menu = Menu::create(itemPrev, itemNext, nullptr);
490 menu->alignItemsHorizontally();
491 menu->setScale(0.5);
492 menu->setAnchorPoint(Vec2(0.0f,0.0f));
493 menu->setPosition(Vec2(s.width/2,70.0f));
494 addChild(menu);
495
496 _sprite = EffectSprite::create("Images/grossini.png");
497 _sprite->setPosition(Vec2(0.0f, s.height/2));
498 addChild(_sprite);
499
500 auto jump = JumpBy::create(4, Vec2(s.width,0.0f), 100, 4);
501 auto rot = RotateBy::create(4, 720);
502 auto spawn = Spawn::create(jump, rot, nullptr);
503 auto rev = spawn->reverse();
504 auto seq = Sequence::create(spawn, rev, nullptr);
505 auto repeat = RepeatForever::create(seq);
506 _sprite->runAction(repeat);
507
508 // set the Effects
509 _effects.pushBack(EffectBlur::create());
510 _effects.pushBack(EffectOutline::create());
511 _effects.pushBack(EffectNoise::create());
512 _effects.pushBack(EffectEdgeDetect::create());
513 _effects.pushBack(EffectGreyScale::create());
514 _effects.pushBack(EffectSepia::create());
515 _effects.pushBack(EffectBloom::create());
516 _effects.pushBack(EffectCelShading::create());
517 _effects.pushBack(EffectLensFlare::create());
518
519 _vectorIndex = 0;
521
522// _sprite->addEffect( _effects.at(8), -10 );
523// _sprite->addEffect( _effects.at(1), 1 );
524
525 return true;
526 }
527 return false;
528}
529
531{
532}
533
535{
536 if (ShaderTestDemo2::init()) {
537
538 auto s = Director::getInstance()->getWinSize();
539 _sprite = EffectSprite::create("Images/elephant1_Diffuse.png");
540 //auto contentSize = _sprite->getContentSize();
541 _sprite->setPosition(Vec2(s.width/2, s.height/2));
542 addChild(_sprite);
543
544 auto lampEffect = EffectNormalMapped::create("Images/elephant1_Normal.png");
545
546 Vec3 pos(150,150, 50);
547 _lightSprite = Sprite::create("Images/ball.png");
548 this->addChild(_lightSprite);
549 _lightSprite->setPosition(Vec2(pos.x, s.height- pos.y));
550 Mat4 mat = _sprite->getNodeToWorldTransform();
551 Point lightPosInLocalSpace = PointApplyAffineTransform(Vec2(pos.x, pos.y), _sprite->getWorldToNodeAffineTransform());
552 lampEffect->setLightColor(Color4F(1,1,1,1));
553 lampEffect->setLightPos(Vec3(lightPosInLocalSpace.x, lightPosInLocalSpace.y, 50.0f));
554 lampEffect->setKBump(2);
555 _sprite->setEffect(lampEffect);
556 _effect = lampEffect;
557 auto listener = EventListenerTouchAllAtOnce::create();
558 listener->onTouchesBegan = CC_CALLBACK_2(EffectSpriteLamp::onTouchesBegan, this);
559 listener->onTouchesMoved = CC_CALLBACK_2(EffectSpriteLamp::onTouchesMoved, this);
560 listener->onTouchesEnded = CC_CALLBACK_2(EffectSpriteLamp::onTouchesEnded, this);
561 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
562 return true;
563 }
564 return false;
565}
566
567
568void EffectSpriteLamp::onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)
569{
570 for ( auto &item: touches )
571 {
572 auto touch = item;
573 auto s = Director::getInstance()->getWinSize();
574 Point loc_winSpace = touch->getLocationInView();
575 _lightSprite->setPosition(Vec2( loc_winSpace.x, s.height - loc_winSpace.y));
576 Vec3 pos(loc_winSpace.x,loc_winSpace.y, 50);
577 Mat4 mat = _sprite->getNodeToWorldTransform();
578 Point lightPosInLocalSpace = PointApplyAffineTransform(Vec2(pos.x, pos.y), _sprite->getWorldToNodeAffineTransform());
579 ((EffectNormalMapped*)_effect)->setLightPos(Vec3(lightPosInLocalSpace.x, lightPosInLocalSpace.y, 50.0f));
580 }
581}
582
583void EffectSpriteLamp::onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event)
584{
585 for ( auto &item: touches )
586 {
587 auto touch = item;
588 auto s = Director::getInstance()->getWinSize();
589 Point loc_winSpace = touch->getLocationInView();
590 _lightSprite->setPosition(Vec2( loc_winSpace.x, s.height - loc_winSpace.y));
591 Vec3 pos(loc_winSpace.x,loc_winSpace.y, 50);
592 Mat4 mat = _sprite->getNodeToWorldTransform();
593 Point lightPosInLocalSpace = PointApplyAffineTransform(Vec2(pos.x, pos.y), _sprite->getWorldToNodeAffineTransform());
594 ((EffectNormalMapped*)_effect)->setLightPos(Vec3(lightPosInLocalSpace.x, lightPosInLocalSpace.y, 50.0f));
595 }
596}
597
598void EffectSpriteLamp::onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event)
599{
600 for ( auto &item: touches )
601 {
602 auto touch = item;
603 auto s = Director::getInstance()->getWinSize();
604 Point loc_winSpace = touch->getLocationInView();
605 _lightSprite->setPosition(Vec2( loc_winSpace.x, s.height - loc_winSpace.y));
606 Vec3 pos(loc_winSpace.x,loc_winSpace.y, 50);
607 Mat4 mat = _sprite->getNodeToWorldTransform();
608 Point lightPosInLocalSpace = PointApplyAffineTransform(Vec2(pos.x, pos.y), _sprite->getWorldToNodeAffineTransform());
609 ((EffectNormalMapped*)_effect)->setLightPos(Vec3(lightPosInLocalSpace.x, lightPosInLocalSpace.y, 50.0f));
610 }
611}
#define ADD_TEST_CASE(__className__)
Definition: BaseTest.h:211
static int tuple_sort(const std::tuple< ssize_t, Effect *, QuadCommand > &tuple1, const std::tuple< ssize_t, Effect *, QuadCommand > &tuple2)
Definition: ShaderTest2.cpp:57
static void updateUniforms(backend::ProgramState *programState)
Definition: ShaderTest2.cpp:63
USING_NS_CC
Definition: ShaderTest2.cpp:33
#define SET_TEXTURE(ps, name, idx, value)
Definition: ShaderTest2.cpp:41
#define SET_UNIFORM(ps, name, value)
Definition: ShaderTest2.cpp:35
CREATE_FUNC(EffectBloom)
virtual void setTarget(EffectSprite *sprite) override
void setBlurSampleNum(float num)
virtual void setTarget(EffectSprite *sprite) override
CREATE_FUNC(EffectBlur)
float _blurSampleNum
bool init(float blurRadius=10.0f, float sampleNum=5.0f)
void setBlurRadius(float radius)
float _blurRadius
virtual void setTarget(EffectSprite *sprite) override
CREATE_FUNC(EffectCelShading)
CREATE_FUNC(EffectEdgeDetect)
virtual void setTarget(EffectSprite *sprite) override
CREATE_FUNC(EffectGreyScale)
std::string _fragSource
Definition: ShaderTest2.h:57
cocos2d::backend::ProgramState * _programState
Definition: ShaderTest2.h:55
virtual void setTarget(EffectSprite *sprite)
Definition: ShaderTest2.h:49
bool initProgramState(const std::string &fragmentFilename)
cocos2d::backend::ProgramState * getProgramState() const
Definition: ShaderTest2.h:48
virtual ~Effect()
CREATE_FUNC(EffectLensFlare)
virtual void setTarget(EffectSprite *sprite) override
CREATE_FUNC(EffectNoise)
virtual void setTarget(EffectSprite *sprite) override
EffectSprite * _sprite
void setLightColor(const Color4F &color)
static EffectNormalMapped * create(const std::string &normalMapFileName)
CREATE_FUNC(EffectNormalMapped)
bool initNormalMap(const std::string &normalMapFileName)
float getKBump() const
void setLightPos(const Vec3 &pos)
void setKBump(float value)
virtual void setTarget(EffectSprite *sprite) override
CREATE_FUNC(EffectOutline)
CREATE_FUNC(EffectSepia)
void setEffect(Effect *effect)
Definition: ShaderTest2.cpp:89
void addEffect(Effect *effect, ssize_t order)
Effect * _defaultEffect
static EffectSprite * create(const std::string &filename)
Definition: ShaderTest2.cpp:79
void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override
std::vector< std::tuple< ssize_t, Effect *, QuadCommand > > _effects
cocos2d::Sprite * _lightSprite
Definition: ShaderTest2.h:91
virtual void onTouchesEnded(const std::vector< cocos2d::Touch * > &touches, cocos2d::Event *unused_event)
EffectSprite * _sprite
Definition: ShaderTest2.h:89
virtual bool init()
virtual void onTouchesBegan(const std::vector< cocos2d::Touch * > &touches, cocos2d::Event *unused_event)
Effect * _effect
Definition: ShaderTest2.h:90
virtual void onTouchesMoved(const std::vector< cocos2d::Touch * > &touches, cocos2d::Event *unused_event)
virtual bool init()
cocos2d::Vector< Effect * > _effects
Definition: ShaderTest2.h:72
EffectSprite * _sprite
Definition: ShaderTest2.h:73
ssize_t _vectorIndex
Definition: ShaderTest2.h:71