Merge pull request #19517 from PatriceJiang/3d-material-test-cases

Enable material system test cases
This commit is contained in:
minggo 2019-03-19 09:46:46 +08:00 committed by GitHub
commit cb9cf672a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 745 additions and 444 deletions

View File

@ -383,9 +383,21 @@ void Sprite::setVertexLayout()
void Sprite::updateShaders(const char* vert, const char* frag)
{
auto programState = new (std::nothrow) backend::ProgramState(vert, frag);
setProgramState(programState);
CC_SAFE_RELEASE_NULL(programState);
}
void Sprite::setProgramState(backend::ProgramState *programState)
{
CCASSERT(programState, "argument should not be nullptr");
auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor();
if (_programState != programState)
{
CC_SAFE_RELEASE(_programState);
_programState = new (std::nothrow) backend::ProgramState(vert, frag);
_programState = programState;
CC_SAFE_RETAIN(programState);
}
pipelineDescriptor.programState = _programState;
_mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix");

View File

@ -418,6 +418,16 @@ public:
*/
TextureAtlas* getTextureAtlas() const { return _textureAtlas; }
/**
* Set ProgramState
*/
void setProgramState(backend::ProgramState *programState);
/**
* Get current ProgramState
*/
inline backend::ProgramState *getProgramState() const { return _programState; }
/**
* Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode.
*/

View File

@ -322,11 +322,18 @@ void Mesh::setMaterial(Material* material)
_material = material;
CC_SAFE_RETAIN(_material);
}
_meshCommands.clear();
if (_material)
{
for (auto technique: _material->getTechniques())
{
//allocate MeshCommand vector for technique
//allocate MeshCommand for each pass
_meshCommands[technique->getName()] = std::vector<MeshCommand>(technique->getPasses().size());
auto &list = _meshCommands[technique->getName()];
int i = 0;
for (auto pass: technique->getPasses())
{
#ifdef COCOS2D_DEBUG
@ -341,8 +348,9 @@ void Mesh::setMaterial(Material* material)
}
#endif
//TODO
auto vertexAttribBinding = VertexAttribBinding::create(_meshIndexData, pass);
auto vertexAttribBinding = VertexAttribBinding::create(_meshIndexData, pass, &list[i]);
pass->setVertexAttribBinding(vertexAttribBinding);
i += 1;
}
}
}
@ -413,8 +421,8 @@ void Mesh::draw(Renderer* renderer, float globalZOrder, const Mat4& transform, u
setLightUniforms(pass, scene, color, lightMask);
}
}
_material->draw(globalZ,
auto &commands = _meshCommands[technique->getName()];
_material->draw(commands.data(), globalZ,
getVertexBuffer(),
getIndexBuffer(),
getPrimitiveType(),

View File

@ -247,7 +247,6 @@ protected:
bool _force2DQueue; // add this mesh to 2D render queue
std::string _name;
//MeshCommand _meshCommand;
MeshIndexData* _meshIndexData;
//GLProgramState* _glProgramState;
BlendFunc _blend;
@ -255,6 +254,7 @@ protected:
Material* _material;
AABB _aabb;
std::function<void()> _visibleChanged;
std::unordered_map<std::string, std::vector<MeshCommand> > _meshCommands;
///light parameters
std::vector<Vec3> _dirLightUniformColorValues;

View File

@ -58,7 +58,7 @@ VertexAttribBinding::~VertexAttribBinding()
}
}
VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, Pass* pass)
VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, Pass* pass, MeshCommand *command)
{
CCASSERT(meshIndexData && pass && pass->getProgramState(), "Invalid MeshIndexData and/or programState");
@ -71,12 +71,13 @@ VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, P
if (b->_meshIndexData == meshIndexData && b->_programState == pass->getProgramState())
{
// Found a match!
command->getPipelineDescriptor().vertexLayout = *b->_vertexLayout;
return b;
}
}
b = new (std::nothrow) VertexAttribBinding();
if (b && b->init(meshIndexData, pass))
if (b && b->init(meshIndexData, pass, command))
{
b->autorelease();
__vertexAttribBindingCache.push_back(b);
@ -85,14 +86,14 @@ VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, P
return b;
}
bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass)
bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand *command)
{
CCASSERT(meshIndexData && pass && pass->getProgramState(), "Invalid arguments");
auto programState = pass->getProgramState();
_vertexLayout = pass->getVertexLayout();
_vertexLayout = &command->getPipelineDescriptor().vertexLayout;
// One-time initialization.
//TODO arnold

View File

@ -72,7 +72,7 @@ public:
*
* @return A VertexAttribBinding for the requested parameters.
*/
static VertexAttribBinding* create(MeshIndexData* meshIndexData, Pass *pass);
static VertexAttribBinding* create(MeshIndexData* meshIndexData, Pass *pass, MeshCommand *);
/**
* Binds this vertex array object.
@ -107,7 +107,7 @@ private:
*/
VertexAttribBinding& operator=(const VertexAttribBinding&);
bool init(MeshIndexData* meshIndexData, Pass *pass);
bool init(MeshIndexData* meshIndexData, Pass *pass, MeshCommand *);
void setVertexAttribPointer(const std::string& name, backend::VertexFormat type, GLboolean normalized, int offset, int flag);
backend::AttributeBindInfo* getVertexAttribValue(const std::string &name);
void parseAttributes();

View File

@ -71,6 +71,7 @@ public:
/**Destructor.*/
~CustomCommand();
public:
/**
TODO: should remove it.

View File

@ -35,7 +35,9 @@
#include "base/CCProperties.h"
#include "base/CCDirector.h"
#include "platform/CCFileUtils.h"
#include "base/CCConsole.h"
#include <sstream>
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#define strcasecmp _stricmp
@ -43,6 +45,27 @@
NS_CC_BEGIN
namespace {
std::string replaceDefines(const std::string &compileTimeDefines) {
auto defineParts = Console::Utility::split(compileTimeDefines, ';');
std::stringstream ss;
for (auto &p : defineParts)
{
if (p.find("#define ") == std::string::npos)
{
ss << "#define " << p << std::endl;
}
else
{
ss << p << std::endl;
}
}
return ss.str();
}
}
// Helpers declaration
static const char* getOptionalString(Properties* properties, const char* key, const char* defaultValue);
static bool isValidUniform(const char* name);
@ -118,13 +141,15 @@ bool Material::initWithProperties(Properties* materialProperties)
return parseProperties(materialProperties);
}
void Material::draw(float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
void Material::draw(MeshCommand* meshCommands, float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
CustomCommand::PrimitiveType primitive, CustomCommand::IndexFormat indexFormat,
unsigned int indexCount, const Mat4& modelView)
{
int i = 0;
for (const auto& pass: _currentTechnique->_passes)
{
pass->draw(globalZOrder, vertexBuffer, indexBuffer,primitive, indexFormat, indexCount, modelView);
pass->draw(&meshCommands[i], globalZOrder, vertexBuffer, indexBuffer,primitive, indexFormat, indexCount, modelView);
i++;
}
}
@ -194,6 +219,8 @@ bool Material::parsePass(Technique* technique, Properties* passProperties)
auto pass = Pass::create(technique);
technique->addPass(pass);
pass->setName(passProperties->getId());
// Pass can have 3 different namespaces:
// - one or more "sampler"
// - one "renderState"
@ -339,7 +366,8 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties)
auto vertShaderSrc = fu->getStringFromFile(vertShader);
auto fragShaderSrc = fu->getStringFromFile(fragShader);
std::string defs = compileTimeDefines;
auto defs = replaceDefines(compileTimeDefines);
vertShaderSrc = defs + "\n" + vertShaderSrc;
fragShaderSrc = defs + "\n" + fragShaderSrc;
@ -427,11 +455,8 @@ bool Material::parseUniform(backend::ProgramState* programState, Properties* pro
case Properties::Type::STRING:
default:
{
CCASSERT(false, "auto binding is nolonger supported");
//TODO arnold
// Assume this is a parameter auto-binding.
//programState->setParameterAutoBinding(uniformName, properties->getString());
programState->setParameterAutoBinding(uniformName, properties->getString());
break;
}
}

View File

@ -96,7 +96,7 @@ public:
*/
static Material* createWithProperties(Properties* materialProperties);
void draw(float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
void draw(MeshCommand* meshCommand, float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
CustomCommand::PrimitiveType primitive, CustomCommand::IndexFormat indexFormat,
unsigned int indexCount, const Mat4& modelView);

View File

@ -62,6 +62,12 @@ void MeshCommand::init(float globalZOrder)
CustomCommand::init(globalZOrder);
}
void MeshCommand::init(float globalZOrder, const Mat4 &transform)
{
CustomCommand::init(globalZOrder);
_mv = transform;
}
MeshCommand::~MeshCommand()
{
#if CC_ENABLE_CACHE_TEXTURE_DATA

View File

@ -58,6 +58,7 @@ public:
MeshCommand();
virtual ~MeshCommand();
MeshCommand(const MeshCommand &) = default;
/**
Init function. The render command will be in 2D mode.
@ -65,6 +66,8 @@ public:
*/
void init(float globalZOrder);
void init(float globalZOrder, const Mat4 &transform);
#if CC_ENABLE_CACHE_TEXTURE_DATA
void listenRendererRecreated(EventCustom* event);
#endif

View File

@ -101,8 +101,7 @@ bool Pass::initWithProgramState(Technique* technique, backend::ProgramState *pro
Pass::Pass()
{
_meshCommand.setBeforeCallback(CC_CALLBACK_0(Pass::onBeforeVisitCmd, this));
_meshCommand.setAfterCallback(CC_CALLBACK_0(Pass::onAfterVisitCmd, this));
}
Pass::~Pass()
@ -116,7 +115,6 @@ Pass* Pass::clone() const
auto pass = new (std::nothrow) Pass();
if (pass)
{
//RenderState::cloneInto(pass);
pass->_renderState = _renderState;
pass->setProgramState(_programState->clone());
@ -143,7 +141,6 @@ void Pass::setProgramState(backend::ProgramState* programState)
CC_SAFE_RELEASE(_programState);
_programState = programState;
CC_SAFE_RETAIN(_programState);
_meshCommand.getPipelineDescriptor().programState = _programState;
initUniformLocations();
_hashDirty = true;
}
@ -181,53 +178,28 @@ void Pass::initUniformLocations()
_locAmbientLigthColor = ps->getUniformLocation(s_ambientLightUniformColorName);
}
//uint32_t Pass::getHash() const
//{
// if (_hashDirty || _state->isDirty())
// {
// //FIXME: loose information?
// uint32_t program = (uint32_t)(intptr_t)(_programState->getProgram());
// uint32_t textureid = _texture ? _texture->getName() : -1;
// uint32_t stateblockid = _state->getHash();
//
// _hash = program ^ textureid ^ stateblockid;
//
// _hashDirty = false;
// }
//
// return _hash;
//}
//void Pass::bind(const Mat4& modelView)
//{
// bind(modelView, true);
//}
//void Pass::bind(const Mat4& modelView, bool bindAttributes)
//{
// // vertex attribs
// if (bindAttributes && _vertexAttribBinding)
// _vertexAttribBinding->bind();
//
// auto glprogramstate = _glProgramState ? _glProgramState : getTarget()->getGLProgramState();
//
// glprogramstate->applyGLProgram(modelView);
// glprogramstate->applyUniforms();
//
// //set render state
// RenderState::bind(this);
//}
void Pass::draw(float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
void Pass::draw(MeshCommand *meshCommand, float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
MeshCommand::PrimitiveType primitive, MeshCommand::IndexFormat indexFormat,
unsigned int indexCount, const Mat4& modelView)
{
_meshCommand.init(globalZOrder);
_meshCommand.setPrimitiveType(primitive);
_meshCommand.setIndexBuffer(indexBuffer, indexFormat);
_meshCommand.setVertexBuffer(vertexBuffer);
_meshCommand.setIndexDrawInfo(0, indexCount);
meshCommand->setBeforeCallback(CC_CALLBACK_0(Pass::onBeforeVisitCmd, this, meshCommand));
meshCommand->setAfterCallback(CC_CALLBACK_0(Pass::onAfterVisitCmd, this, meshCommand));
meshCommand->init(globalZOrder, modelView);
meshCommand->setPrimitiveType(primitive);
meshCommand->setIndexBuffer(indexBuffer, indexFormat);
meshCommand->setVertexBuffer(vertexBuffer);
meshCommand->setIndexDrawInfo(0, indexCount);
meshCommand->getPipelineDescriptor().programState = _programState;
auto *renderer = Director::getInstance()->getRenderer();
renderer->addCommand(meshCommand);
}
void Pass::updateMVPUniform(const Mat4& modelView)
{
auto &matrixP = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto mvp = matrixP * modelView;
_programState->setUniform(_locMVPMatrix, mvp.m, sizeof(mvp.m));
@ -247,17 +219,11 @@ void Pass::draw(float globalZOrder, backend::Buffer* vertexBuffer, backend::Buff
_programState->setUniform(_locNormalMatrix, normalMatrix.data(), sizeof(normalMatrix[0]) * normalMatrix.size());
}
auto *renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_meshCommand);
}
void Pass::onBeforeVisitCmd()
void Pass::onBeforeVisitCmd(MeshCommand *command)
{
auto *renderer = Director::getInstance()->getRenderer();
//_oldDepthEnabledState = renderer->getDepthTest();
auto &pipelineDescriptor = _meshCommand.getPipelineDescriptor();
_rendererDepthTestEnabled = renderer->getDepthTest();
_rendererDepthCmpFunc = renderer->getDepthCompareFunction();
@ -265,15 +231,16 @@ void Pass::onBeforeVisitCmd()
_rendererDepthWrite = renderer->getDepthWrite();
_rendererWinding = renderer->getWinding();
_renderState.bindPass(this);
renderer->setDepthTest(true);
_renderState.bindPass(this, command);
updateMVPUniform(command->getMV());
}
void Pass::onAfterVisitCmd()
void Pass::onAfterVisitCmd(MeshCommand *command)
{
auto *renderer = Director::getInstance()->getRenderer();
_renderState.unbindPass(this);
_renderState.unbindPass(this, command);
renderer->setDepthTest(_rendererDepthTestEnabled);
renderer->setDepthCompareFunction(_rendererDepthCmpFunc);
renderer->setCullMode(_rendererCullMode);
@ -295,14 +262,6 @@ void Pass::setTechnique(Technique *technique)
_technique = technique; //weak reference
}
//void Pass::unbind()
//{
// RenderState::StateBlock::restore(0);
//
//// _vertexAttribBinding->unbind();
//}
void Pass::setVertexAttribBinding(VertexAttribBinding* binding)
{
if (_vertexAttribBinding != binding)
@ -409,6 +368,4 @@ void Pass::setUniformAmbientLigthColor(const void *data, size_t dataLen)
TRY_SET_UNIFORM(_locAmbientLigthColor);
}
NS_CC_END

View File

@ -66,23 +66,10 @@ public:
/** Returns the ProgramState */
backend::ProgramState* getProgramState() const;
backend::VertexLayout* getVertexLayout() { return &(_meshCommand.getPipelineDescriptor().vertexLayout); }
/** Binds the GLProgramState and the RenderState.
This method must be called before call the actual draw call.
*/
//void bind(const Mat4& modelView);
//void bind(const Mat4& modelView, bool bindAttributes);
void draw(float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
void draw(MeshCommand *meshCommand, float globalZOrder, backend::Buffer* vertexBuffer, backend::Buffer* indexBuffer,
MeshCommand::PrimitiveType primitive, MeshCommand::IndexFormat indexFormat,
unsigned int indexCount, const Mat4& modelView);
/** Unbinds the Pass.
This method must be called AFTER calling the actual draw call
*/
//void unbind();
/**
* Sets a vertex attribute binding for this pass.
*
@ -100,8 +87,8 @@ public:
*/
VertexAttribBinding* getVertexAttributeBinding() const;
//TODO arnold
//uint32_t getHash() const;
void setName(const std::string &name) { _name = name; }
const std::string &getName() const { return _name; }
/**
* Returns a clone (deep-copy) of this instance */
@ -109,6 +96,7 @@ public:
void setTechnique(Technique *technique);
void updateMVPUniform(const Mat4& modelView);
void setUniformTexture(uint32_t slot, backend::Texture *); //u_texture
void setUniformNormTexture(uint32_t slot, backend::Texture *); //u_texture
@ -143,21 +131,17 @@ protected:
Node* getTarget() const;
VertexAttribBinding* _vertexAttribBinding = nullptr;
MeshCommand _meshCommand;
backend::ProgramState * _programState = nullptr;
Technique * _technique = nullptr;
bool _hashDirty = true;
RenderState _renderState;
std::string _name;
private:
//bool _oldDepthEnabledState;
void initUniformLocations();
void onBeforeVisitCmd();
void onAfterVisitCmd();
backend::ProgramState* _programState = nullptr;
void onBeforeVisitCmd(MeshCommand *);
void onAfterVisitCmd(MeshCommand *);
backend::UniformLocation _locMVPMatrix;
backend::UniformLocation _locMVMatrix;

View File

@ -95,6 +95,8 @@ public:
// Can use the result to change the descriptor content.
inline PipelineDescriptor& getPipelineDescriptor() { return _pipelineDescriptor; }
const Mat4 & getMV() const { return _mv; }
protected:
/**Constructor.*/
RenderCommand();
@ -124,6 +126,8 @@ protected:
/** Depth from the model view matrix.*/
float _depth = 0.f;
Mat4 _mv;
PipelineDescriptor _pipelineDescriptor;
};

View File

@ -46,13 +46,13 @@ std::string RenderState::getName() const
}
void RenderState::bindPass(Pass* pass)
void RenderState::bindPass(Pass* pass, MeshCommand* command)
{
CC_ASSERT(pass);
assert(pass->_technique && pass->_technique->_material);
auto *technique = pass->_technique;
auto *material = technique->_material;
auto &pipelineDescriptor = pass->_meshCommand.getPipelineDescriptor();
auto &pipelineDescriptor = command->getPipelineDescriptor();
//need reset all state
//pipelineDescriptor.blendDescriptor.blendEnabled = true;
@ -71,9 +71,9 @@ void RenderState::bindPass(Pass* pass)
}
void RenderState::unbindPass(Pass* pass)
void RenderState::unbindPass(Pass* pass, MeshCommand* command)
{
auto &pipelineDescriptor = pass->_meshCommand.getPipelineDescriptor();
auto &pipelineDescriptor = command->getPipelineDescriptor();
RenderState::StateBlock::restore(0, &pipelineDescriptor);
}

View File

@ -37,11 +37,13 @@
#include "renderer/CCPipelineDescriptor.h"
#include "renderer/backend/Types.h"
#include "renderer/CCMeshCommand.h"
NS_CC_BEGIN
class Texture2D;
class Pass;
class MeshCommand;
using CullFaceSide = backend::CullMode;
using FrontFace = backend::Winding;
@ -64,10 +66,10 @@ public:
* Binds the render state for this RenderState and any of its parents, top-down,
* for the given pass.
*/
void bindPass(Pass* pass);
void bindPass(Pass* pass, MeshCommand *);
void unbindPass(Pass* pass);
void unbindPass(Pass* pass, MeshCommand *);
/**
* Defines a block of fixed-function render states that can be applied to a

View File

@ -69,6 +69,7 @@ set(COCOS_RENDERER_SRC
renderer/backend/ShaderModule.cpp
renderer/backend/StringUtils.cpp
renderer/backend/Texture.cpp
renderer/backend/Types.cpp
renderer/backend/VertexLayout.cpp
renderer/backend/ProgramCache.cpp
renderer/backend/Program.cpp

View File

@ -3,6 +3,9 @@
#include "renderer/backend/Program.h"
#include "renderer/backend/Texture.h"
#include "renderer/backend/Types.h"
#include <algorithm>
#ifdef CC_USE_METAL
#include "glsl_optimizer.h"
#endif
@ -52,6 +55,8 @@ namespace {
}
}
//static field
std::vector<ProgramState::AutoBindingResolver*> ProgramState::_customAutoBindingResolvers;
UniformBuffer::UniformBuffer(const backend::UniformInfo &_uniformInfo)
: uniformInfo(_uniformInfo)
@ -228,6 +233,11 @@ backend::UniformLocation ProgramState::getUniformLocation(const std::string& uni
return _program->getUniformLocation(uniform);
}
void ProgramState::setCallbackUniform(const backend::UniformLocation& uniformLocation,const UniformCallback& callback)
{
_callbackUniforms[uniformLocation] = callback;
}
void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, const void* data, uint32_t size)
{
switch (uniformLocation.shaderStage)
@ -407,5 +417,32 @@ void ProgramState::setTextureArray(int location, const std::vector<uint32_t>& sl
textureInfo[location] = std::move(info);
}
void ProgramState::setParameterAutoBinding(const std::string &uniform, const std::string &autoBinding)
{
_autoBindings.emplace(uniform, autoBinding);
applyAutoBinding(uniform, autoBinding);
}
void ProgramState::applyAutoBinding(const std::string &uniformName, const std::string &autoBinding)
{
bool resolved = false;
for (const auto resolver : _customAutoBindingResolvers)
{
resolved = resolver->resolveAutoBinding(this, uniformName, autoBinding);
if (resolved) break;
}
}
ProgramState::AutoBindingResolver::AutoBindingResolver()
{
_customAutoBindingResolvers.emplace_back(this);
}
ProgramState::AutoBindingResolver::~AutoBindingResolver()
{
auto &list = _customAutoBindingResolvers;
list.erase(std::remove(list.begin(), list.end(), this), list.end());
}
CC_BACKEND_END

View File

@ -4,6 +4,7 @@
#include <string>
#include <unordered_map>
#include <cstdint>
#include <functional>
#include "platform/CCPlatformMacros.h"
#include "base/CCRef.h"
#include "renderer/backend/Types.h"
@ -48,6 +49,9 @@ struct TextureInfo
class ProgramState : public Ref
{
public:
using UniformCallback = std::function<void(ProgramState*, const UniformLocation &)>;
ProgramState(const std::string& vertexShader, const std::string& fragmentShader);
virtual ~ProgramState();
@ -66,12 +70,77 @@ public:
inline std::vector<UniformBuffer>& getVertexUniformInfos() { return _vertexUniformInfos; }
inline const std::vector<UniformBuffer>& getFragmentUniformInfos() const { return _fragmentUniformInfos; }
void setCallbackUniform(const backend::UniformLocation&, const UniformCallback &);
//set textures
void setTexture(const backend::UniformLocation& uniformLocation, uint32_t slot, backend::Texture* texture);
void setTextureArray(const backend::UniformLocation& uniformLocation, const std::vector<uint32_t>& slots, const std::vector<backend::Texture*> textures);
inline const std::unordered_map<int, TextureInfo>& getVertexTextureInfos() const { return _vertexTextureInfos; }
inline const std::unordered_map<int, TextureInfo>& getFragmentTextureInfos() const { return _fragmentTextureInfos; }
inline const std::unordered_map<UniformLocation, UniformCallback, UniformLocation>& getCallbackUniforms() const { return _callbackUniforms; }
/**
* An abstract base class that can be extended to support custom material auto bindings.
*
* Implementing a custom auto binding resolver allows the set of built-in parameter auto
* bindings to be extended or overridden. Any parameter auto binding that is set on a
* material will be forwarded to any custom auto binding resolvers, in the order in which
* they are registered. If a registered resolver returns true (specifying that it handles
* the specified autoBinding), no further code will be executed for that autoBinding.
* This allows auto binding resolvers to not only implement new/custom binding strings,
* but it also lets them override existing/built-in ones. For this reason, you should
* ensure that you ONLY return true if you explicitly handle a custom auto binding; return
* false otherwise.
*
* Note that the custom resolver is called only once for a GLProgramState object when its
* node binding is initially set. This occurs when a material is initially bound to a
* Node. The resolver is NOT called each frame or each time the GLProgramState is bound.
*
* If no registered resolvers explicitly handle an auto binding, the binding will attempt
* to be resolved using the internal/built-in resolver, which is able to handle any
* auto bindings found in the GLProgramState::AutoBinding enumeration.
*
* When an instance of a class that extends AutoBindingResolver is created, it is automatically
* registered as a custom auto binding handler. Likewise, it is automatically unregistered
* on destruction.
*
* @script{ignore}
*/
class CC_DLL AutoBindingResolver {
public:
AutoBindingResolver();
virtual ~AutoBindingResolver();
/**
* Called when an unrecognized uniform variable is encountered
* during material loading.
*
* Implementations of this method should do a string comparison on the passed
* in name parameter and decide whether or not they should handle the
* parameter. If the parameter is not handled, false should be returned so
* that other auto binding resolvers get a chance to handle the parameter.
* Otherwise, the parameter should be set or bound and true should be returned.
*
* @param programState The ProgramState
* @param uniformName Name of the uniform
* @param autoBinding Name of the auto binding to be resolved.
*
* @return True if the auto binding is handled and the associated parameter is
* bound, false otherwise.
*/
virtual bool resolveAutoBinding(ProgramState *, const std::string &uniformName, const std::string &autoBinding) = 0;
};
/**
* Sets a uniform auto-binding.
*
* This method parses the passed in autoBinding string and attempts to convert it
* to an enumeration value. If it matches to one of the predefined strings, it will create a
* callback to get the correct value at runtime.
*
* @param uniformName The name of the material parameter to store an auto-binding for.
* @param autoBinding A string matching one of the built-in AutoBinding enum constants.
*/
void setParameterAutoBinding(const std::string &uniformName, const std::string &autoBinding);
protected:
@ -88,13 +157,25 @@ protected:
//float3 etc in Metal has both sizeof and alignment same as float4, convert it before fill into uniform buffer
void convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector<char>& uniformData);
#endif
/**
* Applies the specified custom auto-binding.
*
* @param uniformName Name of the shader uniform.
* @param autoBinding Name of the auto binding.
*/
void applyAutoBinding(const std::string &, const std::string &);
backend::Program* _program = nullptr;
std::vector<UniformBuffer> _vertexUniformInfos;
std::vector<UniformBuffer> _fragmentUniformInfos;
std::unordered_map<UniformLocation, UniformCallback, UniformLocation> _callbackUniforms;
std::unordered_map<int, TextureInfo> _vertexTextureInfos;
std::unordered_map<int, TextureInfo> _fragmentTextureInfos;
std::unordered_map<std::string, std::string> _autoBindings;
static std::vector<AutoBindingResolver*> _customAutoBindingResolvers;
};
CC_BACKEND_END

View File

@ -0,0 +1,16 @@
#include "Types.h"
CC_BACKEND_BEGIN
bool UniformLocation::operator==(const UniformLocation &other) const
{
return shaderStage == other.shaderStage && location == other.location;
}
std::size_t UniformLocation::operator()(const UniformLocation &uniform) const {
return (((size_t) shaderStage) & 0xF)|((size_t)(location << 4));
}
CC_BACKEND_END

View File

@ -247,10 +247,15 @@ struct UniformLocation
{
int location = -1;
ShaderStage shaderStage = ShaderStage::VERTEX;
UniformLocation() = default;
operator bool() { return location >= 0; }
void reset() { location = -1; }
bool operator == (const UniformLocation &other) const;
std::size_t operator()(const UniformLocation &uniform) const;
};
struct AttributeBindInfo
{
std::string attributeName;

View File

@ -385,6 +385,13 @@ void CommandBufferMTL::setUniformBuffer() const
{
if (_programState)
{
auto &callbackUniforms = _programState->getCallbackUniforms();
for(auto &cb : callbackUniforms)
{
cb.second(_programState, cb.first);
}
// Uniform buffer is bound to index 1.
const auto& vertexUniformBuffer = _renderPipelineMTL->getVertexUniformBuffer();
const auto& vertexUniformInfo = _programState->getVertexUniformInfos();

View File

@ -331,10 +331,11 @@ void CommandBufferGL::bindVertexBuffer(ProgramGL *program) const
{
if (! vertexBuffer)
continue;
if (i >= attributeInfos.size())
break;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->getHandler());
const auto& attributeInfo = attributeInfos[i];
const auto &layouts = vertexLayouts->at(i);
for (const auto& attribute : attributeInfo)
@ -357,7 +358,14 @@ void CommandBufferGL::setUniforms(ProgramGL* program) const
{
if (_programState)
{
auto& callbacks = _programState->getCallbackUniforms();
auto& uniformInfos = _programState->getVertexUniformInfos();
for (auto &cb : callbacks)
{
cb.second(_programState, cb.first);
}
int i = 0;
for(auto& iter : uniformInfos)
{

View File

@ -73663,6 +73663,56 @@ int lua_cocos2dx_Sprite_setFlippedX(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Sprite_setProgramState(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Sprite* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Sprite",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Sprite*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Sprite_setProgramState'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 1)
{
cocos2d::backend::ProgramState* arg0;
ok &= luaval_to_object<cocos2d::backend::ProgramState>(tolua_S, 2, "cc.ProgramState",&arg0, "cc.Sprite:setProgramState");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Sprite_setProgramState'", nullptr);
return 0;
}
cobj->setProgramState(arg0);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Sprite:setProgramState",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Sprite_setProgramState'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Sprite_getResourceType(lua_State* tolua_S)
{
int argc = 0;
@ -74696,6 +74746,53 @@ int lua_cocos2dx_Sprite_isDirty(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Sprite_getProgramState(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Sprite* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Sprite",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Sprite*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Sprite_getProgramState'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
{
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Sprite_getProgramState'", nullptr);
return 0;
}
cocos2d::backend::ProgramState* ret = cobj->getProgramState();
object_to_luaval<cocos2d::backend::ProgramState>(tolua_S, "cc.ProgramState",(cocos2d::backend::ProgramState*)ret);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Sprite:getProgramState",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Sprite_getProgramState'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Sprite_getCenterRectNormalized(lua_State* tolua_S)
{
int argc = 0;
@ -75616,6 +75713,7 @@ int lua_register_cocos2dx_Sprite(lua_State* tolua_S)
tolua_function(tolua_S,"getTexture",lua_cocos2dx_Sprite_getTexture);
tolua_function(tolua_S,"setFlippedY",lua_cocos2dx_Sprite_setFlippedY);
tolua_function(tolua_S,"setFlippedX",lua_cocos2dx_Sprite_setFlippedX);
tolua_function(tolua_S,"setProgramState",lua_cocos2dx_Sprite_setProgramState);
tolua_function(tolua_S,"getResourceType",lua_cocos2dx_Sprite_getResourceType);
tolua_function(tolua_S,"setDisplayFrameWithAnimationName",lua_cocos2dx_Sprite_setDisplayFrameWithAnimationName);
tolua_function(tolua_S,"getBatchNode",lua_cocos2dx_Sprite_getBatchNode);
@ -75637,6 +75735,7 @@ int lua_register_cocos2dx_Sprite(lua_State* tolua_S)
tolua_function(tolua_S,"removeAllChildrenWithCleanup",lua_cocos2dx_Sprite_removeAllChildrenWithCleanup);
tolua_function(tolua_S,"getResourceName",lua_cocos2dx_Sprite_getResourceName);
tolua_function(tolua_S,"isDirty",lua_cocos2dx_Sprite_isDirty);
tolua_function(tolua_S,"getProgramState",lua_cocos2dx_Sprite_getProgramState);
tolua_function(tolua_S,"getCenterRectNormalized",lua_cocos2dx_Sprite_getCenterRectNormalized);
tolua_function(tolua_S,"setAtlasIndex",lua_cocos2dx_Sprite_setAtlasIndex);
tolua_function(tolua_S,"initWithTexture",lua_cocos2dx_Sprite_initWithTexture);
@ -87665,21 +87764,24 @@ int lua_cocos2dx_RenderState_unbindPass(lua_State* tolua_S)
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 1)
if (argc == 2)
{
cocos2d::Pass* arg0;
cocos2d::MeshCommand* arg1;
ok &= luaval_to_object<cocos2d::Pass>(tolua_S, 2, "cc.Pass",&arg0, "cc.RenderState:unbindPass");
ok &= luaval_to_object<cocos2d::MeshCommand>(tolua_S, 3, "cc.MeshCommand",&arg1, "cc.RenderState:unbindPass");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_RenderState_unbindPass'", nullptr);
return 0;
}
cobj->unbindPass(arg0);
cobj->unbindPass(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.RenderState:unbindPass",argc, 1);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.RenderState:unbindPass",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
@ -87715,21 +87817,24 @@ int lua_cocos2dx_RenderState_bindPass(lua_State* tolua_S)
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 1)
if (argc == 2)
{
cocos2d::Pass* arg0;
cocos2d::MeshCommand* arg1;
ok &= luaval_to_object<cocos2d::Pass>(tolua_S, 2, "cc.Pass",&arg0, "cc.RenderState:bindPass");
ok &= luaval_to_object<cocos2d::MeshCommand>(tolua_S, 3, "cc.MeshCommand",&arg1, "cc.RenderState:bindPass");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_RenderState_bindPass'", nullptr);
return 0;
}
cobj->bindPass(arg0);
cobj->bindPass(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.RenderState:bindPass",argc, 1);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.RenderState:bindPass",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
@ -88274,39 +88379,42 @@ int lua_cocos2dx_Material_draw(lua_State* tolua_S)
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 7)
if (argc == 8)
{
double arg0;
cocos2d::backend::Buffer* arg1;
cocos2d::MeshCommand* arg0;
double arg1;
cocos2d::backend::Buffer* arg2;
cocos2d::backend::PrimitiveType arg3;
cocos2d::backend::IndexFormat arg4;
unsigned int arg5;
cocos2d::Mat4 arg6;
cocos2d::backend::Buffer* arg3;
cocos2d::backend::PrimitiveType arg4;
cocos2d::backend::IndexFormat arg5;
unsigned int arg6;
cocos2d::Mat4 arg7;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.Material:draw");
ok &= luaval_to_object<cocos2d::MeshCommand>(tolua_S, 2, "cc.MeshCommand",&arg0, "cc.Material:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 3, "cc.Buffer",&arg1, "cc.Material:draw");
ok &= luaval_to_number(tolua_S, 3,&arg1, "cc.Material:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 4, "cc.Buffer",&arg2, "cc.Material:draw");
ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "cc.Material:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 5, "cc.Buffer",&arg3, "cc.Material:draw");
ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "cc.Material:draw");
ok &= luaval_to_uint32(tolua_S, 7,&arg5, "cc.Material:draw");
ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "cc.Material:draw");
ok &= luaval_to_mat4(tolua_S, 8, &arg6, "cc.Material:draw");
ok &= luaval_to_uint32(tolua_S, 8,&arg6, "cc.Material:draw");
ok &= luaval_to_mat4(tolua_S, 9, &arg7, "cc.Material:draw");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Material_draw'", nullptr);
return 0;
}
cobj->draw(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
cobj->draw(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Material:draw",argc, 7);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Material:draw",argc, 8);
return 0;
#if COCOS2D_DEBUG >= 1
@ -89148,7 +89256,7 @@ int lua_cocos2dx_Pass_getVertexAttributeBinding(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_setUniformPointLightRangeInverse(lua_State* tolua_S)
int lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
@ -89168,7 +89276,7 @@ int lua_cocos2dx_Pass_setUniformPointLightRangeInverse(lua_State* tolua_S)
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'", nullptr);
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'", nullptr);
return 0;
}
#endif
@ -89182,22 +89290,22 @@ int lua_cocos2dx_Pass_setUniformPointLightRangeInverse(lua_State* tolua_S)
#pragma warning NO CONVERSION TO NATIVE FOR void*
ok = false;
ok &= luaval_to_uint32(tolua_S, 3,&arg1, "cc.Pass:setUniformPointLightRangeInverse");
ok &= luaval_to_uint32(tolua_S, 3,&arg1, "cc.Pass:setUniformSpotLightOuterAngleCos");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'", nullptr);
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'", nullptr);
return 0;
}
cobj->setUniformPointLightRangeInverse(arg0, arg1);
cobj->setUniformSpotLightOuterAngleCos(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:setUniformPointLightRangeInverse",argc, 2);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:setUniformSpotLightOuterAngleCos",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'.",&tolua_err);
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'.",&tolua_err);
#endif
return 0;
@ -89310,6 +89418,103 @@ int lua_cocos2dx_Pass_setUniformMatrixPalette(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_setName(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Pass",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Pass*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_setName'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 1)
{
std::string arg0;
ok &= luaval_to_std_string(tolua_S, 2,&arg0, "cc.Pass:setName");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_setName'", nullptr);
return 0;
}
cobj->setName(arg0);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:setName",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_setName'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Pass_getName(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Pass",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Pass*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_getName'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
{
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_getName'", nullptr);
return 0;
}
const std::string& ret = cobj->getName();
lua_pushlstring(tolua_S,ret.c_str(),ret.length());
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:getName",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_getName'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Pass_setUniformSpotLightRangeInverse(lua_State* tolua_S)
{
int argc = 0;
@ -89364,6 +89569,53 @@ int lua_cocos2dx_Pass_setUniformSpotLightRangeInverse(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_clone(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Pass",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Pass*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_clone'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
{
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_clone'", nullptr);
return 0;
}
cocos2d::Pass* ret = cobj->clone();
object_to_luaval<cocos2d::Pass>(tolua_S, "cc.Pass",(cocos2d::Pass*)ret);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:clone",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_clone'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Pass_draw(lua_State* tolua_S)
{
int argc = 0;
@ -89390,39 +89642,42 @@ int lua_cocos2dx_Pass_draw(lua_State* tolua_S)
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 7)
if (argc == 8)
{
double arg0;
cocos2d::backend::Buffer* arg1;
cocos2d::MeshCommand* arg0;
double arg1;
cocos2d::backend::Buffer* arg2;
cocos2d::backend::PrimitiveType arg3;
cocos2d::backend::IndexFormat arg4;
unsigned int arg5;
cocos2d::Mat4 arg6;
cocos2d::backend::Buffer* arg3;
cocos2d::backend::PrimitiveType arg4;
cocos2d::backend::IndexFormat arg5;
unsigned int arg6;
cocos2d::Mat4 arg7;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.Pass:draw");
ok &= luaval_to_object<cocos2d::MeshCommand>(tolua_S, 2, "cc.MeshCommand",&arg0, "cc.Pass:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 3, "cc.Buffer",&arg1, "cc.Pass:draw");
ok &= luaval_to_number(tolua_S, 3,&arg1, "cc.Pass:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 4, "cc.Buffer",&arg2, "cc.Pass:draw");
ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "cc.Pass:draw");
ok &= luaval_to_object<cocos2d::backend::Buffer>(tolua_S, 5, "cc.Buffer",&arg3, "cc.Pass:draw");
ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "cc.Pass:draw");
ok &= luaval_to_uint32(tolua_S, 7,&arg5, "cc.Pass:draw");
ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "cc.Pass:draw");
ok &= luaval_to_mat4(tolua_S, 8, &arg6, "cc.Pass:draw");
ok &= luaval_to_uint32(tolua_S, 8,&arg6, "cc.Pass:draw");
ok &= luaval_to_mat4(tolua_S, 9, &arg7, "cc.Pass:draw");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_draw'", nullptr);
return 0;
}
cobj->draw(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
cobj->draw(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:draw",argc, 7);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:draw",argc, 8);
return 0;
#if COCOS2D_DEBUG >= 1
@ -89432,7 +89687,7 @@ int lua_cocos2dx_Pass_draw(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_getVertexLayout(lua_State* tolua_S)
int lua_cocos2dx_Pass_setUniformPointLightRangeInverse(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
@ -89452,29 +89707,36 @@ int lua_cocos2dx_Pass_getVertexLayout(lua_State* tolua_S)
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_getVertexLayout'", nullptr);
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
if (argc == 2)
{
const void* arg0;
unsigned int arg1;
#pragma warning NO CONVERSION TO NATIVE FOR void*
ok = false;
ok &= luaval_to_uint32(tolua_S, 3,&arg1, "cc.Pass:setUniformPointLightRangeInverse");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_getVertexLayout'", nullptr);
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'", nullptr);
return 0;
}
cocos2d::backend::VertexLayout* ret = cobj->getVertexLayout();
object_to_luaval<cocos2d::backend::VertexLayout>(tolua_S, "cc.VertexLayout",(cocos2d::backend::VertexLayout*)ret);
cobj->setUniformPointLightRangeInverse(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:getVertexLayout",argc, 0);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:setUniformPointLightRangeInverse",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_getVertexLayout'.",&tolua_err);
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_setUniformPointLightRangeInverse'.",&tolua_err);
#endif
return 0;
@ -89532,7 +89794,7 @@ int lua_cocos2dx_Pass_setUniformNormTexture(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_clone(lua_State* tolua_S)
int lua_cocos2dx_Pass_updateMVPUniform(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
@ -89552,29 +89814,32 @@ int lua_cocos2dx_Pass_clone(lua_State* tolua_S)
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_clone'", nullptr);
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_updateMVPUniform'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
if (argc == 1)
{
cocos2d::Mat4 arg0;
ok &= luaval_to_mat4(tolua_S, 2, &arg0, "cc.Pass:updateMVPUniform");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_clone'", nullptr);
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_updateMVPUniform'", nullptr);
return 0;
}
cocos2d::Pass* ret = cobj->clone();
object_to_luaval<cocos2d::Pass>(tolua_S, "cc.Pass",(cocos2d::Pass*)ret);
cobj->updateMVPUniform(arg0);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:clone",argc, 0);
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:updateMVPUniform",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_clone'.",&tolua_err);
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_updateMVPUniform'.",&tolua_err);
#endif
return 0;
@ -89999,60 +90264,6 @@ int lua_cocos2dx_Pass_setUniformTexture(lua_State* tolua_S)
return 0;
}
int lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Pass* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Pass",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Pass*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 2)
{
const void* arg0;
unsigned int arg1;
#pragma warning NO CONVERSION TO NATIVE FOR void*
ok = false;
ok &= luaval_to_uint32(tolua_S, 3,&arg1, "cc.Pass:setUniformSpotLightOuterAngleCos");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'", nullptr);
return 0;
}
cobj->setUniformSpotLightOuterAngleCos(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Pass:setUniformSpotLightOuterAngleCos",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos'.",&tolua_err);
#endif
return 0;
}
int lua_cocos2dx_Pass_setUniformColor(lua_State* tolua_S)
{
int argc = 0;
@ -90251,14 +90462,17 @@ int lua_register_cocos2dx_Pass(lua_State* tolua_S)
tolua_function(tolua_S,"setUniformSpotLightInnerAngleCos",lua_cocos2dx_Pass_setUniformSpotLightInnerAngleCos);
tolua_function(tolua_S,"setTechnique",lua_cocos2dx_Pass_setTechnique);
tolua_function(tolua_S,"getVertexAttributeBinding",lua_cocos2dx_Pass_getVertexAttributeBinding);
tolua_function(tolua_S,"setUniformPointLightRangeInverse",lua_cocos2dx_Pass_setUniformPointLightRangeInverse);
tolua_function(tolua_S,"setUniformSpotLightOuterAngleCos",lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos);
tolua_function(tolua_S,"setUniformSpotLightDir",lua_cocos2dx_Pass_setUniformSpotLightDir);
tolua_function(tolua_S,"setUniformMatrixPalette",lua_cocos2dx_Pass_setUniformMatrixPalette);
tolua_function(tolua_S,"setName",lua_cocos2dx_Pass_setName);
tolua_function(tolua_S,"getName",lua_cocos2dx_Pass_getName);
tolua_function(tolua_S,"setUniformSpotLightRangeInverse",lua_cocos2dx_Pass_setUniformSpotLightRangeInverse);
tolua_function(tolua_S,"draw",lua_cocos2dx_Pass_draw);
tolua_function(tolua_S,"getVertexLayout",lua_cocos2dx_Pass_getVertexLayout);
tolua_function(tolua_S,"setUniformNormTexture",lua_cocos2dx_Pass_setUniformNormTexture);
tolua_function(tolua_S,"clone",lua_cocos2dx_Pass_clone);
tolua_function(tolua_S,"draw",lua_cocos2dx_Pass_draw);
tolua_function(tolua_S,"setUniformPointLightRangeInverse",lua_cocos2dx_Pass_setUniformPointLightRangeInverse);
tolua_function(tolua_S,"setUniformNormTexture",lua_cocos2dx_Pass_setUniformNormTexture);
tolua_function(tolua_S,"updateMVPUniform",lua_cocos2dx_Pass_updateMVPUniform);
tolua_function(tolua_S,"setUniformDirLightDir",lua_cocos2dx_Pass_setUniformDirLightDir);
tolua_function(tolua_S,"getProgramState",lua_cocos2dx_Pass_getProgramState);
tolua_function(tolua_S,"setUniformSpotLightColor",lua_cocos2dx_Pass_setUniformSpotLightColor);
@ -90267,7 +90481,6 @@ int lua_register_cocos2dx_Pass(lua_State* tolua_S)
tolua_function(tolua_S,"setUniformSpotLightPosition",lua_cocos2dx_Pass_setUniformSpotLightPosition);
tolua_function(tolua_S,"setVertexAttribBinding",lua_cocos2dx_Pass_setVertexAttribBinding);
tolua_function(tolua_S,"setUniformTexture",lua_cocos2dx_Pass_setUniformTexture);
tolua_function(tolua_S,"setUniformSpotLightOuterAngleCos",lua_cocos2dx_Pass_setUniformSpotLightOuterAngleCos);
tolua_function(tolua_S,"setUniformColor",lua_cocos2dx_Pass_setUniformColor);
tolua_function(tolua_S,"setUniformPointLightColor",lua_cocos2dx_Pass_setUniformPointLightColor);
tolua_function(tolua_S,"createWithProgramState", lua_cocos2dx_Pass_createWithProgramState);

View File

@ -2223,6 +2223,10 @@ int register_all_cocos2dx(lua_State* tolua_S);

View File

@ -263,7 +263,7 @@ list(APPEND GAME_SOURCE
# Classes/LabelTest/LabelTestNew.cpp
Classes/LayerTest/LayerTest.cpp
# Classes/LightTest/LightTest.cpp
# Classes/MaterialSystemTest/MaterialSystemTest.cpp
Classes/MaterialSystemTest/MaterialSystemTest.cpp
Classes/MenuTest/MenuTest.cpp
Classes/MotionStreakTest/MotionStreakTest.cpp
Classes/MultiTouchTest/MultiTouchTest.cpp

View File

@ -49,8 +49,6 @@ MaterialSystemTest::MaterialSystemTest()
ADD_TEST_CASE(Material_MultipleSprite3D);
ADD_TEST_CASE(Material_Sprite3DTest);
ADD_TEST_CASE(Material_parsePerformance);
ADD_TEST_CASE(Material_invalidate);
ADD_TEST_CASE(Material_renderState);
}
std::string MaterialSystemBaseTest::title() const
@ -126,22 +124,37 @@ void Material_2DEffects::onEnter()
auto spriteBlur = Sprite::create("Images/grossini.png");
spriteBlur->setPositionNormalized(Vec2(0.2f, 0.5f));
this->addChild(spriteBlur);
spriteBlur->setGLProgramState(mat1->getTechniqueByName("blur")->getPassByIndex(0)->getGLProgramState());
spriteBlur->setProgramState(mat1->getTechniqueByName("blur")->getPassByIndex(0)->getProgramState());
auto spriteOutline = Sprite::create("Images/grossini.png");
spriteOutline->setPositionNormalized(Vec2(0.4f, 0.5f));
this->addChild(spriteOutline);
spriteOutline->setGLProgramState(mat1->getTechniqueByName("outline")->getPassByIndex(0)->getGLProgramState());
spriteOutline->setProgramState(mat1->getTechniqueByName("outline")->getPassByIndex(0)->getProgramState());
auto spriteNoise = Sprite::create("Images/grossini.png");
spriteNoise->setPositionNormalized(Vec2(0.6f, 0.5f));
this->addChild(spriteNoise);
spriteNoise->setGLProgramState(mat1->getTechniqueByName("noise")->getPassByIndex(0)->getGLProgramState());
spriteNoise->setProgramState(mat1->getTechniqueByName("noise")->getPassByIndex(0)->getProgramState());
auto spriteEdgeDetect = Sprite::create("Images/grossini.png");
spriteEdgeDetect->setPositionNormalized(Vec2(0.8f, 0.5f));
this->addChild(spriteEdgeDetect);
spriteEdgeDetect->setGLProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getGLProgramState());
spriteEdgeDetect->setProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getProgramState());
timeUniforms.clear();
#define FETCH_CCTIME_LOCATION(sprite) do { \
auto programState = sprite->getProgramState(); \
auto location = programState->getUniformLocation("CC_Time"); \
timeUniforms.emplace_back(programState, location); \
}while(0)
FETCH_CCTIME_LOCATION(spriteBlur);
FETCH_CCTIME_LOCATION(spriteOutline);
FETCH_CCTIME_LOCATION(spriteNoise);
FETCH_CCTIME_LOCATION(spriteEdgeDetect);
schedule(CC_SCHEDULE_SELECTOR(Material_2DEffects::updateCCTimeUniforms));
// properties is not a "Ref" object
CC_SAFE_DELETE(properties);
@ -152,6 +165,16 @@ std::string Material_2DEffects::subtitle() const
return "Testing effects on Sprite";
}
void Material_2DEffects::updateCCTimeUniforms(float)
{
float time = Director::getInstance()->getTotalFrames() * Director::getInstance()->getAnimationInterval();
Vec4 random(time / 10.0f, time, time * 2.0f, time * 4.0f);
for (auto &loc : timeUniforms)
{
loc.programState->setUniform(loc.location, &random, sizeof(random));
}
}
//
// MARK: Material_AutoBindings
//
@ -159,42 +182,45 @@ std::string Material_2DEffects::subtitle() const
/*
* Custom material auto-binding resolver for terrain.
*/
class EffectAutoBindingResolver : public GLProgramState::AutoBindingResolver
class EffectAutoBindingResolver : public backend::ProgramState::AutoBindingResolver
{
bool resolveAutoBinding(GLProgramState* glProgramState, Node* node, const std::string& uniform, const std::string& autoBinding);
virtual bool resolveAutoBinding(backend::ProgramState* programState,/* Node* node,*/ const std::string& uniform, const std::string& autoBinding) override;
void callbackRadius(GLProgram* glProgram, Uniform* uniform);
void callbackColor(GLProgram* glProgram, Uniform* uniform);
void callbackRadius(backend::ProgramState* programState, backend::UniformLocation uniform);
void callbackColor(backend::ProgramState* programState, backend::UniformLocation uniform);
};
bool EffectAutoBindingResolver::resolveAutoBinding(GLProgramState* glProgramState, Node* node, const std::string& uniform, const std::string& autoBinding)
bool EffectAutoBindingResolver::resolveAutoBinding(backend::ProgramState* programState, /*Node* node,*/ const std::string& uniform, const std::string& autoBinding)
{
if (autoBinding.compare("DYNAMIC_RADIUS")==0)
{
glProgramState->setUniformCallback(uniform, CC_CALLBACK_2(EffectAutoBindingResolver::callbackRadius, this));
auto loc = programState->getUniformLocation(uniform);
programState->setCallbackUniform(loc, CC_CALLBACK_2(EffectAutoBindingResolver::callbackRadius, this));
return true;
}
else if (autoBinding.compare("OUTLINE_COLOR")==0)
{
glProgramState->setUniformCallback(uniform, CC_CALLBACK_2(EffectAutoBindingResolver::callbackColor, this));
auto loc = programState->getUniformLocation(uniform);
programState->setCallbackUniform(loc, CC_CALLBACK_2(EffectAutoBindingResolver::callbackColor, this));
return true;
}
return false;
}
void EffectAutoBindingResolver::callbackRadius(GLProgram* glProgram, Uniform* uniform)
void EffectAutoBindingResolver::callbackRadius(backend::ProgramState *programState, backend::UniformLocation uniform)
{
float f = CCRANDOM_0_1() * 10;
glProgram->setUniformLocationWith1f(uniform->location, f);
programState->setUniform(uniform, &f, sizeof(f));
}
void EffectAutoBindingResolver::callbackColor(GLProgram* glProgram, Uniform* uniform)
void EffectAutoBindingResolver::callbackColor(backend::ProgramState *programState, backend::UniformLocation uniform)
{
float r = CCRANDOM_0_1();
float g = CCRANDOM_0_1();
float b = CCRANDOM_0_1();
Vec3 color(r, g, b);
glProgram->setUniformLocationWith3f(uniform->location, r, g, b);
programState->setUniform(uniform, &color, sizeof(color));
}
Material_AutoBindings::Material_AutoBindings()
@ -223,23 +249,27 @@ void Material_AutoBindings::onEnter()
auto spriteBlur = Sprite::create("Images/grossini.png");
spriteBlur->setPositionNormalized(Vec2(0.2f, 0.5f));
this->addChild(spriteBlur);
spriteBlur->setGLProgramState(mat1->getTechniqueByName("blur")->getPassByIndex(0)->getGLProgramState());
spriteBlur->setProgramState(mat1->getTechniqueByName("blur")->getPassByIndex(0)->getProgramState());
auto spriteOutline = Sprite::create("Images/grossini.png");
spriteOutline->setPositionNormalized(Vec2(0.4f, 0.5f));
this->addChild(spriteOutline);
spriteOutline->setGLProgramState(mat1->getTechniqueByName("outline")->getPassByIndex(0)->getGLProgramState());
spriteOutline->setProgramState(mat1->getTechniqueByName("outline")->getPassByIndex(0)->getProgramState());
auto spriteNoise = Sprite::create("Images/grossini.png");
spriteNoise->setPositionNormalized(Vec2(0.6f, 0.5f));
this->addChild(spriteNoise);
spriteNoise->setGLProgramState(mat1->getTechniqueByName("noise")->getPassByIndex(0)->getGLProgramState());
spriteNoise->setProgramState(mat1->getTechniqueByName("noise")->getPassByIndex(0)->getProgramState());
auto spriteEdgeDetect = Sprite::create("Images/grossini.png");
spriteEdgeDetect->setPositionNormalized(Vec2(0.8f, 0.5f));
this->addChild(spriteEdgeDetect);
spriteEdgeDetect->setGLProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getGLProgramState());
spriteEdgeDetect->setProgramState(mat1->getTechniqueByName("edge_detect")->getPassByIndex(0)->getProgramState());
_noiseProgramState = spriteNoise->getProgramState();
_locationTime = _noiseProgramState->getUniformLocation("CC_Time");
schedule(CC_SCHEDULE_SELECTOR(Material_AutoBindings::updateUniformTime));
// properties is not a "Ref" object
CC_SAFE_DELETE(properties);
}
@ -249,6 +279,13 @@ std::string Material_AutoBindings::subtitle() const
return "Testing auto-bindings uniforms";
}
void Material_AutoBindings::updateUniformTime(float dt)
{
float time = Director::getInstance()->getTotalFrames() * Director::getInstance()->getAnimationInterval();
Vec4 random(time / 10.0f, time, time * 2.0f, time * 4.0f);
_noiseProgramState->setUniform(_locationTime, &random, sizeof(random));
}
//
//
//
@ -304,9 +341,7 @@ void Material_setTechnique::changeMaterial(float dt)
break;
}
_techniqueState++;
if (_techniqueState>2)
_techniqueState = 0;
_techniqueState = (_techniqueState + 1) % 3;
}
//
@ -446,131 +481,6 @@ std::string Material_parsePerformance::subtitle() const
return "Testing parsing performance";
}
//
//
//
void Material_invalidate::onEnter()
{
MaterialSystemBaseTest::onEnter();
// ORC
auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b");
sprite->setScale(5);
sprite->setRotation3D(Vec3(0,180,0));
addChild(sprite);
sprite->setPositionNormalized(Vec2(0.3f,0.3f));
auto rotate = RotateBy::create(5, Vec3(0,360,0));
auto repeat = RepeatForever::create(rotate);
sprite->runAction(repeat);
// SPINE
auto skeletonNode = spine::SkeletonAnimation::createWithJsonFile("spine/goblins-pro.json", "spine/goblins.atlas", 1.5f);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setSkin("goblin");
skeletonNode->setScale(0.25);
skeletonNode->setPositionNormalized(Vec2(0.6f,0.3f));
this->addChild(skeletonNode);
}
std::string Material_invalidate::subtitle() const
{
return "Testing RenderState::StateBlock::invalidate()";
}
void Material_invalidate::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
_customCommand.init(_globalZOrder, transform, flags);
_customCommand.func = []() {
glDisable(GL_DEPTH_TEST);
CHECK_GL_ERROR_DEBUG();
glDepthMask(false);
CHECK_GL_ERROR_DEBUG();
glEnable(GL_CULL_FACE);
CHECK_GL_ERROR_DEBUG();
glCullFace((GLenum)GL_FRONT);
CHECK_GL_ERROR_DEBUG();
glFrontFace((GLenum)GL_CW);
CHECK_GL_ERROR_DEBUG();
glDisable(GL_BLEND);
CHECK_GL_ERROR_DEBUG();
// a non-optimal way is to pass all bits, but that would be very inefficient
// RenderState::StateBlock::invalidate(RenderState::StateBlock::RS_ALL_ONES);
RenderState::StateBlock::invalidate(RenderState::StateBlock::RS_DEPTH_TEST |
RenderState::StateBlock::RS_DEPTH_WRITE |
RenderState::StateBlock::RS_CULL_FACE |
RenderState::StateBlock::RS_CULL_FACE_SIDE |
RenderState::StateBlock::RS_FRONT_FACE |
RenderState::StateBlock::RS_BLEND);
};
renderer->addCommand(&_customCommand);
}
//
//
//
void Material_renderState::onEnter()
{
MaterialSystemBaseTest::onEnter();
// ORC
auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b");
sprite->setScale(5);
sprite->setRotation3D(Vec3(0,180,0));
addChild(sprite);
sprite->setPositionNormalized(Vec2(0.3f,0.3f));
auto rotate = RotateBy::create(5, Vec3(0,360,0));
auto repeat = RepeatForever::create(rotate);
sprite->runAction(repeat);
// SPINE
auto skeletonNode = spine::SkeletonAnimation::createWithJsonFile("spine/goblins-pro.json", "spine/goblins.atlas", 1.5f);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setSkin("goblin");
skeletonNode->setScale(0.25);
skeletonNode->setPositionNormalized(Vec2(0.6f,0.3f));
this->addChild(skeletonNode);
_stateBlock.setDepthTest(false);
_stateBlock.setDepthWrite(false);
_stateBlock.setCullFace(true);
_stateBlock.setCullFaceSide(RenderState::CULL_FACE_SIDE_FRONT);
_stateBlock.setFrontFace(RenderState::FRONT_FACE_CW);
_stateBlock.setBlend(false);
}
std::string Material_renderState::subtitle() const
{
return "You should see a Spine animation on the right";
}
void Material_renderState::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
_customCommand.init(_globalZOrder, transform, flags);
_customCommand.func = [this]() {
this->_stateBlock.bind();
// should do something...
// and after that, restore
this->_stateBlock.restore(0);
};
renderer->addCommand(&_customCommand);
}
// MARK: Helper functions
static void printProperties(Properties* properties, int indent)

View File

@ -26,6 +26,10 @@
#pragma once
#include "../BaseTest.h"
#include "renderer/backend/Types.h"
#include "renderer/backend/ProgramState.h"
#include <vector>
DEFINE_TEST_SUITE(MaterialSystemTest);
@ -42,6 +46,7 @@ public:
virtual void onEnter() override;
virtual std::string subtitle() const override;
};
class Material_MultipleSprite3D : public MaterialSystemBaseTest
@ -60,6 +65,17 @@ public:
virtual void onEnter() override;
virtual std::string subtitle() const override;
void updateCCTimeUniforms(float);
private:
struct Locations {
Locations(cocos2d::backend::ProgramState *ps, cocos2d::backend::UniformLocation loc)
: programState(ps), location(loc) {}
cocos2d::backend::ProgramState *programState = nullptr;
cocos2d::backend::UniformLocation location;
};
std::vector<Locations> timeUniforms;
};
class EffectAutoBindingResolver;
@ -74,8 +90,12 @@ public:
virtual void onEnter() override;
virtual std::string subtitle() const override;
void updateUniformTime(float);
private:
EffectAutoBindingResolver *_resolver;
cocos2d::backend::UniformLocation _locationTime;
EffectAutoBindingResolver *_resolver = nullptr;
cocos2d::backend::ProgramState *_noiseProgramState = nullptr;
};
class Material_setTechnique : public MaterialSystemBaseTest
@ -114,31 +134,5 @@ protected:
unsigned int _maxParsingCoumt;
};
class Material_invalidate : public MaterialSystemBaseTest
{
public:
CREATE_FUNC(Material_invalidate);
virtual void onEnter() override;
virtual std::string subtitle() const override;
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
cocos2d::CustomCommand _customCommand;
};
class Material_renderState : public MaterialSystemBaseTest
{
public:
CREATE_FUNC(Material_renderState);
virtual void onEnter() override;
virtual std::string subtitle() const override;
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
cocos2d::RenderState::StateBlock _stateBlock;
cocos2d::CustomCommand _customCommand;
};

View File

@ -77,7 +77,7 @@ public:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
addTest("JNIHelper", []() { return new JNITests(); });
#endif
// addTest("Material System", [](){return new MaterialSystemTest(); });
addTest("Material System", [](){return new MaterialSystemTest(); });
// addTest("Navigation Mesh", [](){return new NavMeshTests(); });
addTest("Node: BillBoard Test", [](){ return new BillBoardTests(); });
// addTest("Node: Camera 3D Test", [](){ return new Camera3DTests(); });

View File

@ -9,6 +9,8 @@ uniform vec2 resolution;
uniform float blurRadius;
uniform float sampleNum;
uniform sampler2D u_texture;
vec4 blur(vec2);
void main(void)
@ -34,7 +36,7 @@ vec4 blur(vec2 p)
for(float y = -r; y < r; y += sampleStep)
{
float weight = (r - abs(x)) * (r - abs(y));
col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight;
col += texture2D(u_texture, p + vec2(x * unit.x, y * unit.y)) * weight;
count += weight;
}
}
@ -42,5 +44,5 @@ vec4 blur(vec2 p)
return col / count;
}
return texture2D(CC_Texture0, p);
return texture2D(u_texture, p);
}

View File

@ -6,11 +6,12 @@ varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec2 resolution;
uniform sampler2D u_texture;
float lookup(vec2 p, float dx, float dy)
{
vec2 uv = p.xy + vec2(dx , dy ) / resolution.xy;
vec4 c = texture2D(CC_Texture0, uv.xy);
vec4 c = texture2D(u_texture, uv.xy);
return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;
}

View File

@ -8,6 +8,8 @@ varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec2 resolution;
uniform sampler2D u_texture;
uniform vec4 CC_Time;
const float intensity = 0.05;
vec3 noise(vec2 uv)
@ -21,6 +23,6 @@ vec3 noise(vec2 uv)
void main(void)
{
gl_FragColor.xyz = intensity * noise(gl_FragCoord.xy / sin(resolution.xy * CC_Time[1] * 0.01)) + (1. - intensity) *
texture2D(CC_Texture0,v_texCoord.xy).xyz;
texture2D(u_texture,v_texCoord.xy).xyz;
gl_FragColor.w = 1.;
}

View File

@ -10,18 +10,20 @@ uniform vec3 u_outlineColor;
uniform float u_threshold;
uniform float u_radius;
uniform sampler2D u_texture;
void main()
{
float radius = u_radius;
vec4 accum = vec4(0.0);
vec4 normal = vec4(0.0);
normal = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y));
normal = texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y - radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y - radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y + radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y + radius));
accum += texture2D(u_texture, vec2(v_texCoord.x - radius, v_texCoord.y - radius));
accum += texture2D(u_texture, vec2(v_texCoord.x + radius, v_texCoord.y - radius));
accum += texture2D(u_texture, vec2(v_texCoord.x + radius, v_texCoord.y + radius));
accum += texture2D(u_texture, vec2(v_texCoord.x - radius, v_texCoord.y + radius));
accum *= u_threshold;
accum.rgb = u_outlineColor * accum.a;

View File

@ -10,9 +10,11 @@ varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
uniform mat4 u_MVPMatrix;
void main()
{
gl_Position = CC_PMatrix * a_position;
gl_Position = u_MVPMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}

View File

@ -20,9 +20,12 @@ varying vec3 v_vertexToSpotLightDirection[MAX_SPOT_LIGHT_NUM];
varying vec3 v_normal;
#endif
uniform mat4 u_MVMatrix;
uniform mat4 u_PMatrix;
uniform mat3 u_NormalMatrix;
void main(void)
{
vec4 ePosition = CC_MVMatrix * a_position;
vec4 ePosition = u_MVMatrix * a_position;
#if (MAX_POINT_LIGHT_NUM > 0)
for (int i = 0; i < MAX_POINT_LIGHT_NUM; ++i)
{
@ -38,11 +41,11 @@ void main(void)
#endif
#if ((MAX_DIRECTIONAL_LIGHT_NUM > 0) || (MAX_POINT_LIGHT_NUM > 0) || (MAX_SPOT_LIGHT_NUM > 0))
v_normal = CC_NormalMatrix * a_normal;
v_normal = u_NormalMatrix * a_normal;
#endif
TextureCoordOut = a_texCoord;
TextureCoordOut.y = 1.0 - TextureCoordOut.y;
gl_Position = CC_PMatrix * ePosition;
gl_Position = u_PMatrix * ePosition;
}