Improve shader managment

1. Rename uniformId to batchId, refine batch draw check logic, not use xxhash to compute uniforms id
2. Material works, not check all cpp-tests, but some 2d/3d material works fine
3. Shader load/cache API improvements.
4. BREAK compatibliity: Node::setProgramState change parameter needsRetain to ownPS and value inverted.
5. custom vertexLayout setup: add new API ProgramState::getMutableVertexLayout, mark ProgramState::setVertexAttrib deprecated.
6. ProgramManager registerCustomProgram change to gen progId by vsName, fsName
with xxhash64, if register succed, user can load it by progId with `loadProgram`
7. Add API ProgramManager::loadProgram for loading builtin by progType or
loding a custom program by id
8. Add API ProgramManager::loadProgram to load program by vsName, fsName
immediately without register as CUSTOM_PROGRAM
9. Add API Node::setProgramStateByProgramId(progTypeOrId); for set programState with
programType or programId explicit.
10. Migrate material load logic
This commit is contained in:
halx99 2023-07-25 09:13:20 +08:00
parent 5a0838e52b
commit c37af4c38e
71 changed files with 789 additions and 2134 deletions

View File

@ -92,9 +92,9 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh
return true; return true;
} }
bool AtlasNode::setProgramState(backend::ProgramState* programState, bool needsRetain) bool AtlasNode::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
{ {
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;

View File

@ -99,7 +99,7 @@ public:
void setQuadsToDraw(ssize_t quadsToDraw); void setQuadsToDraw(ssize_t quadsToDraw);
size_t getQuadsToDraw() const; size_t getQuadsToDraw() const;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
AtlasNode() = default; AtlasNode() = default;
virtual ~AtlasNode(); virtual ~AtlasNode();

View File

@ -178,11 +178,11 @@ void DrawNode::updateShaderInternal(CustomCommand& cmd,
void DrawNode::setVertexLayout(CustomCommand& cmd) void DrawNode::setVertexLayout(CustomCommand& cmd)
{ {
auto* programState = cmd.getPipelineDescriptor().programState; auto* programState = cmd.getPipelineDescriptor().programState;
programState->validateSharedVertexLayout(VertexLayoutHelper::setupDrawNode); programState->validateSharedVertexLayout(backend::VertexLayoutType::DrawNode);
} }
void DrawNode::freeShaderInternal(CustomCommand& cmd) void DrawNode::freeShaderInternal(CustomCommand& cmd)
{ {
auto& pipelinePS = cmd.getPipelineDescriptor().programState; auto& pipelinePS = cmd.getPipelineDescriptor().programState;
AX_SAFE_RELEASE_NULL(pipelinePS); AX_SAFE_RELEASE_NULL(pipelinePS);
} }

View File

@ -117,17 +117,19 @@ bool GridBase::initWithSize(const Vec2& gridSize, Texture2D* texture, bool flipp
uint32_t totalSize = (VERTEX_POSITION_SIZE + VERTEX_TEXCOORD_SIZE) * sizeof(float); uint32_t totalSize = (VERTEX_POSITION_SIZE + VERTEX_TEXCOORD_SIZE) * sizeof(float);
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position"); auto iter = attributeInfo.find("a_position");
auto layout = _programState->getMutableVertexLayout();
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false); layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false);
} }
iter = attributeInfo.find("a_texCoord"); iter = attributeInfo.find("a_texCoord");
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset, layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset,
false); false);
} }
_programState->setVertexStride(totalSize); layout->setStride(totalSize);
calculateVertexPoints(); calculateVertexPoints();
updateBlendState(); updateBlendState();

View File

@ -676,12 +676,12 @@ static Texture2D* _getTexture(Label* label)
void Label::setVertexLayout() void Label::setVertexLayout()
{ {
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
} }
bool Label::setProgramState(backend::ProgramState* programState, bool needsRetain) bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
{ {
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
updateUniformLocations(); updateUniformLocations();
for (auto&& batch : _batchCommands) for (auto&& batch : _batchCommands)
@ -743,8 +743,7 @@ void Label::updateShaderProgram()
} }
} }
auto* program = backend::Program::getBuiltinProgram(programType); this->setProgramStateByProgramId(programType);
setProgramState(new backend::ProgramState(program), false);
updateUniformLocations(); updateUniformLocations();

View File

@ -674,7 +674,7 @@ public:
*/ */
float getAdditionalKerning() const; float getAdditionalKerning() const;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
FontAtlas* getFontAtlas() { return _fontAtlas; } FontAtlas* getFontAtlas() { return _fontAtlas; }

View File

@ -221,9 +221,9 @@ void MotionStreak::setTexture(Texture2D* texture)
} }
} }
bool MotionStreak::setProgramState(backend::ProgramState* programState, bool needsRetain) bool MotionStreak::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/)
{ {
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
AXASSERT(programState, "argument should not be nullptr"); AXASSERT(programState, "argument should not be nullptr");
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
@ -235,23 +235,24 @@ bool MotionStreak::setProgramState(backend::ProgramState* programState, bool nee
// setup custom vertex layout for V2F_T2F_C4B // setup custom vertex layout for V2F_T2F_C4B
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position"); auto iter = attributeInfo.find("a_position");
auto layout = _programState->getMutableVertexLayout();
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false); layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false);
} }
iter = attributeInfo.find("a_texCoord"); iter = attributeInfo.find("a_texCoord");
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2,
2 * sizeof(float), false); 2 * sizeof(float), false);
} }
iter = attributeInfo.find("a_color"); iter = attributeInfo.find("a_color");
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4, layout->setAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4,
4 * sizeof(float), true); 4 * sizeof(float), true);
} }
_programState->setVertexStride(4 * sizeof(float) + 4 * sizeof(uint8_t)); layout->setStride(4 * sizeof(float) + 4 * sizeof(uint8_t));
updateProgramStateTexture(_texture); updateProgramStateTexture(_texture);
return true; return true;

View File

@ -156,7 +156,7 @@ public:
_startingPositionInitialized = bStartingPositionInitialized; _startingPositionInitialized = bStartingPositionInitialized;
} }
bool setProgramState(backend::ProgramState* programState, bool needsRetain) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
MotionStreak(); MotionStreak();
virtual ~MotionStreak(); virtual ~MotionStreak();

View File

@ -45,6 +45,7 @@ THE SOFTWARE.
#include "2d/Component.h" #include "2d/Component.h"
#include "renderer/Material.h" #include "renderer/Material.h"
#include "math/TransformUtils.h" #include "math/TransformUtils.h"
#include "renderer/backend/ProgramManager.h"
#include "renderer/backend/ProgramStateRegistry.h" #include "renderer/backend/ProgramStateRegistry.h"
#if AX_NODE_RENDER_SUBPIXEL #if AX_NODE_RENDER_SUBPIXEL
@ -2228,22 +2229,33 @@ void Node::setProgramStateWithRegistry(uint32_t programType, Texture2D* texture)
{ {
auto samplerFlags = texture ? texture->getSamplerFlags() : 0; auto samplerFlags = texture ? texture->getSamplerFlags() : 0;
auto programState = backend::ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags); auto programState = backend::ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags);
setProgramState(programState, false); setProgramState(programState, true);
} }
bool Node::setProgramState(backend::ProgramState* programState, bool needsRetain) bool Node::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
{ {
if (_programState != programState) if (_programState != programState)
{ {
AX_SAFE_RELEASE(_programState); AX_SAFE_RELEASE(_programState);
_programState = programState; _programState = programState;
if (needsRetain) if (!ownPS)
AX_SAFE_RETAIN(_programState); AX_SAFE_RETAIN(_programState);
return !!_programState; return !!_programState;
} }
return false; return false;
} }
backend::ProgramState* Node::setProgramStateByProgramId(uint64_t programId)
{
auto prog = ProgramManager::getInstance()->loadProgram(programId);
if (prog)
{
this->setProgramState(new ProgramState(prog), true);
return _programState;
}
return nullptr;
}
void Node::updateProgramStateTexture(Texture2D* texture) void Node::updateProgramStateTexture(Texture2D* texture)
{ {
if (texture == nullptr || texture->getBackendTexture() == nullptr || _programState == nullptr) if (texture == nullptr || texture->getBackendTexture() == nullptr || _programState == nullptr)

View File

@ -1828,7 +1828,14 @@ public:
* Sets ProgramState with retain * Sets ProgramState with retain
* @param programState * @param programState
*/ */
virtual bool setProgramState(backend::ProgramState* programState, bool needsRetain = true); virtual bool setProgramState(backend::ProgramState* programState, bool ownPS = false);
/**
* Sets ProgramState by programId
* @param progId the program id or programType used to create programState
* @return ProgramState* (nullable)
*/
backend::ProgramState* setProgramStateByProgramId(uint64_t progId);
backend::ProgramState* getProgramState() const; backend::ProgramState* getProgramState() const;

View File

@ -57,15 +57,16 @@ backend::ProgramState* initPipelineDescriptor(ax::CustomCommand& command,
pipelieDescriptor.programState = programState; pipelieDescriptor.programState = programState;
// set custom vertexLayout according to V2F_C4B_T2F structure // set custom vertexLayout according to V2F_C4B_T2F structure
programState->setVertexAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION), auto vertexLayout = programState->getMutableVertexLayout();
backend::VertexFormat::FLOAT2, 0, false); vertexLayout->setAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION),
programState->setVertexAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD), backend::VertexFormat::FLOAT2, 0, false);
backend::VertexFormat::FLOAT2, vertexLayout->setAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD),
offsetof(V2F_C4B_T2F, texCoords), false); backend::VertexFormat::FLOAT2,
programState->setVertexAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR), offsetof(V2F_C4B_T2F, texCoords), false);
vertexLayout->setAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, backend::VertexFormat::UBYTE4,
offsetof(V2F_C4B_T2F, colors), true); offsetof(V2F_C4B_T2F, colors), true);
programState->setVertexStride(sizeof(V2F_C4B_T2F)); vertexLayout->setStride(sizeof(V2F_C4B_T2F));
if (ridal) if (ridal)
{ {
@ -107,7 +108,7 @@ bool ProgressTimer::initWithSprite(Sprite* sp)
// TODO: Use ProgramState Vector to Node // TODO: Use ProgramState Vector to Node
AX_SAFE_RELEASE(_programState2); AX_SAFE_RELEASE(_programState2);
setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), false); setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), true);
_programState2 = initPipelineDescriptor(_customCommand2, false, _locMVP2, _locTex2); _programState2 = initPipelineDescriptor(_customCommand2, false, _locMVP2, _locTex2);
return true; return true;

View File

@ -159,7 +159,7 @@ bool RenderTexture::initWithWidthAndHeight(int w,
PixelFormat depthStencilFormat, PixelFormat depthStencilFormat,
bool sharedRenderTarget) bool sharedRenderTarget)
{ {
AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8, "only RGB and RGBA formats are valid for a render texture"); AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4, "only RGB and RGBA formats are valid for a render texture");
bool ret = false; bool ret = false;
do do

View File

@ -358,7 +358,7 @@ void Sprite::setTexture(std::string_view filename)
void Sprite::setVertexLayout() void Sprite::setVertexLayout()
{ {
AXASSERT(_programState, "programState should not be nullptr"); AXASSERT(_programState, "programState should not be nullptr");
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
} }
void Sprite::setProgramState(uint32_t type) void Sprite::setProgramState(uint32_t type)
@ -366,10 +366,10 @@ void Sprite::setProgramState(uint32_t type)
setProgramStateWithRegistry(type, _texture); setProgramStateWithRegistry(type, _texture);
} }
bool Sprite::setProgramState(backend::ProgramState* programState, bool needsRetain) bool Sprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
{ {
AXASSERT(programState, "argument should not be nullptr"); AXASSERT(programState, "argument should not be nullptr");
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;

View File

@ -425,7 +425,7 @@ public:
/** /**
* Set or Attach new ProgramState * Set or Attach new ProgramState
*/ */
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
/** /**
* Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode. * Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode.

View File

@ -124,13 +124,13 @@ void SpriteBatchNode::setUniformLocation()
void SpriteBatchNode::setVertexLayout() void SpriteBatchNode::setVertexLayout()
{ {
AXASSERT(_programState, "programState should not be nullptr"); AXASSERT(_programState, "programState should not be nullptr");
_programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite);
} }
bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool needsRetain) bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
{ {
AXASSERT(programState, "programState should not be nullptr"); AXASSERT(programState, "programState should not be nullptr");
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor();
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;

View File

@ -213,7 +213,7 @@ public:
*/ */
virtual std::string getDescription() const override; virtual std::string getDescription() const override;
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
/** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array. /** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array.
* This method should be called only when you are dealing with very big AtlasSprite and when most of the Sprite * This method should be called only when you are dealing with very big AtlasSprite and when most of the Sprite

View File

@ -835,9 +835,9 @@ void MeshRenderer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag
} }
} }
bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool needsRetain) bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
{ {
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
for (auto&& state : _meshes) for (auto&& state : _meshes)
{ {

View File

@ -129,7 +129,7 @@ public:
// overrides // overrides
/** Sets ProgramState, attributes should be bound by the user */ /** Sets ProgramState, attributes should be bound by the user */
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
/* /*
* Get AABB * Get AABB

View File

@ -121,8 +121,7 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const
_blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
// shader state // shader state
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); this->setProgramStateByProgramId(ProgramType::POSITION_TEXTURE_COLOR);
setProgramState(new backend::ProgramState(program), false);
_customCommand.getPipelineDescriptor().programState = _programState; _customCommand.getPipelineDescriptor().programState = _programState;

View File

@ -64,8 +64,7 @@ bool Skybox::init()
_customCommand.setAfterCallback(AX_CALLBACK_0(Skybox::onAfterDraw, this)); _customCommand.setAfterCallback(AX_CALLBACK_0(Skybox::onAfterDraw, this));
// create and set our custom shader // create and set our custom shader
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::SKYBOX_3D); setProgramStateByProgramId(backend::ProgramType::SKYBOX_3D);
setProgramState(new backend::ProgramState(program), false);
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();

View File

@ -106,8 +106,7 @@ void ax::Terrain::setLightDir(const Vec3& lightDir)
bool Terrain::initProperties() bool Terrain::initProperties()
{ {
auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::TERRAIN_3D); setProgramStateByProgramId(ProgramType::TERRAIN_3D);
setProgramState(new backend::ProgramState(program), false);
_stateBlock.depthWrite = true; _stateBlock.depthWrite = true;
_stateBlock.depthTest = true; _stateBlock.depthTest = true;

View File

@ -90,15 +90,17 @@ bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCom
// Parse and set attributes // Parse and set attributes
parseAttributes(); parseAttributes();
int offset = 0; int offset = 0;
auto vertexLayout = _programState->getMutableVertexLayout();
for (auto k = 0; k < attributeCount; k++) for (auto k = 0; k < attributeCount; k++)
{ {
auto meshattribute = meshVertexData->getMeshVertexAttrib(k); auto meshattribute = meshVertexData->getMeshVertexAttrib(k);
setVertexAttribPointer(shaderinfos::getAttributeName(meshattribute.vertexAttrib), meshattribute.type, false, setVertexAttribPointer(vertexLayout, shaderinfos::getAttributeName(meshattribute.vertexAttrib),
meshattribute.type, false,
offset, 1 << k); offset, 1 << k);
offset += meshattribute.getAttribSizeBytes(); offset += meshattribute.getAttribSizeBytes();
} }
_programState->setVertexStride(offset); vertexLayout->setStride(offset);
AXASSERT(offset == meshVertexData->getSizePerVertex(), "vertex layout mismatch!"); AXASSERT(offset == meshVertexData->getSizePerVertex(), "vertex layout mismatch!");
@ -133,7 +135,8 @@ const backend::AttributeBindInfo* VertexAttribBinding::getVertexAttribValue(std:
return nullptr; return nullptr;
} }
void VertexAttribBinding::setVertexAttribPointer(std::string_view name, void VertexAttribBinding::setVertexAttribPointer(VertexLayout* vertexLayout,
std::string_view name,
backend::VertexFormat type, backend::VertexFormat type,
bool normalized, bool normalized,
int offset, int offset,
@ -143,7 +146,7 @@ void VertexAttribBinding::setVertexAttribPointer(std::string_view name,
if (v) if (v)
{ {
// AXLOG("axmol: set attribute '%s' location: %d, offset: %d", name.c_str(), v->location, offset); // AXLOG("axmol: set attribute '%s' location: %d, offset: %d", name.c_str(), v->location, offset);
_programState->setVertexAttrib(name, v->location, type, offset, normalized); vertexLayout->setAttrib(name, v->location, type, offset, normalized);
_vertexAttribsFlags |= flag; _vertexAttribsFlags |= flag;
} }
else else

View File

@ -107,7 +107,7 @@ private:
VertexAttribBinding& operator=(const VertexAttribBinding&); VertexAttribBinding& operator=(const VertexAttribBinding&);
bool init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*); bool init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*);
void setVertexAttribPointer(std::string_view name, void setVertexAttribPointer(VertexLayout* vertexLayout, std::string_view name,
backend::VertexFormat type, backend::VertexFormat type,
bool normalized, bool normalized,
int offset, int offset,

View File

@ -566,9 +566,7 @@ bool GLViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rect, f
#endif #endif
#if defined(AX_USE_GL) #if defined(AX_USE_GL)
CHECK_GL_ERROR_DEBUG();
glfwSwapInterval(_glContextAttrs.vsync ? 1 : 0); glfwSwapInterval(_glContextAttrs.vsync ? 1 : 0);
CHECK_GL_ERROR_DEBUG();
// check OpenGL version at first // check OpenGL version at first
const GLubyte* glVersion = glGetString(GL_VERSION); const GLubyte* glVersion = glGetString(GL_VERSION);

View File

@ -1,6 +1,5 @@
set(_AX_RENDERER_HEADER set(_AX_RENDERER_HEADER
renderer/CallbackCommand.h renderer/CallbackCommand.h
renderer/Colorizer.h
renderer/CustomCommand.h renderer/CustomCommand.h
renderer/GroupCommand.h renderer/GroupCommand.h
renderer/Material.h renderer/Material.h
@ -63,7 +62,6 @@ set(_AX_RENDERER_SRC
renderer/TextureCube.cpp renderer/TextureCube.cpp
renderer/TrianglesCommand.cpp renderer/TrianglesCommand.cpp
renderer/Shaders.cpp renderer/Shaders.cpp
renderer/Colorizer.cpp
renderer/backend/ProgramManager.cpp renderer/backend/ProgramManager.cpp
renderer/backend/ProgramStateRegistry.cpp renderer/backend/ProgramStateRegistry.cpp

View File

@ -1,865 +0,0 @@
#include "Colorizer.h"
#include "math/Mat3.h"
#include "2d/Node.h"
#include "renderer/Shaders.h"
#include "renderer/backend/Device.h"
NS_AX_BEGIN
#define FLT_SQRT_2 1.4142135623730950488016887242097
#define FLT_SQRT_3 1.7320508075688772935274463415059
#define FLT_XRS (1 / FLT_SQRT_2)
#define FLT_XRC FLT_XRS
#define FLT_YRS (-1 / FLT_SQRT_3)
#define FLT_YRC (FLT_SQRT_2 / FLT_SQRT_3)
#define RLUM (0.3086)
#define GLUM (0.6094)
#define BLUM (0.0820)
#define CLZ_PRINTMAT 0
typedef float _M3X3[3][3];
typedef float _M4X4[4][4];
static Vec3 fastest_rgb2hsv(const Color3B& rgb)
{
float r = rgb.r / 255.0f;
float g = rgb.g / 255.0f;
float b = rgb.b / 255.0f;
float h, s, v;
float K = 0.f;
if (g < b)
{
std::swap(g, b);
K = -1.f;
}
if (r < g)
{
std::swap(r, g);
K = -2.f / 6.f - K;
}
float chroma = r - std::min(g, b);
h = fabs(K + (g - b) / (6.f * chroma + 1e-20f));
s = chroma / (r + 1e-20f);
v = r;
return Vec3(h, s, v);
}
static Vec3 rgb2hsv(const Color3B& rgb)
{
unsigned char dst_h, dst_s, dst_v;
float r = rgb.r / 255.0f;
float g = rgb.g / 255.0f;
float b = rgb.b / 255.0f;
float h, s, v; // h:0-360.0, s:0.0-1.0, v:0.0-1.0
float max = std::max({r, g, b});
float min = std::min({r, g, b});
v = max;
if (max == 0.0f)
{
s = 0;
h = 0;
}
else if (max - min == 0.0f)
{
s = 0;
h = 0;
}
else
{
s = (max - min) / max;
if (max == r)
{
h = 60 * ((g - b) / (max - min)) + 0;
}
else if (max == g)
{
h = 60 * ((b - r) / (max - min)) + 120;
}
else
{
h = 60 * ((r - g) / (max - min)) + 240;
}
}
if (h < 0)
h += 360.0f;
dst_h = (unsigned char)(h / 2); // dst_h : 0-180
dst_s = (unsigned char)(s /* * 255*/); // dst_s : 0-255
dst_v = (unsigned char)(v /** 255*/); // dst_v : 0-255
return Vec3(dst_h / 180.f, dst_s, dst_v);
}
static void hsv2rgb(const unsigned char& src_h,
const unsigned char& src_s,
const unsigned char& src_v,
unsigned char& dst_r,
unsigned char& dst_g,
unsigned char& dst_b)
{
float h = src_h * 2.0f; // 0-360
float s = src_s / 255.0f; // 0.0-1.0
float v = src_v / 255.0f; // 0.0-1.0
float r, g, b; // 0.0-1.0
int hi = (int)(h / 60.0f) % 6;
float f = (h / 60.0f) - hi;
float p = v * (1.0f - s);
float q = v * (1.0f - s * f);
float t = v * (1.0f - s * (1.0f - f));
switch (hi)
{
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
dst_r = (unsigned char)(r * 255); // dst_r : 0-255
dst_g = (unsigned char)(g * 255); // dst_r : 0-255
dst_b = (unsigned char)(b * 255); // dst_r : 0-255
}
#if CLZ_PRINTMAT
static void printmat3(float mat[3][3])
{
int x, y;
char svalue[256];
int n = 0;
for (y = 0; y < 3; y++)
{
for (x = 0; x < 3; x++)
n += sprintf(svalue + n, "%f ", mat[y][x]);
n += sprintf(svalue + n, "\n");
}
n += sprintf(svalue + n, "\n");
log("%s", svalue);
}
static void printmat4(float mat[4][4])
{
int x, y;
char svalue[256];
int n = 0;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
n += sprintf(svalue + n, "%f ", mat[y][x]);
n += sprintf(svalue + n, "\n");
}
n += sprintf(svalue + n, "\n");
log("%s", svalue);
}
inline void printmat3(float (&mat)[9])
{
printmat3((_M3X3&)mat);
}
inline void printmat4(float (&mat)[16])
{
printmat4((_M4X4&)mat);
}
#endif
inline void createRotationX(Mat4* dst, float sv, float cv)
{
dst->m[5] = cv;
dst->m[6] = sv;
dst->m[9] = -sv;
dst->m[10] = cv;
}
inline void createRotationY(Mat4* dst, float sv, float cv)
{
dst->m[0] = cv;
dst->m[2] = -sv;
dst->m[8] = sv;
dst->m[10] = cv;
}
inline void createRotationZ(Mat4* dst, float sv, float cv)
{
dst->m[0] = cv;
dst->m[1] = sv;
dst->m[4] = -sv;
dst->m[5] = cv;
}
inline void rotateX(Mat4* dst, float sv, float cv)
{
Mat4 temp;
createRotationX(&temp, sv, cv);
Mat4::multiply(temp, *dst, dst);
}
inline void rotateY(Mat4* dst, float sv, float cv)
{
Mat4 temp;
createRotationY(&temp, sv, cv);
Mat4::multiply(temp, *dst, dst); // dst->multiply(temp); pitfall: matrix1 * matrix2 != matrix2 * matrix1
}
inline void rotateZ(Mat4* dst, float sv, float cv)
{
Mat4 temp;
createRotationZ(&temp, sv, cv);
Mat4::multiply(temp, *dst, dst);
}
inline void rotateZ(Mat4* dst, float angle)
{
Mat4 temp;
Mat4::createRotationZ(angle, &temp);
Mat4::multiply(temp, *dst, dst);
}
/*
* matrixmult -
* multiply two matricies
*/
static void matrixmult(float a[4][4], float b[4][4], float c[4][4])
{
int x, y;
float temp[4][4];
for (y = 0; y < 4; y++)
for (x = 0; x < 4; x++)
{
temp[y][x] = b[y][0] * a[0][x] + b[y][1] * a[1][x] + b[y][2] * a[2][x] + b[y][3] * a[3][x];
}
for (y = 0; y < 4; y++)
for (x = 0; x < 4; x++)
c[y][x] = temp[y][x];
}
/*
* identmat -
* make an identity matrix
*/
inline void identmat(float* matrix)
{
*matrix++ = 1.0; /* row 1 */
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 2 */
*matrix++ = 1.0;
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 3 */
*matrix++ = 0.0;
*matrix++ = 1.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 4 */
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 1.0;
}
/*
* xformpnt -
* transform a 3D point using a matrix
*/
static void xformpnt(float matrix[4][4], float x, float y, float z, float* tx, float* ty, float* tz)
{
*tx = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0] + matrix[3][0];
*ty = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1] + matrix[3][1];
*tz = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2] + matrix[3][2];
}
/*
* cscalemat -
* make a color scale marix
*/
static void cscalemat(float mat[4][4], float rscale, float gscale, float bscale)
{
float mmat[4][4];
mmat[0][0] = rscale;
mmat[0][1] = 0.0;
mmat[0][2] = 0.0;
mmat[0][3] = 0.0;
mmat[1][0] = 0.0;
mmat[1][1] = gscale;
mmat[1][2] = 0.0;
mmat[1][3] = 0.0;
mmat[2][0] = 0.0;
mmat[2][1] = 0.0;
mmat[2][2] = bscale;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* lummat -
* make a luminance marix
*/
static void lummat(float mat[4][4])
{
float mmat[4][4];
float rwgt, gwgt, bwgt;
rwgt = RLUM;
gwgt = GLUM;
bwgt = BLUM;
mmat[0][0] = rwgt;
mmat[0][1] = rwgt;
mmat[0][2] = rwgt;
mmat[0][3] = 0.0;
mmat[1][0] = gwgt;
mmat[1][1] = gwgt;
mmat[1][2] = gwgt;
mmat[1][3] = 0.0;
mmat[2][0] = bwgt;
mmat[2][1] = bwgt;
mmat[2][2] = bwgt;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* saturatemat -
* make a saturation marix
*/
static void saturatemat(float mat[4][4], float sat)
{
float mmat[4][4];
float a, b, c, d, e, f, g, h, i;
float rwgt, gwgt, bwgt;
rwgt = RLUM;
gwgt = GLUM;
bwgt = BLUM;
a = (1.0 - sat) * rwgt + sat;
b = (1.0 - sat) * rwgt;
c = (1.0 - sat) * rwgt;
d = (1.0 - sat) * gwgt;
e = (1.0 - sat) * gwgt + sat;
f = (1.0 - sat) * gwgt;
g = (1.0 - sat) * bwgt;
h = (1.0 - sat) * bwgt;
i = (1.0 - sat) * bwgt + sat;
mmat[0][0] = a;
mmat[0][1] = b;
mmat[0][2] = c;
mmat[0][3] = 0.0;
mmat[1][0] = d;
mmat[1][1] = e;
mmat[1][2] = f;
mmat[1][3] = 0.0;
mmat[2][0] = g;
mmat[2][1] = h;
mmat[2][2] = i;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* offsetmat -
* offset r, g, and b
*/
static void offsetmat(float mat[4][4], float roffset, float goffset, float boffset)
{
float mmat[4][4];
mmat[0][0] = 1.0;
mmat[0][1] = 0.0;
mmat[0][2] = 0.0;
mmat[0][3] = 0.0;
mmat[1][0] = 0.0;
mmat[1][1] = 1.0;
mmat[1][2] = 0.0;
mmat[1][3] = 0.0;
mmat[2][0] = 0.0;
mmat[2][1] = 0.0;
mmat[2][2] = 1.0;
mmat[2][3] = 0.0;
mmat[3][0] = roffset;
mmat[3][1] = goffset;
mmat[3][2] = boffset;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* xrotate -
* rotate about the x (red) axis
*/
inline void xrotatemat(float mat[4][4], float rs, float rc)
{
float mmat[4][4];
mmat[0][0] = 1.0;
mmat[0][1] = 0.0;
mmat[0][2] = 0.0;
mmat[0][3] = 0.0;
mmat[1][0] = 0.0;
mmat[1][1] = rc;
mmat[1][2] = rs;
mmat[1][3] = 0.0;
mmat[2][0] = 0.0;
mmat[2][1] = -rs;
mmat[2][2] = rc;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* yrotate -
* rotate about the y (green) axis
*/
static void yrotatemat(float mat[4][4], float rs, float rc)
{
float mmat[4][4];
mmat[0][0] = rc;
mmat[0][1] = 0.0;
mmat[0][2] = -rs;
mmat[0][3] = 0.0;
mmat[1][0] = 0.0;
mmat[1][1] = 1.0;
mmat[1][2] = 0.0;
mmat[1][3] = 0.0;
mmat[2][0] = rs;
mmat[2][1] = 0.0;
mmat[2][2] = rc;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* zrotate -
* rotate about the z (blue) axis
*/
static void zrotatemat(float mat[4][4], float rs, float rc)
{
float mmat[4][4];
mmat[0][0] = rc;
mmat[0][1] = rs;
mmat[0][2] = 0.0;
mmat[0][3] = 0.0;
mmat[1][0] = -rs;
mmat[1][1] = rc;
mmat[1][2] = 0.0;
mmat[1][3] = 0.0;
mmat[2][0] = 0.0;
mmat[2][1] = 0.0;
mmat[2][2] = 1.0;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* zshear -
* shear z using x and y.
*/
static void zshearmat(float mat[4][4], float dx, float dy)
{
float mmat[4][4];
mmat[0][0] = 1.0;
mmat[0][1] = 0.0;
mmat[0][2] = dx;
mmat[0][3] = 0.0;
mmat[1][0] = 0.0;
mmat[1][1] = 1.0;
mmat[1][2] = dy;
mmat[1][3] = 0.0;
mmat[2][0] = 0.0;
mmat[2][1] = 0.0;
mmat[2][2] = 1.0;
mmat[2][3] = 0.0;
mmat[3][0] = 0.0;
mmat[3][1] = 0.0;
mmat[3][2] = 0.0;
mmat[3][3] = 1.0;
matrixmult(mmat, mat, mat);
}
/*
* simplehuerotatemat -
* simple hue rotation. This changes luminance
*/
static void simplehuerotatemat(float mat[4][4], float rot)
{
// log("************* simplehuerotatemat");
float mag;
float xrs, xrc;
float yrs, yrc;
float zrs, zrc;
identmat((float*)mat);
/* rotate the grey vector into positive Z */
mag = sqrt(2.0);
xrs = 1.0 / mag;
xrc = 1.0 / mag;
xrotatemat(mat, xrs, xrc);
// printmat(mat);
mag = sqrt(3.0);
yrs = -1.0 / mag;
yrc = sqrt(2.0) / mag;
yrotatemat(mat, yrs, yrc);
// printmat(mat);
/* rotate the hue */
zrs = sin(rot);
zrc = cos(rot);
zrotatemat(mat, zrs, zrc);
// printmat(mat);
/* rotate the grey vector back into place */
yrotatemat(mat, -yrs, yrc);
// printmat(mat);
xrotatemat(mat, -xrs, xrc);
// printmat(mat);
// log("############## simplehuerotatemat");
}
/*
* huerotatemat -
* rotate the hue, while maintaining luminance.
*/
static void huerotatemat(float mat[4][4], float rot)
{
float mmat[4][4];
float mag;
float lx, ly, lz;
float xrs, xrc;
float yrs, yrc;
float zrs, zrc;
float zsx, zsy;
identmat((float*)mat);
identmat((float*)&mmat);
/* rotate the grey vector into positive Z */
mag = sqrt(2.0);
xrs = 1.0 / mag;
xrc = 1.0 / mag;
xrotatemat(mmat, xrs, xrc);
mag = sqrt(3.0);
yrs = -1.0 / mag;
yrc = sqrt(2.0) / mag;
yrotatemat(mmat, yrs, yrc);
/* shear the space to make the luminance plane horizontal */
xformpnt(mmat, RLUM, GLUM, BLUM, &lx, &ly, &lz);
zsx = lx / lz;
zsy = ly / lz;
zshearmat(mmat, zsx, zsy);
/* rotate the hue */
zrs = sin(rot);
zrc = cos(rot);
zrotatemat(mmat, zrs, zrc);
/* unshear the space to put the luminance plane back */
zshearmat(mmat, -zsx, -zsy);
/* rotate the grey vector back into place */
yrotatemat(mmat, -yrs, yrc);
xrotatemat(mmat, -xrs, xrc);
matrixmult(mmat, mat, mat);
}
/*
* xformpnt -
* transform a 3D point using a matrix
*/
static void xformpnt(Mat3* matrix, float x, float y, float z, float* tx, float* ty, float* tz)
{
*tx = x * matrix->m[0] + y * matrix->m[3] + z * matrix->m[6];
*ty = x * matrix->m[1] + y * matrix->m[4] + z * matrix->m[7];
*tz = x * matrix->m[2] + y * matrix->m[5] + z * matrix->m[8];
}
/*
* zshear -
* shear z using x and y.
*/
static void zshearmat(Mat3* mat, float dx, float dy)
{
// float mmat[4][4];
Mat3 mmat;
// mmat[0][0] = 1.0;
// mmat[0][1] = 0.0;
mmat.m[2] = dx;
// mmat[0][3] = 0.0;
// mmat[1][0] = 0.0;
// mmat[1][1] = 1.0;
mmat.m[5] = dy;
// mmat[1][3] = 0.0;
// mmat[2][0] = 0.0;
// mmat[2][1] = 0.0;
// mmat[2][2] = 1.0;
// mmat[2][3] = 0.0;
// mmat[3][0] = 0.0;
// mmat[3][1] = 0.0;
// mmat[3][2] = 0.0;
// mmat[3][3] = 1.0;
mat->mult(mmat); // matrixmult(mmat, mat, mat);
}
static void createHueMatrix(Mat4* dst, float angle)
{
// log("************* createHueMatrix4f");
memcpy(dst, &dst->IDENTITY, sizeof(*dst));
/* rotate the grey vector into positive Z */
createRotationX(dst, FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC);
rotateY(dst, FLT_YRS, FLT_YRC);
/* rotate the hue */
rotateZ(dst, angle);
/* rotate the grey vector back into place */
rotateY(dst, -FLT_YRS, FLT_YRC);
rotateX(dst, -FLT_XRS, FLT_XRC);
// log("############## createHueMatrix4f");
}
static void setMatrixHueOptimized(Mat3* dst, float angle)
{
float lx, ly, lz;
float zsx, zsy;
// memcpy(dst, &dst->IDENTITY, sizeof(*dst));
/* rotate the grey vector into positive Z */
dst->createRotationX(FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC);
dst->rotateY(FLT_YRS, FLT_YRC);
/* shear the space to make the luminance plane horizontal */
xformpnt(dst, RLUM, GLUM, BLUM, &lx, &ly, &lz);
zsx = lx / lz;
zsy = ly / lz;
zshearmat(dst, zsx, zsy);
/* rotate the hue */
dst->rotateZ(angle);
/* unshear the space to put the luminance plane back */
zshearmat(dst, -zsx, -zsy);
/* rotate the grey vector back into place */
dst->rotateY(-FLT_YRS, FLT_YRC);
dst->rotateX(-FLT_XRS, FLT_XRC);
}
/*
* Hue -
* HSV - H
*/
static void setMatrixHue(Mat3* dst, float angle)
{
log("************* createHueMat3");
// memcpy(dst, &dst->IDENTITY, sizeof(*dst));
/* rotate the grey vector into positive Z */
dst->createRotationX(FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC);
dst->rotateY(FLT_YRS, FLT_YRC);
/* rotate the hue */
dst->rotateZ(angle);
/* rotate the grey vector back into place */
dst->rotateY(-FLT_YRS, FLT_YRC);
dst->rotateX(-FLT_XRS, FLT_XRC);
log("############## createHueMat3");
}
/*
* saturatemat - 0~1, 0%~100% ?
* HSV - S
*/
static void setMatrixSat(Mat3* dst, float sat)
{
Mat3 temp;
float a, b, c, d, e, f, g, h, i;
float rwgt, gwgt, bwgt;
rwgt = RLUM;
gwgt = GLUM;
bwgt = BLUM;
a = (1.0 - sat) * rwgt + sat;
b = (1.0 - sat) * rwgt;
c = (1.0 - sat) * rwgt;
d = (1.0 - sat) * gwgt;
e = (1.0 - sat) * gwgt + sat;
f = (1.0 - sat) * gwgt;
g = (1.0 - sat) * bwgt;
h = (1.0 - sat) * bwgt;
i = (1.0 - sat) * bwgt + sat;
temp.m[0] = a;
temp.m[1] = b;
temp.m[2] = c;
// mmat[0][3] = 0.0;
temp.m[3] = d;
temp.m[4] = e;
temp.m[5] = f;
// mmat[1][3] = 0.0;
temp.m[6] = g;
temp.m[7] = h;
temp.m[8] = i;
// mmat[2][3] = 0.0;
// mmat[3][0] = 0.0;
// mmat[3][1] = 0.0;
// mmat[3][2] = 0.0;
// mmat[3][3] = 1.0;
// matrixmult(mmat, mat, mat);
dst->mult(temp);
}
/* Value
* HSV - V: 0~1, 0%, 100%
*/
static void setMatrixVal(Mat3* dst, float value)
{
// float mmat[4][4];
Mat3 temp;
temp.m[0] = value;
// temp.m[1] = 0.0;
// temp.m[2] = 0.0;
// mmat[0][3] = 0.0;
// mmat[1][0] = 0.0;
temp.m[4] = value;
// mmat[1][2] = 0.0;
// mmat[1][3] = 0.0;
// mmat[2][0] = 0.0;
// mmat[2][1] = 0.0;
temp.m[8] = value;
// mmat[2][3] = 0.0;
dst->mult(temp);
// matrixmult(mmat, mat, mat);
}
bool Colorizer::enableNodeIntelliShading(Node* node, const Vec3& hsv, const Vec3& filter)
{
if (node == nullptr)
return false;
node->setProgramState(backend::ProgramType::HSV);
updateNodeHsv(node, hsv, filter);
return true;
}
void Colorizer::updateNodeHsv(Node* node, const Vec3& hsv, const Vec3& filter)
{
Mat3 hsvMatrix;
setMatrixHueOptimized(&hsvMatrix, hsv.x);
setMatrixSat(&hsvMatrix, hsv.y);
setMatrixVal(&hsvMatrix, hsv.z);
#if CLZ_PRINTMAT
printmat3(hsvMatrix.m);
#endif
auto programState = node->getProgramState();
programState->setUniform(programState->getUniformLocation("u_mix_hsv"), &hsvMatrix.m[0], sizeof(hsvMatrix));
programState->setUniform(programState->getUniformLocation("u_filter_rgb"), &filter, sizeof(filter));
programState->hashOfUniforms();
}
NS_AX_END

View File

@ -1,23 +0,0 @@
/**
* CCColorizer, for color translate matrix
* reference: http://graficaobscura.com/matrix/index.html
* @autohr HALX99 2020
*/
#pragma once
#ifndef _CCCOLORIZER_H_
# define _CCCOLORIZER_H_
# include "math/Math.h"
# include "base/Types.h"
# include <string>
NS_AX_BEGIN
class AX_DLL Colorizer
{
public:
static bool enableNodeIntelliShading(Node* node, const Vec3& hsv, const Vec3& filter = Vec3(1.0f, 0.45f, 0.3109f));
static void updateNodeHsv(Node* node, const Vec3& hsv, const Vec3& filter = Vec3(1.0f, 0.45f, 0.3109f));
};
NS_AX_END
#endif

View File

@ -367,24 +367,12 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties)
// fragmentShader // fragmentShader
const char* fragShader = getOptionalString(shaderProperties, "fragmentShader", nullptr); const char* fragShader = getOptionalString(shaderProperties, "fragmentShader", nullptr);
// compileTimeDefines // compileTimeDefines, since axmol-1.1 no longer support compile time defines
const char* compileTimeDefines = getOptionalString(shaderProperties, "defines", ""); // const char* compileTimeDefines = getOptionalString(shaderProperties, "defines", "");
auto* fu = FileUtils::getInstance();
if (vertShader && fragShader) if (vertShader && fragShader)
{ {
auto program = ProgramManager::getInstance()->loadProgram(vertShader, fragShader);
auto vertShaderSrc = fu->getStringFromFile(vertShader);
auto fragShaderSrc = fu->getStringFromFile(fragShader);
//since axmol-1.1 no longer support compile time defines
//auto defs = replaceDefines(compileTimeDefines);
//vertShaderSrc = defs + "\n" + vertShaderSrc;
//fragShaderSrc = defs + "\n" + fragShaderSrc;
auto* program = backend::Device::getInstance()->newProgram(vertShaderSrc, fragShaderSrc);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
pass->setProgramState(programState); pass->setProgramState(programState);
@ -410,8 +398,7 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties)
} }
space = shaderProperties->getNextNamespace(); space = shaderProperties->getNextNamespace();
} }
AX_SAFE_RELEASE(program); programState->release();
AX_SAFE_RELEASE(programState);
} }
return true; return true;

View File

@ -62,8 +62,8 @@ AX_DLL const std::string_view hsv_frag = "hsv_fs"sv;
AX_DLL const std::string_view dualSampler_hsv_frag = "dualSampler_hsv_fs"sv; AX_DLL const std::string_view dualSampler_hsv_frag = "dualSampler_hsv_fs"sv;
AX_DLL const std::string_view videoTextureYUY2_frag = "videoTextureYUY2_fs"sv; AX_DLL const std::string_view videoTextureYUY2_frag = "videoTextureYUY2_fs"sv;
AX_DLL const std::string_view videoTextureNV12_frag = "videoTextureNV12_fs"sv; AX_DLL const std::string_view videoTextureNV12_frag = "videoTextureNV12_fs"sv;
AX_DLL const std::string_view lineColor3D_frag = "lineColor3D_fs"sv; AX_DLL const std::string_view lineColor_frag = "lineColor_fs"sv;
AX_DLL const std::string_view lineColor3D_vert = "lineColor3D_vs"sv; AX_DLL const std::string_view lineColor_vert = "lineColor_vs"sv;
AX_DLL const std::string_view color_frag = "color_fs"sv; AX_DLL const std::string_view color_frag = "color_fs"sv;
AX_DLL const std::string_view colorNormal_frag = "colorNormal_fs"sv; AX_DLL const std::string_view colorNormal_frag = "colorNormal_fs"sv;
AX_DLL const std::string_view colorNormalTexture_frag = "colorNormalTexture_fs"sv; AX_DLL const std::string_view colorNormalTexture_frag = "colorNormalTexture_fs"sv;

View File

@ -75,8 +75,8 @@ extern AX_DLL const std::string_view videoTextureYUY2_frag;
extern AX_DLL const std::string_view videoTextureNV12_frag; extern AX_DLL const std::string_view videoTextureNV12_frag;
/* below is 3d shaders */ /* below is 3d shaders */
extern AX_DLL const std::string_view lineColor3D_frag; extern AX_DLL const std::string_view lineColor_frag;
extern AX_DLL const std::string_view lineColor3D_vert; extern AX_DLL const std::string_view lineColor_vert;
extern AX_DLL const std::string_view color_frag; extern AX_DLL const std::string_view color_frag;
extern AX_DLL const std::string_view colorNormal_frag; extern AX_DLL const std::string_view colorNormal_frag;
extern AX_DLL const std::string_view colorNormalTexture_frag; extern AX_DLL const std::string_view colorNormalTexture_frag;

View File

@ -53,15 +53,16 @@ void TrianglesCommand::init(float globalOrder,
} }
_mv = mv; _mv = mv;
auto programType = _pipelineDescriptor.programState->getProgram()->getProgramType(); auto batchId = _pipelineDescriptor.programState->getBatchId();
auto uniformID = _pipelineDescriptor.programState->hashOfUniforms(); if (_batchId != batchId || _texture != texture->getBackendTexture() || _blendType != blendType)
if (_programType != programType || _texture != texture->getBackendTexture() || _blendType != blendType ||
_uniformID != uniformID)
{ {
_programType = programType; _batchId = batchId;
_texture = texture->getBackendTexture(); _texture = texture->getBackendTexture();
_blendType = blendType; _blendType = blendType;
_uniformID = uniformID;
// since it would be too expensive to check the uniforms, simplify enable batching for built-in program.
// if (_programType == backend::ProgramType::CUSTOM_PROGRAM)
// setSkipBatching(true);
// TODO: minggo set it in Node? // TODO: minggo set it in Node?
auto& blendDescriptor = _pipelineDescriptor.blendDescriptor; auto& blendDescriptor = _pipelineDescriptor.blendDescriptor;
@ -87,8 +88,7 @@ void TrianglesCommand::generateMaterialID()
struct struct
{ {
void* texture; void* texture;
uint32_t programType; uint64_t batchId;
uint32_t uniformID;
backend::BlendFactor src; backend::BlendFactor src;
backend::BlendFactor dst; backend::BlendFactor dst;
} hashMe; } hashMe;
@ -98,12 +98,11 @@ void TrianglesCommand::generateMaterialID()
// are set to random values by different compilers. // are set to random values by different compilers.
memset(&hashMe, 0, sizeof(hashMe)); memset(&hashMe, 0, sizeof(hashMe));
hashMe.texture = _texture; hashMe.texture = _texture;
hashMe.src = _blendType.src; hashMe.src = _blendType.src;
hashMe.dst = _blendType.dst; hashMe.dst = _blendType.dst;
hashMe.programType = _programType; hashMe.batchId = _batchId;
hashMe.uniformID = _uniformID; _materialID = XXH32((const void*)&hashMe, sizeof(hashMe), 0);
_materialID = XXH32((const void*)&hashMe, sizeof(hashMe), 0);
} }
NS_AX_END NS_AX_END

View File

@ -117,8 +117,7 @@ protected:
// Cached value to determine to generate material id or not. // Cached value to determine to generate material id or not.
BlendFunc _blendType = BlendFunc::DISABLE; BlendFunc _blendType = BlendFunc::DISABLE;
uint32_t _programType = backend::ProgramType::CUSTOM_PROGRAM; uint64_t _batchId = 0;
uint32_t _uniformID = 0;
backend::TextureBackend* _texture = nullptr; backend::TextureBackend* _texture = nullptr;
}; };

View File

@ -360,7 +360,7 @@ struct ProgramType
LABEL_DISTANCE_NORMAL, // positionTextureColor_vert, label_distanceNormal_frag LABEL_DISTANCE_NORMAL, // positionTextureColor_vert, label_distanceNormal_frag
LABEL_DISTANCE_OUTLINE, // positionTextureColor_vert, label_distanceOutline_frag LABEL_DISTANCE_OUTLINE, // positionTextureColor_vert, label_distanceOutline_frag
LABLE_DISTANCE_GLOW, // positionTextureColor_vert, label_distanceGlow_frag LABLE_DISTANCE_GLOW, // positionTextureColor_vert, label_distanceGlow_frag
LAYER_RADIA_GRADIENT, // position_vert, layer_radialGradient_frag LAYER_RADIA_GRADIENT, // position_vert, layer_radialGradient_frag
DUAL_SAMPLER, DUAL_SAMPLER,
@ -394,12 +394,13 @@ struct ProgramType
VIDEO_TEXTURE_YUY2, VIDEO_TEXTURE_YUY2,
VIDEO_TEXTURE_NV12, VIDEO_TEXTURE_NV12,
VIDEO_TEXTURE_BGR32, VIDEO_TEXTURE_BGR32,
BUILTIN_COUNT, BUILTIN_COUNT,
VIDEO_TEXTURE_RGB32 = POSITION_TEXTURE_COLOR, VIDEO_TEXTURE_RGB32 = POSITION_TEXTURE_COLOR,
CUSTOM_PROGRAM = 0x1000, // user-define program, used by engine CUSTOM_PROGRAM = 0x1000, // user-define program, used by engine
}; };
}; };
NS_AX_BACKEND_END NS_AX_BACKEND_END

View File

@ -28,6 +28,154 @@
NS_AX_BACKEND_BEGIN NS_AX_BACKEND_BEGIN
/*
* shader vertex layout setup functions
*/
struct VertexLayoutHelper
{
static void setupDummy(Program*) {}
static void setupTexture(Program* program)
{
auto vertexLayout = program->getVertexLayout();
/// a_position
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
/// a_texCoord
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, 2 * sizeof(float), false);
vertexLayout->setStride(4 * sizeof(float));
}
static void setupSprite(Program* program)
{
auto vertexLayout = program->getVertexLayout();
/// a_position
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
/// a_texCoord
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false);
/// a_color
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR,
program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
vertexLayout->setStride(sizeof(V3F_C4B_T2F));
}
static void setupDrawNode(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V2F_C4B_T2F, texCoords), false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR,
program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true);
vertexLayout->setStride(sizeof(V2F_C4B_T2F));
}
static void setupDrawNode3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR,
program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, sizeof(Vec3), true);
vertexLayout->setStride(sizeof(V3F_C4B));
}
static void setupSkyBox(Program* program)
{
auto vertexLayout = program->getVertexLayout();
auto attrNameLoc = program->getAttributeLocation(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION);
vertexLayout->setAttrib(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, attrNameLoc,
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setStride(sizeof(Vec3));
}
static void setupPU3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_C4F, position), false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, uv), false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR,
program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false);
vertexLayout->setStride(sizeof(V3F_T2F_C4F));
}
static void setupPos(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
vertexLayout->setStride(sizeof(Vec2));
}
static void setupPosColor(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR,
program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::FLOAT4, offsetof(V3F_C4F, colors), false);
vertexLayout->setStride(sizeof(V3F_C4F));
}
static void setupTerrain3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false);
vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_NORMAL,
program->getAttributeLocation(backend::Attribute::NORMAL),
backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_N3F, normal), false);
vertexLayout->setStride(sizeof(V3F_T2F_N3F));
}
};
std::function<void(Program*)> Program::s_vertexLayoutSetupList[static_cast<int>(VertexLayoutType::Count)] = {
VertexLayoutHelper::setupDummy, VertexLayoutHelper::setupPos, VertexLayoutHelper::setupTexture,
VertexLayoutHelper::setupSprite, VertexLayoutHelper::setupDrawNode, VertexLayoutHelper::setupDrawNode3D,
VertexLayoutHelper::setupSkyBox, VertexLayoutHelper::setupPU3D, VertexLayoutHelper::setupPosColor,
VertexLayoutHelper::setupTerrain3D
};
Program::Program(std::string_view vs, std::string_view fs) Program::Program(std::string_view vs, std::string_view fs)
: _vertexShader(vs), _fragmentShader(fs), _vertexLayout(new VertexLayout()) : _vertexShader(vs), _fragmentShader(fs), _vertexLayout(new VertexLayout())
{} {}
@ -36,9 +184,10 @@ Program::~Program() {
delete _vertexLayout; delete _vertexLayout;
} }
void Program::setProgramType(uint32_t type) void Program::setupVertexLayout(VertexLayoutType vlt)
{ {
_programType = type; if (vlt < VertexLayoutType::Count)
s_vertexLayoutSetupList[static_cast<int>(vlt)](this);
} }
Program* Program::getBuiltinProgram(uint32_t type) Program* Program::getBuiltinProgram(uint32_t type)
@ -46,4 +195,9 @@ Program* Program::getBuiltinProgram(uint32_t type)
return ProgramManager::getInstance()->getBuiltinProgram(type); return ProgramManager::getInstance()->getBuiltinProgram(type);
} }
void Program::setProgramIds(uint32_t progType, uint64_t progId) {
_programType = progType;
_programId = progId;
_batchEnabled = _programType != ProgramType::CUSTOM_PROGRAM;
}
NS_AX_BACKEND_END NS_AX_BACKEND_END

View File

@ -30,6 +30,7 @@
#include "Types.h" #include "Types.h"
#include "ShaderCache.h" #include "ShaderCache.h"
#include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
@ -40,6 +41,26 @@ class ShaderModule;
class VertexLayout; class VertexLayout;
class ProgramManager; class ProgramManager;
/**
* @addtogroup _backend
* @{
*/
enum class VertexLayoutType
{
Unspec, // needs binding after program load
Pos, // V2F
Texture, // T2F
Sprite, // V3F_C4B_T2F posTexColor
DrawNode, // V2F_C4B_T2F
DrawNode3D, // V3F_C4B
SkyBox, // V3F
PU3D, // V3F_C4B_T2F // same with sprite, TODO: reuse spriete
posColor, // V3F_C4B
Terrain3D, // V3F_T2F_V3F
Count
};
/** /**
* @addtogroup _backend * @addtogroup _backend
* @{ * @{
@ -116,12 +137,23 @@ public:
*/ */
std::string_view getFragmentShader() const { return _fragmentShader; } std::string_view getFragmentShader() const { return _fragmentShader; }
/**
* Sets the program shared vertex layout type, see: VertexLayoutType
*/
void setupVertexLayout(VertexLayoutType vlt);
/** /**
* Get engine built-in program type. * Get engine built-in program type.
* @return The built-in program type. * @return The built-in program type.
*/ */
uint32_t getProgramType() const { return _programType; } uint32_t getProgramType() const { return _programType; }
/**
* Get program id.
* @return The program id.
*/
int64_t getProgramId() const { return _programId; }
/** /**
* Get uniform buffer size in bytes that can hold all the uniforms. * Get uniform buffer size in bytes that can hold all the uniforms.
* @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT. * @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT.
@ -143,15 +175,18 @@ public:
*/ */
virtual const hlookup::string_map<UniformInfo>& getAllActiveUniformInfo(ShaderStage stage) const = 0; virtual const hlookup::string_map<UniformInfo>& getAllActiveUniformInfo(ShaderStage stage) const = 0;
/**
* Set engin built-in program type.
* @param type Specifies the program type.
*/
void setProgramType(uint32_t type);
inline VertexLayout* getVertexLayout() const { return _vertexLayout; } inline VertexLayout* getVertexLayout() const { return _vertexLayout; }
/**
* Sets batch draw enabled
*/
void setBatchDrawEnabled(bool enabled) { _batchEnabled = enabled; }
bool isBatchEnabled() const { return _batchEnabled; }
protected: protected:
void setProgramIds(uint32_t progType, uint64_t progId);
/** /**
* @param vs Specifes the vertex shader source. * @param vs Specifes the vertex shader source.
* @param fs Specifes the fragment shader source. * @param fs Specifes the fragment shader source.
@ -192,6 +227,12 @@ protected:
std::string _fragmentShader; ///< Fragment shader. std::string _fragmentShader; ///< Fragment shader.
VertexLayout* _vertexLayout = nullptr; VertexLayout* _vertexLayout = nullptr;
uint32_t _programType = ProgramType::CUSTOM_PROGRAM; ///< built-in program type, initial value is CUSTOM_PROGRAM. uint32_t _programType = ProgramType::CUSTOM_PROGRAM; ///< built-in program type, initial value is CUSTOM_PROGRAM.
uint64_t _programId = 0;
bool _batchEnabled = false;
using VERTEX_LAYOUT_SETUP_FUNC = std::function<void(Program*)>;
static std::function<void(Program*)> s_vertexLayoutSetupList[static_cast<int>(VertexLayoutType::Count)];
}; };
// end of _backend group // end of _backend group

View File

@ -30,20 +30,12 @@
#include "base/Macros.h" #include "base/Macros.h"
#include "base/Configuration.h" #include "base/Configuration.h"
#include "xxhash.h"
NS_AX_BACKEND_BEGIN NS_AX_BACKEND_BEGIN
ProgramManager* ProgramManager::_sharedProgramManager = nullptr; ProgramManager* ProgramManager::_sharedProgramManager = nullptr;
Program* ProgramManager::newProgram(std::string_view vertShaderSource,
std::string_view fragShaderSource,
std::function<void(Program*)> fnSetupLayout)
{
auto program = Device::getInstance()->newProgram(vertShaderSource, fragShaderSource);
if (program)
fnSetupLayout(program);
return program;
}
ProgramManager* ProgramManager::getInstance() ProgramManager* ProgramManager::getInstance()
{ {
if (!_sharedProgramManager) if (!_sharedProgramManager)
@ -62,8 +54,15 @@ void ProgramManager::destroyInstance()
AX_SAFE_RELEASE_NULL(_sharedProgramManager); AX_SAFE_RELEASE_NULL(_sharedProgramManager);
} }
ProgramManager::ProgramManager()
{
_programIdGen = XXH64_createState();
}
ProgramManager::~ProgramManager() ProgramManager::~ProgramManager()
{ {
XXH64_freeState(_programIdGen);
for (auto&& program : _cachedPrograms) for (auto&& program : _cachedPrograms)
{ {
AX_SAFE_RELEASE(program.second); AX_SAFE_RELEASE(program.second);
@ -72,139 +71,6 @@ ProgramManager::~ProgramManager()
backend::ShaderCache::destroyInstance(); backend::ShaderCache::destroyInstance();
} }
/*
* shader vertex layout setup functions
*/
void VertexLayoutHelper::setupDummy(Program*) {}
void VertexLayoutHelper::setupTexture(Program* program)
{
auto vertexLayout = program->getVertexLayout();
/// a_position
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
/// a_texCoord
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, 2 * sizeof(float), false);
vertexLayout->setStride(4 * sizeof(float));
}
void VertexLayoutHelper::setupSprite(Program* program)
{
auto vertexLayout = program->getVertexLayout();
/// a_position
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
/// a_texCoord
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false);
/// a_color
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
vertexLayout->setStride(sizeof(V3F_C4B_T2F));
}
void VertexLayoutHelper::setupDrawNode(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V2F_C4B_T2F, texCoords), false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true);
vertexLayout->setStride(sizeof(V2F_C4B_T2F));
}
void VertexLayoutHelper::setupDrawNode3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::UBYTE4, sizeof(Vec3), true);
vertexLayout->setStride(sizeof(V3F_C4B));
}
void VertexLayoutHelper::setupSkyBox(Program* program)
{
auto vertexLayout = program->getVertexLayout();
auto attrNameLoc = program->getAttributeLocation(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION);
vertexLayout->setAttribute(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, attrNameLoc,
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setStride(sizeof(Vec3));
}
void VertexLayoutHelper::setupPU3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_C4F, position), false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, uv), false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false);
vertexLayout->setStride(sizeof(V3F_T2F_C4F));
}
void VertexLayoutHelper::setupPos(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT2, 0, false);
vertexLayout->setStride(sizeof(Vec2));
}
void VertexLayoutHelper::setupPosColor(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR),
backend::VertexFormat::FLOAT4, offsetof(V3F_C4F, colors), false);
vertexLayout->setStride(sizeof(V3F_C4F));
}
void VertexLayoutHelper::setupTerrain3D(Program* program)
{
auto vertexLayout = program->getVertexLayout();
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION,
program->getAttributeLocation(backend::Attribute::POSITION),
backend::VertexFormat::FLOAT3, 0, false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD,
program->getAttributeLocation(backend::Attribute::TEXCOORD),
backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false);
vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_NORMAL,
program->getAttributeLocation(backend::Attribute::NORMAL), backend::VertexFormat::FLOAT3,
offsetof(V3F_T2F_N3F, normal), false);
vertexLayout->setStride(sizeof(V3F_T2F_N3F));
}
// ### end of vertex layout setup functions // ### end of vertex layout setup functions
static std::string joinPath(std::string_view path, std::string_view childPath) static std::string joinPath(std::string_view path, std::string_view childPath)
{ {
@ -227,70 +93,62 @@ bool ProgramManager::init()
#endif #endif
registerProgram(ProgramType::POSITION_TEXTURE_COLOR, positionTextureColor_vert, positionTextureColor_frag, registerProgram(ProgramType::POSITION_TEXTURE_COLOR, positionTextureColor_vert, positionTextureColor_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::DUAL_SAMPLER, positionTextureColor_vert, dualSampler_frag, registerProgram(ProgramType::DUAL_SAMPLER, positionTextureColor_vert, dualSampler_frag, VertexLayoutType::Sprite);
VertexLayoutHelper::setupSprite);
registerProgram(ProgramType::LABEL_DISTANCE_NORMAL, positionTextureColor_vert, label_distanceNormal_frag, registerProgram(ProgramType::LABEL_DISTANCE_NORMAL, positionTextureColor_vert, label_distanceNormal_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::LABEL_NORMAL, positionTextureColor_vert, label_normal_frag, registerProgram(ProgramType::LABEL_NORMAL, positionTextureColor_vert, label_normal_frag, VertexLayoutType::Sprite);
VertexLayoutHelper::setupSprite);
registerProgram(ProgramType::LABLE_OUTLINE, positionTextureColor_vert, label_outline_frag, registerProgram(ProgramType::LABLE_OUTLINE, positionTextureColor_vert, label_outline_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::LABEL_DISTANCE_OUTLINE, positionTextureColor_vert, label_distanceOutline_frag, registerProgram(ProgramType::LABEL_DISTANCE_OUTLINE, positionTextureColor_vert, label_distanceOutline_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::LABLE_DISTANCE_GLOW, positionTextureColor_vert, label_distanceGlow_frag, registerProgram(ProgramType::LABLE_DISTANCE_GLOW, positionTextureColor_vert, label_distanceGlow_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::POSITION_COLOR_LENGTH_TEXTURE, positionColorLengthTexture_vert, registerProgram(ProgramType::POSITION_COLOR_LENGTH_TEXTURE, positionColorLengthTexture_vert,
positionColorLengthTexture_frag, VertexLayoutHelper::setupDrawNode); positionColorLengthTexture_frag, VertexLayoutType::DrawNode);
registerProgram(ProgramType::POSITION_COLOR_TEXTURE_AS_POINTSIZE, positionColorTextureAsPointsize_vert, registerProgram(ProgramType::POSITION_COLOR_TEXTURE_AS_POINTSIZE, positionColorTextureAsPointsize_vert,
positionColor_frag, VertexLayoutHelper::setupDrawNode); positionColor_frag, VertexLayoutType::DrawNode);
registerProgram(ProgramType::POSITION_COLOR, positionColor_vert, positionColor_frag, registerProgram(ProgramType::POSITION_COLOR, positionColor_vert, positionColor_frag, VertexLayoutType::posColor);
VertexLayoutHelper::setupPosColor); registerProgram(ProgramType::LAYER_RADIA_GRADIENT, position_vert, layer_radialGradient_frag, VertexLayoutType::Pos);
registerProgram(ProgramType::LAYER_RADIA_GRADIENT, position_vert, layer_radialGradient_frag,
VertexLayoutHelper::setupPos);
registerProgram(ProgramType::POSITION_TEXTURE, positionTexture_vert, positionTexture_frag, registerProgram(ProgramType::POSITION_TEXTURE, positionTexture_vert, positionTexture_frag,
VertexLayoutHelper::setupTexture); VertexLayoutType::Texture);
registerProgram(ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, positionTextureColor_vert, registerProgram(ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, positionTextureColor_vert,
positionTextureColorAlphaTest_frag, VertexLayoutHelper::setupSprite); positionTextureColorAlphaTest_frag, VertexLayoutType::Sprite);
registerProgram(ProgramType::POSITION_UCOLOR, positionUColor_vert, positionColor_frag, registerProgram(ProgramType::POSITION_UCOLOR, positionUColor_vert, positionColor_frag, VertexLayoutType::Pos);
VertexLayoutHelper::setupPos);
registerProgram(ProgramType::DUAL_SAMPLER_GRAY, positionTextureColor_vert, dualSampler_gray_frag, registerProgram(ProgramType::DUAL_SAMPLER_GRAY, positionTextureColor_vert, dualSampler_gray_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::GRAY_SCALE, positionTextureColor_vert, grayScale_frag, registerProgram(ProgramType::GRAY_SCALE, positionTextureColor_vert, grayScale_frag, VertexLayoutType::Sprite);
VertexLayoutHelper::setupSprite); registerProgram(ProgramType::LINE_COLOR_3D, lineColor_vert, lineColor_frag, VertexLayoutType::DrawNode3D);
registerProgram(ProgramType::LINE_COLOR_3D, lineColor3D_vert, lineColor3D_frag, registerProgram(ProgramType::CAMERA_CLEAR, cameraClear_vert, cameraClear_frag, VertexLayoutType::Sprite);
VertexLayoutHelper::setupDrawNode3D); registerProgram(ProgramType::SKYBOX_3D, skybox_vert, skybox_frag, VertexLayoutType::SkyBox);
registerProgram(ProgramType::CAMERA_CLEAR, cameraClear_vert, cameraClear_frag, VertexLayoutHelper::setupSprite);
registerProgram(ProgramType::SKYBOX_3D, skybox_vert, skybox_frag, VertexLayoutHelper::setupSkyBox);
registerProgram(ProgramType::SKINPOSITION_TEXTURE_3D, skinPositionTexture_vert, colorTexture_frag, registerProgram(ProgramType::SKINPOSITION_TEXTURE_3D, skinPositionTexture_vert, colorTexture_frag,
VertexLayoutHelper::setupDummy); VertexLayoutType::Unspec);
registerProgram(ProgramType::SKINPOSITION_NORMAL_TEXTURE_3D, skinPositionNormalTexture_vert, registerProgram(ProgramType::SKINPOSITION_NORMAL_TEXTURE_3D, skinPositionNormalTexture_vert,
colorNormalTexture_frag, VertexLayoutHelper::setupDummy); colorNormalTexture_frag, VertexLayoutType::Unspec);
registerProgram(ProgramType::POSITION_NORMAL_TEXTURE_3D, positionNormalTexture_vert, colorNormalTexture_frag, registerProgram(ProgramType::POSITION_NORMAL_TEXTURE_3D, positionNormalTexture_vert, colorNormalTexture_frag,
VertexLayoutHelper::setupDummy); VertexLayoutType::Unspec);
registerProgram(ProgramType::POSITION_TEXTURE_3D, positionTexture3D_vert, colorTexture_frag, registerProgram(ProgramType::POSITION_TEXTURE_3D, positionTexture3D_vert, colorTexture_frag,
VertexLayoutHelper::setupDummy); VertexLayoutType::Unspec);
registerProgram(ProgramType::POSITION_3D, positionTexture3D_vert, color_frag, VertexLayoutHelper::setupSprite); registerProgram(ProgramType::POSITION_3D, positionTexture3D_vert, color_frag, VertexLayoutType::Sprite);
registerProgram(ProgramType::POSITION_NORMAL_3D, positionNormalTexture_vert, colorNormal_frag, registerProgram(ProgramType::POSITION_NORMAL_3D, positionNormalTexture_vert, colorNormal_frag,
VertexLayoutHelper::setupDummy); VertexLayoutType::Unspec);
registerProgram(ProgramType::POSITION_BUMPEDNORMAL_TEXTURE_3D, positionNormalTexture_vert_1, registerProgram(ProgramType::POSITION_BUMPEDNORMAL_TEXTURE_3D, positionNormalTexture_vert_1,
colorNormalTexture_frag_1, VertexLayoutHelper::setupDummy); colorNormalTexture_frag_1, VertexLayoutType::Unspec);
registerProgram(ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D, skinPositionNormalTexture_vert_1, registerProgram(ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D, skinPositionNormalTexture_vert_1,
colorNormalTexture_frag_1, VertexLayoutHelper::setupDummy); colorNormalTexture_frag_1, VertexLayoutType::Unspec);
registerProgram(ProgramType::TERRAIN_3D, terrain_vert, terrain_frag, VertexLayoutHelper::setupTerrain3D); registerProgram(ProgramType::TERRAIN_3D, terrain_vert, terrain_frag, VertexLayoutType::Terrain3D);
registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, VertexLayoutType::PU3D);
VertexLayoutHelper::setupPU3D); registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutType::PU3D);
registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutHelper::setupPU3D); registerProgram(ProgramType::QUAD_COLOR_2D, quadColor_vert, quadColor_frag, VertexLayoutType::Unspec);
registerProgram(ProgramType::QUAD_COLOR_2D, quadColor_vert, quadColor_frag, VertexLayoutHelper::setupDummy); registerProgram(ProgramType::QUAD_TEXTURE_2D, quadTexture_vert, quadTexture_frag, VertexLayoutType::Unspec);
registerProgram(ProgramType::QUAD_TEXTURE_2D, quadTexture_vert, quadTexture_frag, VertexLayoutHelper::setupDummy); registerProgram(ProgramType::HSV, positionTextureColor_vert, hsv_frag, VertexLayoutType::Sprite);
registerProgram(ProgramType::HSV, positionTextureColor_vert, hsv_frag, VertexLayoutHelper::setupSprite);
registerProgram(ProgramType::HSV_DUAL_SAMPLER, positionTextureColor_vert, dualSampler_hsv_frag, registerProgram(ProgramType::HSV_DUAL_SAMPLER, positionTextureColor_vert, dualSampler_hsv_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::VIDEO_TEXTURE_YUY2, positionTextureColor_vert, videoTextureYUY2_frag, registerProgram(ProgramType::VIDEO_TEXTURE_YUY2, positionTextureColor_vert, videoTextureYUY2_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
registerProgram(ProgramType::VIDEO_TEXTURE_NV12, positionTextureColor_vert, videoTextureNV12_frag, registerProgram(ProgramType::VIDEO_TEXTURE_NV12, positionTextureColor_vert, videoTextureNV12_frag,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
// The builtin dual sampler shader registry // The builtin dual sampler shader registry
ProgramStateRegistry::getInstance()->registerProgram(ProgramType::POSITION_TEXTURE_COLOR, ProgramStateRegistry::getInstance()->registerProgram(ProgramType::POSITION_TEXTURE_COLOR,
@ -304,111 +162,117 @@ bool ProgramManager::init()
return true; return true;
} }
Program* ProgramManager::getCustomProgram(uint32_t type) const Program* ProgramManager::getBuiltinProgram(uint32_t type)
{ {
return getBuiltinProgram(type | ProgramType::CUSTOM_PROGRAM); assert(type < ProgramType::BUILTIN_COUNT);
auto& info = _builtinRegistry[static_cast<int>(type)];
return loadProgram(info.vsName, info.fsName, type, static_cast<uint64_t>(type), info.vlt);
} }
Program* ProgramManager::getBuiltinProgram(uint32_t type) const Program* ProgramManager::loadProgram(uint64_t progId)
{ {
auto iter = _cachedPrograms.find(type); if (progId < ProgramType::BUILTIN_COUNT)
if (iter != _cachedPrograms.end()) return getBuiltinProgram(static_cast<uint32_t>(progId));
return iter->second;
return addProgram(type); auto it = _customRegistry.find(progId);
if (it != _customRegistry.end())
return loadProgram(it->second.vsName, it->second.fsName, ProgramType::CUSTOM_PROGRAM, progId, it->second.vlt);
return nullptr;
} }
Program* ProgramManager::addProgram(uint32_t internalType) const Program* ProgramManager::loadProgram(std::string_view vsName, std::string_view fsName, VertexLayoutType vlt)
{ {
Program* program = nullptr; return loadProgram(vsName, fsName, ProgramType::CUSTOM_PROGRAM, computeProgramId(vsName, fsName), vlt);
if (internalType < ProgramType::BUILTIN_COUNT) }
{
auto& func = _builtinRegistry[internalType]; Program* ProgramManager::loadProgram(std::string_view vsName,
if (func) std::string_view fsName,
program = func(); uint32_t progType,
} uint64_t progId,
else VertexLayoutType vlt)
{ {
auto iter = _customRegistry.find(internalType); assert(!vsName.empty() && !fsName.empty());
if (iter != _customRegistry.end())
{ auto it = _cachedPrograms.find(progId);
auto& func = iter->second; if (it != _cachedPrograms.end())
if (func) return it->second;
program = func();
} auto fileUtils = FileUtils::getInstance();
} auto vertFile = fileUtils->fullPathForFilename(vsName);
auto fragFile = fileUtils->fullPathForFilename(fsName);
auto vertSource = fileUtils->getStringFromFile(vertFile);
auto fragSource = fileUtils->getStringFromFile(fragFile);
auto program = backend::Device::getInstance()->newProgram(vertSource, fragSource);
if (program) if (program)
{ {
program->setProgramType(internalType); program->setProgramIds(progType, progId);
_cachedPrograms.emplace(internalType, program); if (vlt < VertexLayoutType::Count)
program->setupVertexLayout(vlt);
_cachedPrograms.emplace(progId, program);
} }
return program; return program;
} }
bool ProgramManager::registerCustomProgram(uint32_t type, uint64_t ProgramManager::registerCustomProgram(std::string_view vsName,
std::string_view vsName, std::string_view fsName,
std::string_view fsName, VertexLayoutType vlt,
std::function<void(Program*)> fnSetupLayout, bool force) bool force)
{ {
auto internalType = ProgramType::CUSTOM_PROGRAM | type; return registerProgram(ProgramType::CUSTOM_PROGRAM, vsName, fsName, vlt, force);
return registerProgram(internalType, vsName, fsName, std::move(fnSetupLayout), force);
} }
bool ProgramManager::registerProgram(uint32_t internalType, uint64_t ProgramManager::registerProgram(uint32_t progType,
std::string_view vertShaderName, std::string_view vsName,
std::string_view fragShaderName, std::string_view fsName,
std::function<void(Program*)> fnSetupLayout, VertexLayoutType vlt,
bool force) bool force)
{ {
auto loadShaderFunc = [vsName = std::string{vertShaderName}, fsName = std::string{fragShaderName}, uint64_t progId = 0;
setupLayout = std::move(fnSetupLayout)]() mutable { if (progType < ProgramType::BUILTIN_COUNT)
auto fileUtils = FileUtils::getInstance(); {
auto vertFile = fileUtils->fullPathForFilename(vsName); _builtinRegistry[static_cast<int>(progType)] = {vsName, fsName, vlt};
auto fragFile = fileUtils->fullPathForFilename(fsName); progId = progType;
auto vertSource = fileUtils->getStringFromFile(vertFile); }
auto fragSource = fileUtils->getStringFromFile(fragFile);
auto program = backend::Device::getInstance()->newProgram(vertSource, fragSource);
setupLayout(program);
return program;
};
bool ret = true;
if (internalType < ProgramType::BUILTIN_COUNT)
_builtinRegistry[internalType] = loadShaderFunc;
else else
{ {
auto it = _customRegistry.find(internalType); progId = computeProgramId(vsName, fsName);
auto it = _customRegistry.find(progId);
if (it == _customRegistry.end()) if (it == _customRegistry.end())
_customRegistry.emplace(internalType, loadShaderFunc); _customRegistry.emplace(progId, BuiltinRegInfo{vsName, fsName, vlt});
else if (ret = force) else if (force)
it->second = loadShaderFunc; it->second = BuiltinRegInfo{vsName, fsName, vlt};
else
progId = 0;
} }
return ret; return progId;
} }
void ProgramManager::removeProgram(Program* program) uint64_t ProgramManager::computeProgramId(std::string_view vsName, std::string_view fsName)
{
XXH64_reset(_programIdGen, 0);
XXH64_update(_programIdGen, vsName.data(), vsName.length());
XXH64_update(_programIdGen, fsName.data(), fsName.length());
return XXH64_digest(_programIdGen);
}
void ProgramManager::unloadProgram(Program* program)
{ {
if (!program) if (!program)
{ {
return; return;
} }
for (auto it = _cachedPrograms.cbegin(); it != _cachedPrograms.cend();) auto it = _cachedPrograms.find(program->_programId);
if (it != _cachedPrograms.end())
{ {
if (it->second == program) it->second->release();
{ _cachedPrograms.erase(it);
it->second->release();
it = _cachedPrograms.erase(it);
break;
}
else
++it;
} }
} }
void ProgramManager::removeUnusedProgram() void ProgramManager::unloadUnusedPrograms()
{ {
for (auto iter = _cachedPrograms.cbegin(); iter != _cachedPrograms.cend();) for (auto iter = _cachedPrograms.cbegin(); iter != _cachedPrograms.cend();)
{ {
@ -426,7 +290,7 @@ void ProgramManager::removeUnusedProgram()
} }
} }
void ProgramManager::removeAllPrograms() void ProgramManager::unloadAllPrograms()
{ {
ProgramStateRegistry::getInstance()->clearPrograms(); ProgramStateRegistry::getInstance()->clearPrograms();
for (auto&& program : _cachedPrograms) for (auto&& program : _cachedPrograms)

View File

@ -32,40 +32,23 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <string_view>
#include "ProgramStateRegistry.h" #include "ProgramStateRegistry.h"
struct XXH64_state_s;
NS_AX_BACKEND_BEGIN NS_AX_BACKEND_BEGIN
/** /**
* @addtogroup _backend * @addtogroup _backend
* @{ * @{
*/ */
struct AX_DLL VertexLayoutHelper
{
static void setupDummy(Program*);
static void setupPos(Program*);
static void setupTexture(Program*);
static void setupSprite(Program*);
static void setupDrawNode(Program*);
static void setupDrawNode3D(Program*);
static void setupSkyBox(Program*);
static void setupPU3D(Program*);
static void setupPosColor(Program*);
static void setupTerrain3D(Program*);
};
/** /**
* Cache and reuse program object. * Cache and reuse program object.
*/ */
class AX_DLL ProgramManager : public Ref class AX_DLL ProgramManager : public Ref
{ {
public: public:
/** new progrma with vertexLayout setup support, user should use this API */
static Program* newProgram(std::string_view vertShaderSource,
std::string_view fragShaderSource,
std::function<void(Program*)> fnSetupLayout = VertexLayoutHelper::setupDummy);
/** returns the shared instance */ /** returns the shared instance */
static ProgramManager* getInstance(); static ProgramManager* getInstance();
@ -73,36 +56,73 @@ public:
static void destroyInstance(); static void destroyInstance();
/// get built-in program /// get built-in program
Program* getBuiltinProgram(uint32_t type) const; Program* getBuiltinProgram(uint32_t type);
// get custom program, should call registerCustomProgram first /*
Program* getCustomProgram(uint32_t type) const; * register a custom program
* @returns
* the id of custom program, 0: fail, the id can use by loadProgram
*/
uint64_t registerCustomProgram(std::string_view vsName,
std::string_view fsName,
VertexLayoutType vlt = VertexLayoutType::Unspec,
bool force = false);
// register custom program create factory, if custom programType already registered, will failed /*
bool registerCustomProgram(uint32_t type, * load a builtin/or custom program:
std::string_view vsName, * @param id: the id of program to load, the id value returned by registerCustomProgram
std::string_view fsName, * or builtin programType, whe the id < ProgramType:BUILTIN_COUNT, this function
std::function<void(Program*)> fnSetupLayout = VertexLayoutHelper::setupDummy, * is identical to 'getBuiltinProgram'
bool force = false); */
Program* loadProgram(uint64_t progId);
/*
* load a program with vsName, fsName as CUSTOM immediately without register
* @params
* @param vsName: the vertex shader name: custom/xxx_vs
* @param fsName: the fragment shader name: custom/xxx_vs
* @param vlt: the builtin vertex layout type used for loading program
* @returns Program* (nullable)
* @remark: the returend program type always ProgramType::CUSTOM_PROGRAM
*/
Program* loadProgram(std::string_view vsName,
std::string_view fsName,
VertexLayoutType vlt = VertexLayoutType::Unspec);
/**
* Unload a program object from cache.
* @param program Specifies the program object to move.
*/
void unloadProgram(Program* program);
/**
* Unload all unused program objects from cache.
*/
void unloadUnusedPrograms();
/**
* Unload all program objects from cache.
*/
void unloadAllPrograms();
/** /**
* Remove a program object from cache. * Remove a program object from cache.
* @param program Specifies the program object to move. * @param program Specifies the program object to move.
*/ */
void removeProgram(Program* program); AX_DEPRECATED_ATTRIBUTE void removeProgram(Program* prog) { unloadProgram(prog); }
/** /**
* Remove all unused program objects from cache. * Remove all unused program objects from cache.
*/ */
void removeUnusedProgram(); AX_DEPRECATED_ATTRIBUTE void removeUnusedProgram() { unloadUnusedPrograms(); }
/** /**
* Remove all program objects from cache. * Remove all program objects from cache.
*/ */
void removeAllPrograms(); AX_DEPRECATED_ATTRIBUTE void removeAllPrograms() { unloadAllPrograms(); }
protected: protected:
ProgramManager() = default; ProgramManager();
virtual ~ProgramManager(); virtual ~ProgramManager();
/** /**
@ -110,18 +130,41 @@ protected:
*/ */
bool init(); bool init();
bool registerProgram(uint32_t internalType, /**
std::string_view vsName, * register a program
std::string_view fsName, */
std::function<void(Program*)> fnSetupLayout, uint64_t registerProgram(uint32_t progType,
bool force = false); std::string_view vsName,
Program* addProgram(uint32_t internalType) const; std::string_view fsName,
VertexLayoutType vlt,
bool force = false);
std::function<Program*()> _builtinRegistry[(int)backend::ProgramType::BUILTIN_COUNT]; /**
std::unordered_map<uint32_t, std::function<Program*()>> _customRegistry; * load a custom program by vsName, fsName, vertexLayout
*/
Program* loadProgram(std::string_view vsName,
std::string_view fsName,
uint32_t progType,
uint64_t progId,
VertexLayoutType vlt);
mutable std::unordered_map<uint32_t, Program*> _cachedPrograms; ///< The cached program object. uint64_t computeProgramId(std::string_view vsName, std::string_view fsName);
static ProgramManager* _sharedProgramManager; ///< A shared instance of the program cache.
struct BuiltinRegInfo
{ // builtin shader name is literal string, so use std::string_view ok
std::string_view vsName;
std::string_view fsName;
VertexLayoutType vlt;
};
BuiltinRegInfo _builtinRegistry[(int)backend::ProgramType::BUILTIN_COUNT];
std::unordered_map<int64_t, BuiltinRegInfo> _customRegistry;
std::unordered_map<int64_t, Program*> _cachedPrograms; ///< The cached program object.
XXH64_state_s* _programIdGen;
static ProgramManager* _sharedProgramManager; ///< A shared instance of the program cache.
}; };
using ProgramCache = ProgramManager; // for compatible using ProgramCache = ProgramManager; // for compatible
@ -136,11 +179,12 @@ NS_AX_BACKEND_END
NS_AX_BEGIN NS_AX_BEGIN
using ProgramType = ::ax::backend::ProgramType; using ProgramType = ::ax::backend::ProgramType;
using Program = ::ax::backend::Program; using ProgramState = ::ax::backend::ProgramState;
using VertexLayout = ::ax::backend::VertexLayout; using Program = ::ax::backend::Program;
using VertexLayoutHelper = ::ax::backend::VertexLayoutHelper; using VertexLayout = ::ax::backend::VertexLayout;
using ProgramManager = ::ax::backend::ProgramManager; using VertexLayoutType = ::ax::backend::VertexLayoutType;
using ProgramRegistry = ::ax::backend::ProgramStateRegistry; using ProgramManager = ::ax::backend::ProgramManager;
using ProgramRegistry = ::ax::backend::ProgramStateRegistry;
NS_AX_END NS_AX_END

View File

@ -32,7 +32,6 @@
#include "base/Director.h" #include "base/Director.h"
#include <algorithm> #include <algorithm>
#include "xxhash.h"
#include "glslcc/sgs-spec.h" #include "glslcc/sgs-spec.h"
NS_AX_BACKEND_BEGIN NS_AX_BACKEND_BEGIN
@ -204,9 +203,18 @@ bool ProgramState::init(Program* program)
EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { this->resetUniforms(); }); EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { this->resetUniforms(); });
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1);
#endif #endif
updateBatchId();
return true; return true;
} }
void ProgramState::updateBatchId()
{
_batchId = _program->isBatchEnabled() ? _program->getProgramId()
: static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this));
}
void ProgramState::resetUniforms() void ProgramState::resetUniforms()
{ {
#if AX_ENABLE_CACHE_TEXTURE_DATA #if AX_ENABLE_CACHE_TEXTURE_DATA
@ -257,7 +265,7 @@ ProgramState* ProgramState::clone() const
#ifdef AX_USE_METAL #ifdef AX_USE_METAL
memcpy(cp->_fragmentUniformBuffer, _fragmentUniformBuffer, _fragmentUniformBufferSize); memcpy(cp->_fragmentUniformBuffer, _fragmentUniformBuffer, _fragmentUniformBufferSize);
#endif #endif
cp->_uniformID = _uniformID; cp->_batchId = this->_batchId;
return cp; return cp;
} }
@ -392,8 +400,6 @@ void ProgramState::setVertexUniform(int location, const void* data, std::size_t
assert(location + offset + size <= _vertexUniformBufferSize); assert(location + offset + size <= _vertexUniformBufferSize);
memcpy(_vertexUniformBuffer + location + offset, data, size); memcpy(_vertexUniformBuffer + location + offset, data, size);
#endif #endif
_uniformDirty = true;
} }
void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size) void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size)
@ -426,7 +432,7 @@ void ProgramState::setVertexAttrib(std::string_view name,
{ {
ensureVertexLayoutMutable(); ensureVertexLayoutMutable();
_vertexLayout->setAttribute(name, index, format, offset, needToBeNormallized); _vertexLayout->setAttrib(name, index, format, offset, needToBeNormallized);
} }
void ProgramState::setVertexStride(uint32_t stride) void ProgramState::setVertexStride(uint32_t stride)
@ -435,16 +441,10 @@ void ProgramState::setVertexStride(uint32_t stride)
_vertexLayout->setStride(stride); _vertexLayout->setStride(stride);
} }
void ProgramState::setVertexLayout(const VertexLayout& vertexLayout) void ProgramState::validateSharedVertexLayout(VertexLayoutType vlt)
{
ensureVertexLayoutMutable();
*_vertexLayout = vertexLayout;
}
void ProgramState::validateSharedVertexLayout(std::function<void(Program*)> fnValidate)
{ {
if (!_ownVertexLayout && !_vertexLayout->isValid()) if (!_ownVertexLayout && !_vertexLayout->isValid())
fnValidate(_program); _program->setupVertexLayout(vlt);
} }
void ProgramState::ensureVertexLayoutMutable() void ProgramState::ensureVertexLayoutMutable()
@ -456,22 +456,21 @@ void ProgramState::ensureVertexLayoutMutable()
} }
} }
uint32_t ProgramState::hashOfUniforms() VertexLayout* ProgramState::getMutableVertexLayout()
{ {
if (!_uniformDirty) if (_ownVertexLayout || !_vertexLayout->isValid())
return _uniformID; return _vertexLayout;
_uniformDirty = false; _ownVertexLayout = true;
#ifdef AX_USE_METAL return _vertexLayout = new VertexLayout();
XXH32_reset(_uniformHashState, 0); }
XXH32_update(_uniformHashState, _vertexUniformBuffer, _vertexUniformBufferSize);
XXH32_update(_uniformHashState, _fragmentUniformBuffer, _fragmentUniformBufferSize);
_uniformID = XXH32_digest(_uniformHashState);
#else
_uniformID = XXH32(_vertexUniformBuffer, _vertexUniformBufferSize, 0);
#endif
return _uniformID; void ProgramState::setSharedVertexLayout(VertexLayout* vertexLayout)
{
if (_ownVertexLayout)
delete _vertexLayout;
_ownVertexLayout = false;
_vertexLayout = vertexLayout;
} }
void ProgramState::setTexture(backend::TextureBackend* texture) void ProgramState::setTexture(backend::TextureBackend* texture)

View File

@ -294,32 +294,38 @@ public:
inline const VertexLayout* getVertexLayout() const { return _vertexLayout; } inline const VertexLayout* getVertexLayout() const { return _vertexLayout; }
VertexLayout* getMutableVertexLayout();
/** void setSharedVertexLayout(VertexLayout* vertexLayout);
* Updates uniformID, it's part of materialID for batch draw
* @param uniformID if not -1, will compute with uniform buffer by XXH32 algorithm and should call /*
* this function after any unstable uniforms set * Gets batch id of current program state, part of batch draw materialID
* @remark If your custom shader uniform not stable, you needs call this function to update uniformID for */
* render to generate a different materialID uint64_t getBatchId() const { return _batchId; };
/*
* Update batchID of current program state, by default, custom program was traits with mutable uniforms
* so batch ID was set to address of valid ProgramState object
* If your programState not volatile, you can invoke this API to set with your custom ProgramId prog->getProgramId()
*/
void updateBatchId();
/*
* Follow API is deprecated, use getMutableVertexLayout instead
*/ */
uint32_t hashOfUniforms(); AX_DEPRECATED_ATTRIBUTE void setVertexAttrib(std::string_view name,
std::size_t index,
void setVertexAttrib(std::string_view name, VertexFormat format,
std::size_t index, std::size_t offset,
VertexFormat format, bool needToBeNormallized);
std::size_t offset, AX_DEPRECATED_ATTRIBUTE void setVertexStride(uint32_t stride);
bool needToBeNormallized);
void setVertexStride(uint32_t stride);
void setVertexLayout(const VertexLayout& vertexLayout);
/** Custom shader program's vertex layout maybe not setup /** Custom shader program's vertex layout maybe not setup
* so engine specific render node(such as Sprite) should invoke this API when ProgramState changed * so engine specific render node(such as Sprite) should invoke this API when ProgramState changed
*/ */
void validateSharedVertexLayout(std::function <void(Program*)> fnValidate); void validateSharedVertexLayout(VertexLayoutType);
protected: protected:
void ensureVertexLayoutMutable(); void ensureVertexLayoutMutable();
/** /**
@ -406,13 +412,9 @@ protected:
static std::vector<AutoBindingResolver*> _customAutoBindingResolvers; static std::vector<AutoBindingResolver*> _customAutoBindingResolvers;
VertexLayout* _vertexLayout = nullptr; VertexLayout* _vertexLayout = nullptr;
bool _ownVertexLayout = false; bool _ownVertexLayout = false;
uint32_t _uniformID = 0; uint64_t _batchId = 0;
bool _uniformDirty = false;
#ifdef AX_USE_METAL
struct XXH32_state_s* _uniformHashState = nullptr;
#endif
#if AX_ENABLE_CACHE_TEXTURE_DATA #if AX_ENABLE_CACHE_TEXTURE_DATA
EventListenerCustom* _backToForegroundListener = nullptr; EventListenerCustom* _backToForegroundListener = nullptr;

View File

@ -28,7 +28,7 @@
NS_AX_BACKEND_BEGIN NS_AX_BACKEND_BEGIN
void VertexLayout::setAttribute(std::string_view name, void VertexLayout::setAttrib(std::string_view name,
std::size_t index, std::size_t index,
VertexFormat format, VertexFormat format,
std::size_t offset, std::size_t offset,

View File

@ -63,7 +63,7 @@ public:
bool needToBeNormallized = false; bool needToBeNormallized = false;
}; };
VertexLayout() = default; VertexLayout() = default;
VertexLayout(const VertexLayout&) = default; VertexLayout(const VertexLayout&) = default;
/** /**
@ -75,11 +75,20 @@ public:
* @param needToBeNormallized Specifies whether fixed-point data values should be normalized (true) or converted * @param needToBeNormallized Specifies whether fixed-point data values should be normalized (true) or converted
* directly as fixed-point values (false) when they are accessed. * directly as fixed-point values (false) when they are accessed.
*/ */
void setAttribute(std::string_view name, void setAttrib(std::string_view name,
std::size_t index,
VertexFormat format,
std::size_t offset,
bool needNormalized);
AX_DEPRECATED_ATTRIBUTE void setAttribute(std::string_view name,
std::size_t index, std::size_t index,
VertexFormat format, VertexFormat format,
std::size_t offset, std::size_t offset,
bool needToBeNormallized); bool needNormalized)
{
setAttrib(name, index, format, offset, needNormalized);
}
/** /**
* Set stride of vertices. * Set stride of vertices.

View File

@ -208,8 +208,6 @@ private:
UniformLocation _builtinUniformLocation[UNIFORM_MAX]; UniformLocation _builtinUniformLocation[UNIFORM_MAX];
int _builtinAttributeLocation[Attribute::ATTRIBUTE_MAX]; int _builtinAttributeLocation[Attribute::ATTRIBUTE_MAX];
std::unordered_map<int, int> _bufferOffset; std::unordered_map<int, int> _bufferOffset;
uint32_t _hashOfUniforms = 0;
}; };
// end of _opengl group // end of _opengl group
/// @} /// @}

View File

@ -0,0 +1,43 @@
#ifndef M_PI
#define M_PI 3.141592654
#endif
/*
* transform color with HSV
* @params
* inColor: input color in rgb
* h: hue shift (in degrees)
* s: saturation multiplier (scalar)
* v: value multiplier (scalar)
* @refers
* https://beesbuzz.biz/code/16-hsv-color-transforms
* https://www.shadertoy.com/view/3syyW1
*/
vec3 transformHSV(vec3 inColor, vec3 hsv)
{
float h = hsv.x;
float s = hsv.y;
float v = hsv.z;
float vsu = v * s * cos(h * M_PI / 180.0);
float vsw = v * s * sin(h * M_PI / 180.0);
vec3 outColor = vec3(
(.299 * v + .701 * vsu + .168 * vsw) * inColor.r + (.587 * v - .587 * vsu + .330 * vsw) * inColor.g +
(.114 * v - .114 * vsu - .497 * vsw) * inColor.b,
(.299 * v - .299 * vsu - .328 * vsw) * inColor.r + (.587 * v + .413 * vsu + .035 * vsw) * inColor.g +
(.114 * v - .114 * vsu + .292 * vsw) * inColor.b,
(.299 * v - .300 * vsu + 1.25 * vsw) * inColor.r + (.587 * v - .588 * vsu - 1.05 * vsw) * inColor.g +
(.114 * v + .886 * vsu - .203 * vsw) * inColor.b
);
return outColor;
}
vec3 trasnformYUV(vec3 YUV, mat4 colorTransform)
{
YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w);
return mat3(
colorTransform[0].xyz,
colorTransform[1].xyz,
colorTransform[2].xyz
) * YUV;
}

View File

@ -2,39 +2,18 @@
precision highp float; precision highp float;
precision highp int; precision highp int;
#include "colorUtils.glsl"
layout(location = 0) in vec2 v_texCoord; layout(location = 0) in vec2 v_texCoord;
layout(location = 1) in vec4 v_fragmentColor; layout(location = 1) in vec4 v_fragmentColor;
layout(binding = 0) uniform sampler2D u_tex0; layout(binding = 0) uniform sampler2D u_tex0;
layout(binding = 1) uniform sampler2D u_tex1; layout(binding = 1) uniform sampler2D u_tex1;
// HSV matrix
// filter color RGB values
layout(std140) uniform fs_ub { layout(std140) uniform fs_ub {
mat3 u_mix_hsv; vec3 u_hsv;
vec3 u_filter_rgb;
}; };
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
void main() void main()
@ -42,21 +21,7 @@ void main()
vec4 texColor = vec4(texture(u_tex0, v_texCoord).rgb, texture(u_tex1, v_texCoord).r); vec4 texColor = vec4(texture(u_tex0, v_texCoord).rgb, texture(u_tex1, v_texCoord).r);
texColor.rgb *= texColor.a; // Premultiply with Alpha channel texColor.rgb *= texColor.a; // Premultiply with Alpha channel
vec3 rgbColor = u_mix_hsv * texColor.rgb; texColor.rgb = transformHSV(texColor.rgb, u_hsv);
float sum = texColor.r + texColor.g + texColor.b; FragColor = texColor * v_fragmentColor;
float rv = texColor.r / sum;
float gv = texColor.g / sum;
float bv = texColor.b / sum;
if( (rv < u_filter_rgb.r && gv < u_filter_rgb.g && bv < u_filter_rgb.b) || texColor.a < 0.1)
{ // color filters, resume to original color
rgbColor = texColor.rgb;
rgbColor.r *= v_fragmentColor.a;
rgbColor.g *= v_fragmentColor.a;
rgbColor.b *= v_fragmentColor.a;
}
rgbColor.rgb = rgbColor.rgb * v_fragmentColor.rgb;
FragColor = vec4(rgbColor, texColor.a * v_fragmentColor.a);
} }

View File

@ -2,58 +2,22 @@
precision highp float; precision highp float;
precision highp int; precision highp int;
#include "colorUtils.glsl"
layout(location = 0) in vec2 v_texCoord; layout(location = 0) in vec2 v_texCoord;
layout(location = 1) in vec4 v_fragmentColor; layout(location = 1) in vec4 v_fragmentColor;
layout(binding = 0) uniform sampler2D u_tex0; layout(binding = 0) uniform sampler2D u_tex0;
// HSV matrix
// filter color RGB values
layout(std140) uniform fs_ub { layout(std140) uniform fs_ub {
mat3 u_mix_hsv; vec3 u_hsv;
vec3 u_filter_rgb;
}; };
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
void main() void main()
{ {
vec4 pixColor = texture(u_tex0, v_texCoord); // * v_fragmentColor; vec4 outColor = texture(u_tex0, v_texCoord);
vec3 rgbColor = u_mix_hsv * pixColor.rgb; outColor.rgb = transformHSV(outColor.rgb, u_hsv);
float sum = pixColor.r + pixColor.g + pixColor.b; FragColor = outColor * v_fragmentColor.a;
float rv = pixColor.r / sum;
float gv = pixColor.g / sum;
float bv = pixColor.b / sum;
if( (rv < u_filter_rgb.r && gv < u_filter_rgb.g && bv < u_filter_rgb.b) || pixColor.a < 0.1)
{ // color filters, resume to original color
rgbColor = pixColor.rgb;
rgbColor.r *= v_fragmentColor.a;
rgbColor.g *= v_fragmentColor.a;
rgbColor.b *= v_fragmentColor.a;
}
rgbColor.rgb = rgbColor.rgb * v_fragmentColor.rgb;
FragColor = vec4(rgbColor, pixColor.a * v_fragmentColor.a);
} }

View File

@ -2,6 +2,7 @@
precision highp float; precision highp float;
precision highp int; precision highp int;
#include "colorUtils.glsl"
layout(location = 0) in vec4 v_fragmentColor; layout(location = 0) in vec4 v_fragmentColor;
layout(location = 1) in vec2 v_texCoord; layout(location = 1) in vec2 v_texCoord;
@ -13,16 +14,6 @@ layout(std140) uniform fs_ub {
mat4 colorTransform; mat4 colorTransform;
}; };
vec3 trasnformYUV(vec3 YUV)
{
YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w);
return mat3(
colorTransform[0].xyz,
colorTransform[1].xyz,
colorTransform[2].xyz
) * YUV;
}
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
void main() void main()
@ -34,7 +25,7 @@ void main()
/* Convert YUV to RGB */ /* Convert YUV to RGB */
vec4 OutColor; vec4 OutColor;
OutColor.xyz = trasnformYUV(YUV); OutColor.xyz = trasnformYUV(YUV, colorTransform);
OutColor.w = 1.0; OutColor.w = 1.0;
FragColor = v_fragmentColor * OutColor; FragColor = v_fragmentColor * OutColor;

View File

@ -2,6 +2,7 @@
precision highp float; precision highp float;
precision highp int; precision highp int;
#include "colorUtils.glsl"
layout(location = 0) in vec4 v_fragmentColor; layout(location = 0) in vec4 v_fragmentColor;
layout(location = 1) in vec2 v_texCoord; layout(location = 1) in vec2 v_texCoord;
@ -13,16 +14,6 @@ layout(std140) uniform fs_ub {
mat4 colorTransform; mat4 colorTransform;
}; };
vec3 trasnformYUV(vec3 YUV)
{
YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w);
return mat3(
colorTransform[0].xyz,
colorTransform[1].xyz,
colorTransform[2].xyz
) * YUV;
}
layout(location = 0) out vec4 FragColor; layout(location = 0) out vec4 FragColor;
void main() void main()
@ -35,7 +26,7 @@ void main()
/* Convert YUV to RGB */ /* Convert YUV to RGB */
vec4 OutColor; vec4 OutColor;
OutColor.xyz = trasnformYUV(YUV); OutColor.xyz = trasnformYUV(YUV, colorTransform);
OutColor.w = 1.0; OutColor.w = 1.0;
FragColor = v_fragmentColor * OutColor; FragColor = v_fragmentColor * OutColor;

View File

@ -1491,9 +1491,11 @@ static bool ImGui_ImplAx_CreateDeviceObjects()
static void ImGui_ImplAx_DestroyDeviceObjects() static void ImGui_ImplAx_DestroyDeviceObjects()
{ {
auto pm = ProgramManager::getInstance();
auto bd = ImGui_ImplGlfw_GetBackendData(); auto bd = ImGui_ImplGlfw_GetBackendData();
AX_SAFE_RELEASE_NULL(bd->ProgramInfo.program); pm->unloadProgram(bd->ProgramInfo.program);
AX_SAFE_RELEASE_NULL(bd->ProgramFontInfo.program); pm->unloadProgram(bd->ProgramFontInfo.program);
ImGui_ImplAx_DestroyFontsTexture(); ImGui_ImplAx_DestroyFontsTexture();
} }
@ -1503,26 +1505,14 @@ static bool ImGui_ImplAx_createShaderPrograms()
auto bd = ImGui_ImplGlfw_GetBackendData(); auto bd = ImGui_ImplGlfw_GetBackendData();
enum
{
ImGuiSprite = 0xFF,
ImGuiFont = 0xFE,
};
auto pm = ProgramManager::getInstance(); auto pm = ProgramManager::getInstance();
pm->registerCustomProgram(ImGuiSprite, "custom/imgui_sprite_vs"sv, ax::positionTextureColor_frag);
pm->registerCustomProgram(ImGuiFont, "custom/imgui_sprite_vs"sv, "custom/imgui_font_fs");
AX_SAFE_RELEASE(bd->ProgramInfo.program); bd->ProgramInfo.program = pm->loadProgram("custom/imgui_sprite_vs"sv, ax::positionTextureColor_frag);
AX_SAFE_RELEASE(bd->ProgramFontInfo.program); bd->ProgramFontInfo.program = pm->loadProgram("custom/imgui_sprite_vs"sv, "custom/imgui_font_fs");
bd->ProgramInfo.program = pm->getCustomProgram(ImGuiSprite);
bd->ProgramFontInfo.program = pm->getCustomProgram(ImGuiFont);
IM_ASSERT(bd->ProgramInfo.program); IM_ASSERT(bd->ProgramInfo.program);
IM_ASSERT(bd->ProgramFontInfo.program); IM_ASSERT(bd->ProgramFontInfo.program);
AX_SAFE_RETAIN(bd->ProgramInfo.program);
AX_SAFE_RETAIN(bd->ProgramFontInfo.program);
if (!bd->ProgramInfo.program || !bd->ProgramFontInfo.program) if (!bd->ProgramInfo.program || !bd->ProgramFontInfo.program)
return false; return false;
@ -1727,7 +1717,7 @@ IMGUI_IMPL_API void ImGui_ImplAx_RenderDrawData(ImDrawData* draw_data)
auto& desc = cmd->getPipelineDescriptor(); auto& desc = cmd->getPipelineDescriptor();
desc.programState = state; desc.programState = state;
// setup attributes for ImDrawVert // setup attributes for ImDrawVert
desc.programState->setVertexLayout(pinfo->layout); desc.programState->setSharedVertexLayout(&pinfo->layout);
desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4)); desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4));
desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture()); desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture());
// In order to composite our output buffer we need to preserve alpha // In order to composite our output buffer we need to preserve alpha

View File

@ -703,7 +703,7 @@ IMGUI_IMPL_API void ImGui_ImplAx_RenderDrawData(ImDrawData* draw_data)
auto& desc = cmd->getPipelineDescriptor(); auto& desc = cmd->getPipelineDescriptor();
desc.programState = state; desc.programState = state;
// setup attributes for ImDrawVert // setup attributes for ImDrawVert
desc.programState->setVertexLayout(pinfo->layout); desc.programState->setSharedVertexLayout(&pinfo->layout);
desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4)); desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4));
desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture()); desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture());
// In order to composite our output buffer we need to preserve alpha // In order to composite our output buffer we need to preserve alpha

View File

@ -72,7 +72,7 @@ bool BoneNode::init()
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
auto* program = auto* program =
ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP?
setProgramState(new ax::backend::ProgramState(program), false); setProgramState(new ax::backend::ProgramState(program), true);
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;
_mvpLocation = _programState->getUniformLocation("u_MVPMatrix"sv); _mvpLocation = _programState->getUniformLocation("u_MVPMatrix"sv);

View File

@ -53,7 +53,7 @@ bool SkeletonNode::init()
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
auto* program = auto* program =
ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP?
setProgramState(new ax::backend::ProgramState(program), false); setProgramState(new ax::backend::ProgramState(program), true);
pipelineDescriptor.programState = _programState; pipelineDescriptor.programState = _programState;
_mvpLocation = _programState->getUniformLocation("u_MVPMatrix"); _mvpLocation = _programState->getUniformLocation("u_MVPMatrix");

View File

@ -36,7 +36,9 @@
#include "WidgetReader/NodeReader/NodeReader.h" #include "WidgetReader/NodeReader/NodeReader.h"
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "renderer/Colorizer.h"
#include "renderer/backend/ProgramManager.h"
#include "renderer/backend/ProgramState.h"
USING_NS_AX; USING_NS_AX;
using namespace flatbuffers; using namespace flatbuffers;
@ -326,8 +328,11 @@ void SpriteReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta
auto filter = options->filter(); auto filter = options->filter();
if (hsv != nullptr && filter != nullptr) if (hsv != nullptr && filter != nullptr)
{ {
Colorizer::enableNodeIntelliShading(sprite, Vec3(hsv->x(), hsv->y(), hsv->z()), auto prog = ProgramManager::getInstance()->getBuiltinProgram(ProgramType::HSV);
Vec3(filter->x(), filter->y(), filter->z())); auto ps = new backend::ProgramState(prog);
sprite->setProgramState(ps, true);
Vec3 axhsv{hsv->x(), hsv->y(), hsv->z()};
ps->setUniform(ps->getUniformLocation("u_hsv"), &axhsv, sizeof(axhsv));
} }
} }
} }

View File

@ -21,4 +21,7 @@ endif()
target_include_directories(${target_name} PUBLIC "runtime/include") target_include_directories(${target_name} PUBLIC "runtime/include")
ax_find_shaders(${CMAKE_CURRENT_LIST_DIR}/shaders SPINE_SHADER_SOURCES)
ax_target_compile_shaders(${target_name} FILES ${SPINE_SHADER_SOURCES} CUSTOM)
setup_ax_extension_config(${target_name}) setup_ax_extension_config(${target_name})

View File

@ -89,8 +89,8 @@ namespace spine {
{ {
auto& currentState = command->getPipelineDescriptor().programState; auto& currentState = command->getPipelineDescriptor().programState;
#if defined(AX_VERSION) #if defined(AX_VERSION)
if (currentState == nullptr || currentState->getProgram() != programState->getProgram() || if (currentState == nullptr ||
currentState->hashOfUniforms() != programState->hashOfUniforms()) currentState->getBatchId() != programState->getBatchId())
{ {
#else #else
if(currentState == nullptr || currentState->getProgram() != programState->getProgram()) { if(currentState == nullptr || currentState->getProgram() != programState->getProgram()) {

View File

@ -47,52 +47,8 @@ using std::max;
#define MAX_VERTICES 64000 #define MAX_VERTICES 64000
#define MAX_INDICES 64000 #define MAX_INDICES 64000
#define STRINGIFY(A) #A
namespace { namespace {
const char *TWO_COLOR_TINT_VERTEX_SHADER = STRINGIFY(
uniform mat4 u_PMatrix;
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec4 a_color2;
attribute vec2 a_texCoords;
\n #ifdef GL_ES\n
varying lowp vec4 v_light;
varying lowp vec4 v_dark;
varying mediump vec2 v_texCoord;
\n #else \n
varying vec4 v_light;
varying vec4 v_dark;
varying vec2 v_texCoord;
\n #endif \n
void main() {
v_light = a_color;
v_dark = a_color2;
v_texCoord = a_texCoords;
gl_Position = u_PMatrix * a_position;
});
const char *TWO_COLOR_TINT_FRAGMENT_SHADER = STRINGIFY(
\n #ifdef GL_ES\n
precision lowp float;
\n #endif \n
uniform sampler2D u_texture;
varying vec4 v_light;
varying vec4 v_dark;
varying vec2 v_texCoord;
void main() {
vec4 texColor = texture2D(u_texture, v_texCoord);
float alpha = texColor.a * v_light.a;
gl_FragColor.a = alpha;
gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;
});
std::shared_ptr<backend::ProgramState> __twoColorProgramState = nullptr; std::shared_ptr<backend::ProgramState> __twoColorProgramState = nullptr;
backend::UniformLocation __locPMatrix; backend::UniformLocation __locPMatrix;
backend::UniformLocation __locTexture; backend::UniformLocation __locTexture;
@ -106,21 +62,25 @@ namespace {
auto locColor = programState->getAttributeLocation("a_color"); auto locColor = programState->getAttributeLocation("a_color");
auto locColor2 = programState->getAttributeLocation("a_color2"); auto locColor2 = programState->getAttributeLocation("a_color2");
programState->setVertexAttrib("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(spine::V3F_C4B_C4B_T2F, position), false); auto vertexLayout = programState->getMutableVertexLayout();
programState->setVertexAttrib("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color), true); vertexLayout->setAttrib("a_position", locPosition, backend::VertexFormat::FLOAT3,
programState->setVertexAttrib("a_color2", locColor2, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true); offsetof(spine::V3F_C4B_C4B_T2F, position), false);
programState->setVertexAttrib("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); vertexLayout->setAttrib("a_color", locColor, backend::VertexFormat::UBYTE4,
programState->setVertexStride(sizeof(spine::V3F_C4B_C4B_T2F)); offsetof(spine::V3F_C4B_C4B_T2F, color), true);
vertexLayout->setAttrib("a_color2", locColor2, backend::VertexFormat::UBYTE4,
offsetof(spine::V3F_C4B_C4B_T2F, color2), true);
vertexLayout->setAttrib("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2,
offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false);
vertexLayout->setStride(sizeof(spine::V3F_C4B_C4B_T2F));
} }
static void initTwoColorProgramState() { static void initTwoColorProgramState() {
if (__twoColorProgramState) { if (__twoColorProgramState) {
return; return;
} }
auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); auto program = ProgramManager::getInstance()->loadProgram("custom/spineTwoColorTint_vs",
"custom/spineTwoColorTint_fs");
auto *programState = new backend::ProgramState(program); auto *programState = new backend::ProgramState(program);
program->release();
updateProgramStateLayout(programState); updateProgramStateLayout(programState);
__twoColorProgramState = std::shared_ptr<backend::ProgramState>(programState); __twoColorProgramState = std::shared_ptr<backend::ProgramState>(programState);

View File

@ -0,0 +1,17 @@
#version 310 es
precision highp float;
uniform sampler2D u_texture;
in vec4 v_light;
in vec4 v_dark;
in vec2 v_texCoord;
out vec4 FragColor;
void main() {
vec4 texColor = texture(u_texture, v_texCoord);
float alpha = texColor.a * v_light.a;
FragColor.a = alpha;
FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;
}

View File

@ -0,0 +1,21 @@
#version 310 es
in vec4 a_position;
in vec4 a_color;
in vec4 a_color2;
in vec2 a_texCoords;
out vec4 v_light;
out vec4 v_dark;
out vec2 v_texCoord;
layout(std140) uniform vs_ub {
mat4 u_PMatrix;
};
void main() {
v_light = a_color;
v_dark = a_color2;
v_texCoord = a_texCoords;
gl_Position = u_PMatrix * a_position;
}

View File

@ -221,8 +221,6 @@ list(APPEND GAME_HEADER
Source/SchedulerTest/SchedulerTest.h Source/SchedulerTest/SchedulerTest.h
Source/MultiTouchTest/MultiTouchTest.h Source/MultiTouchTest/MultiTouchTest.h
Source/testResource.h Source/testResource.h
Source/ShaderTest/ShaderTest.vsh.h
Source/ShaderTest/shaderTest.psh.h
Source/ShaderTest/ShaderTest.h Source/ShaderTest/ShaderTest.h
Source/ShaderTest/ShaderTest2.h Source/ShaderTest/ShaderTest2.h
Source/NewRendererTest/NewRendererTest.h Source/NewRendererTest/NewRendererTest.h

View File

@ -1253,12 +1253,9 @@ void FogTestDemo::onEnter()
AX_SAFE_RELEASE_NULL(_programState1); AX_SAFE_RELEASE_NULL(_programState1);
AX_SAFE_RELEASE_NULL(_programState2); AX_SAFE_RELEASE_NULL(_programState2);
auto vertexSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.vert"); auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs");
auto fragSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.frag");
auto program = ProgramManager::newProgram(vertexSource, fragSource);
_programState1 = new backend::ProgramState(program); _programState1 = new backend::ProgramState(program);
_programState2 = new backend::ProgramState(program); _programState2 = new backend::ProgramState(program);
AX_SAFE_RELEASE(program);
_mesh1 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); _mesh1 = MeshRenderer::create("MeshRendererTest/teapot.c3b");
_mesh2 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); _mesh2 = MeshRenderer::create("MeshRendererTest/teapot.c3b");
@ -1303,15 +1300,12 @@ void FogTestDemo::onEnter()
AX_SAFE_RELEASE_NULL(_programState1); AX_SAFE_RELEASE_NULL(_programState1);
AX_SAFE_RELEASE_NULL(_programState2); AX_SAFE_RELEASE_NULL(_programState2);
auto vertexSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.vert"); auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs");
auto fragSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.frag");
auto program = ProgramManager::newProgram(vertexSource, fragSource);
_programState1 = new backend::ProgramState(program); _programState1 = new backend::ProgramState(program);
_programState2 = new backend::ProgramState(program); _programState2 = new backend::ProgramState(program);
_mesh1->setProgramState(_programState1); _mesh1->setProgramState(_programState1);
_mesh2->setProgramState(_programState2); _mesh2->setProgramState(_programState2);
AX_SAFE_RELEASE(program);
auto fogColor = Vec4(0.5, 0.5, 0.5, 1.0); auto fogColor = Vec4(0.5, 0.5, 0.5, 1.0);
float fogStart = 10; float fogStart = 10;

View File

@ -31,11 +31,8 @@
namespace namespace
{ {
enum CustomProgramType : uint32_t static uint64_t s_blur_program_id = 0;
{ static uint64_t s_sepia_program_id = 0;
BLUR = 1,
SEPIA = 2,
};
} }
USING_NS_AX; USING_NS_AX;
@ -74,14 +71,13 @@ private:
NewRendererTests::NewRendererTests() NewRendererTests::NewRendererTests()
{ {
auto programManager = ProgramManager::getInstance(); auto programManager = ProgramManager::getInstance();
programManager->registerCustomProgram(CustomProgramType::BLUR, positionTextureColor_vert, s_blur_program_id = programManager->registerCustomProgram(positionTextureColor_vert,
"example_Blur_fs"sv, "custom/example_Blur_fs"sv,
VertexLayoutHelper::setupSprite); VertexLayoutType::Sprite);
programManager->registerCustomProgram( s_sepia_program_id = programManager->registerCustomProgram(positionTextureColor_vert,
CustomProgramType::SEPIA, positionTextureColor_vert, "custom/example_Sepia_fs"sv,
"example_Sepia_fs"sv, VertexLayoutType::Sprite);
VertexLayoutHelper::setupSprite);
ADD_TEST_CASE(NewSpriteTest); ADD_TEST_CASE(NewSpriteTest);
ADD_TEST_CASE(GroupCommandTest); ADD_TEST_CASE(GroupCommandTest);
@ -857,7 +853,7 @@ RendererUniformBatch::RendererUniformBatch()
ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState() ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState()
{ {
auto programState = auto programState =
new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::BLUR)); new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id));
programState->autorelease(); programState->autorelease();
backend::UniformLocation loc = programState->getUniformLocation("resolution"); backend::UniformLocation loc = programState->getUniformLocation("resolution");
@ -877,11 +873,7 @@ ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState()
ax::backend::ProgramState* RendererUniformBatch::createSepiaProgramState() ax::backend::ProgramState* RendererUniformBatch::createSepiaProgramState()
{ {
auto programState = auto programState = new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id));
new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::SEPIA));
// programState->hashOfUniforms();
programState->autorelease(); programState->autorelease();
return programState; return programState;
} }
@ -931,7 +923,7 @@ RendererUniformBatch2::RendererUniformBatch2()
backend::ProgramState* RendererUniformBatch2::createBlurProgramState() backend::ProgramState* RendererUniformBatch2::createBlurProgramState()
{ {
auto programState = auto programState =
new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::BLUR)); new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id));
backend::UniformLocation loc = programState->getUniformLocation("resolution"); backend::UniformLocation loc = programState->getUniformLocation("resolution");
auto resolution = Vec2(85, 121); auto resolution = Vec2(85, 121);
@ -951,7 +943,7 @@ backend::ProgramState* RendererUniformBatch2::createBlurProgramState()
backend::ProgramState* RendererUniformBatch2::createSepiaProgramState() backend::ProgramState* RendererUniformBatch2::createSepiaProgramState()
{ {
auto programState = auto programState =
new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::SEPIA)); new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id));
programState->autorelease(); programState->autorelease();
return programState; return programState;
} }

View File

@ -943,19 +943,19 @@ public:
sprite->autorelease(); sprite->autorelease();
auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
sprite->setProgramState(programState, false); sprite->setProgramState(programState, true);
return sprite; return sprite;
} }
bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override;
virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override;
protected: protected:
CustomCommand _customCommand; CustomCommand _customCommand;
}; };
bool MySprite::setProgramState(backend::ProgramState* programState, bool needsRetain) bool MySprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/)
{ {
if (Sprite::setProgramState(programState, needsRetain)) if (Sprite::setProgramState(programState, ownPS))
{ {
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
pipelineDescriptor.programState = programState; pipelineDescriptor.programState = programState;

View File

@ -88,6 +88,8 @@ ShaderNode* ShaderNode::shaderNodeWithVertex(std::string_view vert, std::string_
bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag)
{ {
if (vert.empty())
vert = position_vert;
_vertFileName = vert; _vertFileName = vert;
_fragFileName = frag; _fragFileName = frag;
@ -103,11 +105,13 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag)
// init custom command // init custom command
auto attrPosLoc = _programState->getAttributeLocation("a_position"); auto attrPosLoc = _programState->getAttributeLocation("a_position");
_programState->setVertexAttrib("a_position", attrPosLoc, backend::VertexFormat::FLOAT2, 0, false);
auto vertexLayout = _programState->getMutableVertexLayout();
vertexLayout->setAttrib("a_position", attrPosLoc, backend::VertexFormat::FLOAT2, 0, false);
float w = SIZE_X, h = SIZE_Y; float w = SIZE_X, h = SIZE_Y;
Vec2 vertices[6] = {Vec2(0.0f, 0.0f), Vec2(w, 0.0f), Vec2(w, h), Vec2(0.0f, 0.0f), Vec2(0.0f, h), Vec2(w, h)}; Vec2 vertices[6] = {Vec2(0.0f, 0.0f), Vec2(w, 0.0f), Vec2(w, h), Vec2(0.0f, 0.0f), Vec2(0.0f, h), Vec2(w, h)};
_programState->setVertexStride(sizeof(Vec2)); vertexLayout->setStride(sizeof(Vec2));
/* /*
* TODO: the Y-coordinate of subclasses are flipped in metal * TODO: the Y-coordinate of subclasses are flipped in metal
@ -125,28 +129,10 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag)
void ShaderNode::loadShaderVertex(std::string_view vert, std::string_view frag) void ShaderNode::loadShaderVertex(std::string_view vert, std::string_view frag)
{ {
auto fileUtiles = FileUtils::getInstance(); auto program = ProgramManager::getInstance()->loadProgram(vert, frag, VertexLayoutType::Sprite);
// frag
auto fragmentFilePath = fileUtiles->fullPathForFilename(frag);
auto fragSource = fileUtiles->getStringFromFile(fragmentFilePath);
// vert
std::string vertSource;
if (vert.empty())
{
vertSource = position_vert;
}
else
{
std::string vertexFilePath = fileUtiles->fullPathForFilename(vert);
vertSource = fileUtiles->getStringFromFile(vertexFilePath);
}
auto program = ProgramManager::newProgram(vertSource, fragSource, VertexLayoutHelper::setupSprite);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
setProgramState(programState); setProgramState(programState);
AX_SAFE_RELEASE(programState); AX_SAFE_RELEASE(programState);
AX_SAFE_RELEASE(program);
} }
void ShaderNode::update(float dt) void ShaderNode::update(float dt)
@ -217,7 +203,7 @@ bool ShaderMonjori::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Monjori.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Monjori_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -247,7 +233,7 @@ bool ShaderMandelbrot::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Mandelbrot.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Mandelbrot_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -276,7 +262,7 @@ bool ShaderJulia::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Julia.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Julia_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -305,7 +291,7 @@ bool ShaderHeart::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Heart.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Heart_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -335,7 +321,7 @@ bool ShaderFlower::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Flower.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Flower_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -365,7 +351,7 @@ bool ShaderPlasma::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Plasma.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Plasma_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -448,14 +434,10 @@ bool SpriteBlur::initWithTexture(Texture2D* texture, const Rect& rect)
void SpriteBlur::initProgram() void SpriteBlur::initProgram()
{ {
std::string fragSource = FileUtils::getInstance()->getStringFromFile( auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs", VertexLayoutType::Sprite);
FileUtils::getInstance()->fullPathForFilename("Shaders/example_Blur.fsh"));
auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
setProgramState(programState); setProgramState(programState);
AX_SAFE_RELEASE(programState); AX_SAFE_RELEASE(programState);
AX_SAFE_RELEASE(program);
auto size = getTexture()->getContentSizeInPixels(); auto size = getTexture()->getContentSizeInPixels();
@ -581,10 +563,10 @@ bool ShaderRetroEffect::init()
{ {
auto fragStr = FileUtils::getInstance()->getStringFromFile( auto fragStr = FileUtils::getInstance()->getStringFromFile(
FileUtils::getInstance()->fullPathForFilename("Shaders/example_HorizontalColor.fsh")); FileUtils::getInstance()->fullPathForFilename("custom/example_HorizontalColor_fs"));
char* fragSource = (char*)fragStr.c_str(); char* fragSource = (char*)fragStr.c_str();
auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite); auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_HorizontalColor_fs", VertexLayoutType::Sprite);
auto p = new backend::ProgramState(program); auto p = new backend::ProgramState(program);
auto director = Director::getInstance(); auto director = Director::getInstance();
const auto& screenSizeLocation = p->getUniformLocation("u_screenSize"); const auto& screenSizeLocation = p->getUniformLocation("u_screenSize");
@ -605,7 +587,6 @@ bool ShaderRetroEffect::init()
addChild(_label); addChild(_label);
scheduleUpdate(); scheduleUpdate();
AX_SAFE_RELEASE(program);
return true; return true;
} }
@ -658,7 +639,7 @@ bool ShaderLensFlare::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/shadertoy_LensFlare.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/shadertoy_LensFlare_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -690,7 +671,7 @@ bool ShaderGlow::init()
{ {
if (ShaderTestDemo::init()) if (ShaderTestDemo::init())
{ {
auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/shadertoy_Glow.fsh"); auto sn = ShaderNode::shaderNodeWithVertex("", "custom/shadertoy_Glow_fs");
auto s = Director::getInstance()->getWinSize(); auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2)); sn->setPosition(Vec2(s.width / 2, s.height / 2));
@ -764,10 +745,7 @@ bool ShaderMultiTexture::init()
addChild(_sprite); addChild(_sprite);
_sprite->setPosition(Vec2(s.width / 2, s.height / 2)); _sprite->setPosition(Vec2(s.width / 2, s.height / 2));
auto* fu = FileUtils::getInstance(); auto program = ProgramManager::getInstance()->loadProgram("custom/example_MultiTexture_vs", "custom/example_MultiTexture_fs", VertexLayoutType::Sprite);
auto vertexShader = fu->getStringFromFile("Shaders/example_MultiTexture.vsh");
auto fragmentShader = fu->getStringFromFile("Shaders/example_MultiTexture.fsh");
auto program = ProgramManager::newProgram(vertexShader, fragmentShader, VertexLayoutHelper::setupSprite);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
_sprite->setProgramState(programState); _sprite->setProgramState(programState);
@ -785,7 +763,6 @@ bool ShaderMultiTexture::init()
menu->setPosition(s.width * 7 / 8, s.height / 2); menu->setPosition(s.width * 7 / 8, s.height / 2);
AX_SAFE_RELEASE(programState); AX_SAFE_RELEASE(programState);
AX_SAFE_RELEASE(program);
return true; return true;
} }

View File

@ -153,9 +153,9 @@ protected:
bool initWithVertex(std::string_view vert, std::string_view frag); bool initWithVertex(std::string_view vert, std::string_view frag);
void loadShaderVertex(std::string_view vert, std::string_view frag); void loadShaderVertex(std::string_view vert, std::string_view frag);
virtual bool setProgramState(ax::backend::ProgramState* programState, bool needsRetain = true) override virtual bool setProgramState(ax::backend::ProgramState* programState, bool ownPS = false) override
{ {
if (Node::setProgramState(programState, needsRetain)) if (Node::setProgramState(programState, ownPS))
{ {
_customCommand.getPipelineDescriptor().programState = programState; _customCommand.getPipelineDescriptor().programState = programState;
updateUniforms(); updateUniforms();

View File

@ -1,32 +0,0 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://axmolengine.github.io/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#define STRINGIFY(A) #A
static const char* shadertestvsh = STRINGIFY(
attribute vec4 a_position;
void main() { gl_Position = AX_MVPMatrix * a_position; }
);

View File

@ -183,17 +183,9 @@ protected:
bool Effect::initProgramState(std::string_view fragmentFilename) bool Effect::initProgramState(std::string_view fragmentFilename)
{ {
auto fileUtiles = FileUtils::getInstance(); auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, fragmentFilename, VertexLayoutType::Sprite);
auto fragmentFullPath = fileUtiles->fullPathForFilename(fragmentFilename);
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID)
_fragSource = fragSource;
#endif
auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite);
auto programState = new backend::ProgramState(program); auto programState = new backend::ProgramState(program);
AX_SAFE_RELEASE(_programState); AX_SAFE_RELEASE(_programState);
AX_SAFE_RELEASE(program);
_programState = programState; _programState = programState;
return _programState != nullptr; return _programState != nullptr;
@ -235,7 +227,7 @@ void EffectBlur::setTarget(EffectSprite* sprite)
bool EffectBlur::init(float blurRadius, float sampleNum) bool EffectBlur::init(float blurRadius, float sampleNum)
{ {
initProgramState("Shaders/example_Blur.fsh"); initProgramState("custom/example_Blur_fs");
_blurRadius = blurRadius; _blurRadius = blurRadius;
_blurSampleNum = sampleNum; _blurSampleNum = sampleNum;
@ -260,7 +252,7 @@ public:
bool init() bool init()
{ {
initProgramState("Shaders/example_Outline.fsh"); initProgramState("custom/example_Outline_fs");
Vec3 color(1.0f, 0.2f, 0.3f); Vec3 color(1.0f, 0.2f, 0.3f);
float radius = 0.01f; float radius = 0.01f;
@ -282,7 +274,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_Noisy.fsh"); initProgramState("custom/example_Noisy_fs");
return true; return true;
} }
@ -302,7 +294,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_EdgeDetection.fsh"); initProgramState("custom/example_EdgeDetection_fs");
return true; return true;
} }
@ -322,7 +314,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_GreyScale.fsh"); initProgramState("custom/example_GreyScale_fs");
return true; return true;
} }
}; };
@ -336,7 +328,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_Sepia.fsh"); initProgramState("custom/example_Sepia_fs");
return true; return true;
} }
}; };
@ -350,7 +342,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_Bloom.fsh"); initProgramState("custom/example_Bloom_fs");
return true; return true;
} }
@ -370,7 +362,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_CelShading.fsh"); initProgramState("custom/example_CelShading_fs");
return true; return true;
} }
@ -390,7 +382,7 @@ public:
protected: protected:
bool init() bool init()
{ {
initProgramState("Shaders/example_LensFlare.fsh"); initProgramState("custom/example_LensFlare_fs");
return true; return true;
} }
@ -436,7 +428,7 @@ protected:
bool EffectNormalMapped::init() bool EffectNormalMapped::init()
{ {
initProgramState("Shaders3D/Normal.frag"); initProgramState("custom/Normal_fs");
_kBump = 2; _kBump = 2;
return true; return true;
} }

View File

@ -1,437 +0,0 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://axmolengine.github.io/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#define STRINGIFY(A) #A
static const char* starFlame = STRINGIFY(
uniform vec2 center; uniform vec2 resolution;
vec2 iResolution = resolution; // viewport resolution (in pixels)
float iGlobalTime = AX_Time[1]; // shader playback time (in seconds)
// uniform float iChannelTime[4]; // channel playback time (in seconds)
// uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click
// uniform sampler2D iChannel0; // input channel. XX = 2D/Cube
float noise(vec3 p) // Thx to Las^Mercury
{
vec3 i = floor(p);
vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.);
vec3 f = cos((p - i) * acos(-1.)) * (-.5) + .5;
a = mix(sin(cos(a) * a), sin(cos(1. + a) * (1. + a)), f.x);
a.xy = mix(a.xz, a.yw, f.y);
return mix(a.x, a.y, f.z);
}
float sphere(vec3 p, vec4 spr) { return length(spr.xyz - p) - spr.w; }
float flame(vec3 p) {
float d = sphere(p * vec3(1., .5, 1.), vec4(.0, -1., .0, 1.));
return d + (noise(p + vec3(.0, iGlobalTime * 2., .0)) + noise(p * 3.) * .5) * .25 * (p.y);
}
float scene(vec3 p) { return min(100. - length(p), abs(flame(p))); }
vec4 raymarch(vec3 org, vec3 dir) {
float d = 0.0;
float glow = 0.0;
float eps = 0.02;
vec3 p = org;
bool glowed = false;
for (int i = 0; i < 64; i++)
{
d = scene(p) + eps;
p += d * dir;
if (d > eps)
{
if (flame(p) < .0)
glowed = true;
if (glowed)
glow = float(i) / 64.;
}
}
return vec4(p, glow);
}
void main() {
vec2 v = -1.0 + (2.0 * gl_FragCoord.xy) / iResolution.xy;
// vec2 v = 2.0 * gl_FragCoord.xy / iResolution.xy;
v.x *= iResolution.x / iResolution.y;
vec3 org = vec3(0., -2., 4.);
vec3 dir = normalize(vec3(v.x * 1.6, -v.y, -1.5));
vec4 p = raymarch(org, dir);
float glow = p.w;
vec4 col = mix(vec4(1., .5, .1, 1.), vec4(0.1, .5, 1., 1.), p.y * .02 + .4);
gl_FragColor = mix(vec4(0.), col, pow(glow * 2., 4.));
// gl_FragColor = col;
// gl_FragColor = mix(vec4(1.), mix(vec4(1.,.5,.1,1.),vec4(0.1,.5,1.,1.),p.y*.02+.4), pow(glow*2.,4.));
}
);
static const char* starNestFrg = STRINGIFY(
uniform vec2 center; uniform vec2 resolution;
vec2 iCenter = center;
vec2 iResolution = resolution; // viewport resolution (in pixels)
float iGlobalTime = AX_Time[1]; // shader playback time (in seconds)
// uniform float iChannelTime[4]; // channel playback time (in seconds)
// uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click
// uniform sampler2D iChannel0; // input channel. XX = 2D/Cube
// Star Nest by Pablo Román Andrioli
// This content is under the MIT License.
int iterations = 17;
float formuparam = 0.53;
int volsteps = 20;
float stepsize = 0.1;
float zoom = 0.800;
float tile = 0.850;
float speed = 0.010;
float brightness = 0.0015;
float darkmatter = 0.300;
float distfading = 0.730;
float saturation = 0.850;
void main() {
// iCenter = vec2(300, 300);
// get coords and direction
vec2 uv = gl_FragCoord.xy / iResolution.xy - .5;
// vec2 uv=gl_FragCoord.xy/iResolution.xy ;
// vec2 uv = ( 2* gl_FragCoord.xy - iCenter.xy) / resolution.xy;
uv.y *= iResolution.y / iResolution.x;
// vec2 uv = 2.0* (gl_FragCoord.xy-iResolution.xy)/min(iResolution.y,iResolution.x);
vec3 dir = vec3(uv * zoom, 1.);
float time = iGlobalTime * speed + .25;
// mouse rotation
float a1 = .5 + iMouse.x / iResolution.x * 2.;
float a2 = .8 + iMouse.y / iResolution.y * 2.;
mat2 rot1 = mat2(cos(a1), sin(a1), -sin(a1), cos(a1));
mat2 rot2 = mat2(cos(a2), sin(a2), -sin(a2), cos(a2));
dir.xz *= rot1;
dir.xy *= rot2;
vec3 from = vec3(1., .5, 0.5);
from += vec3(time * 2., time, -2.);
from.xz *= rot1;
from.xy *= rot2;
// volumetric rendering
float s = 0.1;
float fade = 1.;
vec3 v = vec3(0.);
for (int r = 0; r < volsteps; r++)
{
vec3 p = from + s * dir * .5;
p = abs(vec3(tile) - mod(p, vec3(tile * 2.))); // tiling fold
float a = 0.;
float pa = 0.;
for (int i = 0; i < iterations; i++)
{
p = abs(p) / dot(p, p) - formuparam; // the magic formula
a += abs(length(p) - pa); // absolute sum of average change
pa = length(p);
}
float dm = max(0., darkmatter - a * a * .001); // dark matter
a *= a * a; // add contrast
if (r > 6)
fade *= 1. - dm; // dark matter, don't render near
// v+=vec3(dm,dm*.5,0.);
v += fade;
v += vec3(s, s * s, s * s * s * s) * a * brightness * fade; // coloring based on distance
fade *= distfading; // distance fading
s += stepsize;
}
v = mix(vec3(length(v)), v, saturation); // color adjust
gl_FragColor = vec4(v * .01, 1.);
});
static const char* shadertoyRelentlessFrag = STRINGIFY(
uniform vec2 center; uniform vec2 resolution;
vec2 iCenter = center;
vec2 iResolution = resolution; // viewport resolution (in pixels)
float iGlobalTime = AX_Time[1]; // shader playback time (in seconds)
// uniform float iChannelTime[4]; // channel playback time (in seconds)
// uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click
// uniform sampler2D iChannel0; // input channel. XX = 2D/Cube
// srtuss, 2013
// collecting some design ideas for a new game project.
// no raymarching is used.
// if i could add a custom soundtrack, it'd use this one (essential for desired sensation)
// http://www.youtube.com/watch?v=1uFAu65tZpo
//#define GREEN_VERSION
// ** improved camera shaking
// ** cleaned up code
// ** added stuff to the gates
float time = iGlobalTime;
vec2 rotate(vec2 p, float a) {
return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
} float box(vec2 p, vec2 b, float r) { return length(max(abs(p) - b, 0.0)) - r; }
// iq's ray-plane-intersection code
vec3 intersect(in vec3 o, in vec3 d, vec3 c, vec3 u, vec3 v) {
vec3 q = o - c;
return vec3(dot(cross(u, v), q), dot(cross(q, u), d), dot(cross(v, q), d)) / dot(cross(v, u), d);
}
// some noise functions for fast developing
float rand11(float p) { return fract(sin(p * 591.32) * 43758.5357); }
float rand12(vec2 p) { return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5357); }
vec2 rand21(float p) { return fract(vec2(sin(p * 591.32), cos(p * 391.32))); }
vec2 rand22(in vec2 p) { return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077))); }
float noise11(float p) {
float fl = floor(p);
return mix(rand11(fl), rand11(fl + 1.0), fract(p)); // smoothstep(0.0, 1.0, fract(p)));
}
float fbm11(float p) { return noise11(p) * 0.5 + noise11(p * 2.0) * 0.25 + noise11(p * 5.0) * 0.125; }
vec3 noise31(float p) { return vec3(noise11(p), noise11(p + 18.952), noise11(p - 11.372)) * 2.0 - 1.0; }
// something that looks a bit like godrays coming from the surface
float sky(vec3 p) {
float a = atan(p.x, p.z);
float t = time * 0.1;
float v =
rand11(floor(a * 4.0 + t)) * 0.5 + rand11(floor(a * 8.0 - t)) * 0.25 + rand11(floor(a * 16.0 + t)) * 0.125;
return v;
}
vec3 voronoi(in vec2 x) {
vec2 n = floor(x); // grid cell id
vec2 f = fract(x); // grid internal position
vec2 mg; // shortest distance...
vec2 mr; // ..and second shortest distance
float md = 8.0;
float md2 = 8.0;
for (int j = -1; j <= 1; j++)
{
for (int i = -1; i <= 1; i++)
{
vec2 g = vec2(float(i), float(j)); // cell id
vec2 o = rand22(n + g); // offset to edge point
vec2 r = g + o - f;
float d = max(abs(r.x), abs(r.y)); // distance to the edge
if (d < md)
{
md2 = md;
md = d;
mr = r;
mg = g;
}
else if (d < md2)
{
md2 = d;
}
}
}
return vec3(n + mg, md2 - md);
}
//#define A2V(a) vec2(sin((a) * 6.28318531 / 100.0), cos((a) * 6.28318531 / 100.0))
vec2 A2V(float a) { return vec2(sin((a)*6.28318531 / 100.0), cos((a)*6.28318531 / 100.0)); }
float circles(vec2 p) {
float v;
float w;
float l;
float c;
vec2 pp;
l = length(p);
pp = rotate(p, time * 3.0);
c = max(dot(pp, normalize(vec2(-0.2, 0.5))), -dot(pp, normalize(vec2(0.2, 0.5))));
c = min(c, max(dot(pp, normalize(vec2(0.5, -0.5))), -dot(pp, normalize(vec2(0.2, -0.5)))));
c = min(c, max(dot(pp, normalize(vec2(0.3, 0.5))), -dot(pp, normalize(vec2(0.2, 0.5)))));
// innerest stuff
v = abs(l - 0.5) - 0.03;
v = max(v, -c);
v = min(v, abs(l - 0.54) - 0.02);
v = min(v, abs(l - 0.64) - 0.05);
pp = rotate(p, time * -1.333);
c = max(dot(pp, A2V(-5.0)), -dot(pp, A2V(5.0)));
c = min(c, max(dot(pp, A2V(25.0 - 5.0)), -dot(pp, A2V(25.0 + 5.0))));
c = min(c, max(dot(pp, A2V(50.0 - 5.0)), -dot(pp, A2V(50.0 + 5.0))));
c = min(c, max(dot(pp, A2V(75.0 - 5.0)), -dot(pp, A2V(75.0 + 5.0))));
w = abs(l - 0.83) - 0.09;
v = min(v, max(w, c));
return v;
}
float shade1(float d) {
float v = 1.0 - smoothstep(0.0, mix(0.012, 0.2, 0.0), d);
float g = exp(d * -20.0);
return v + g * 0.5;
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
uv = uv * 2.0 - 1.0;
uv.x *= iResolution.x / iResolution.y;
// using an iq styled camera this time :)
// ray origin
vec3 ro = 0.7 * vec3(cos(0.2 * time), 0.0, sin(0.2 * time));
ro.y = cos(0.6 * time) * 0.3 + 0.65;
// camera look at
vec3 ta = vec3(0.0, 0.2, 0.0);
// camera shake intensity
float shake = clamp(3.0 * (1.0 - length(ro.yz)), 0.3, 1.0);
float st = mod(time, 10.0) * 143.0;
// build camera matrix
vec3 ww = normalize(ta - ro + noise31(st) * shake * 0.01);
vec3 uu = normalize(cross(ww, normalize(vec3(0.0, 1.0, 0.2 * sin(time)))));
vec3 vv = normalize(cross(uu, ww));
// obtain ray direction
vec3 rd = normalize(uv.x * uu + uv.y * vv + 1.0 * ww);
// shaking and movement
ro += noise31(-st) * shake * 0.015;
ro.x += time * 2.0;
float inten = 0.0;
// background
float sd = dot(rd, vec3(0.0, 1.0, 0.0));
inten = pow(1.0 - abs(sd), 20.0) + pow(sky(rd), 5.0) * step(0.0, rd.y) * 0.2;
vec3 its;
float v;
float g;
// voronoi floor layers
for (int i = 0; i < 4; i++)
{
float layer = float(i);
its = intersect(ro, rd, vec3(0.0, -5.0 - layer * 5.0, 0.0), vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0));
if (its.x > 0.0)
{
vec3 vo = voronoi((its.yz) * 0.05 + 8.0 * rand21(float(i)));
v = exp(-100.0 * (vo.z - 0.02));
float fx = 0.0;
// add some special fx to lowest layer
if (i == 3)
{
float crd = 0.0; // fract(time * 0.2) * 50.0 - 25.0;
float fxi = cos(vo.x * 0.2 + time * 1.5); // abs(crd - vo.x);
fx = clamp(smoothstep(0.9, 1.0, fxi), 0.0, 0.9) * 1.0 * rand12(vo.xy);
fx *= exp(-3.0 * vo.z) * 2.0;
}
inten += v * 0.1 + fx;
}
}
// draw the gates, 4 should be enough
float gatex = floor(ro.x / 8.0 + 0.5) * 8.0 + 4.0;
float go = -16.0;
for (int i = 0; i < 4; i++)
{
its = intersect(ro, rd, vec3(gatex + go, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
if (dot(its.yz, its.yz) < 2.0 && its.x > 0.0)
{
v = circles(its.yz);
inten += shade1(v);
}
go += 8.0;
}
// draw the stream
for (int j = 0; j < 20; j++)
{
float id = float(j);
vec3 bp = vec3(0.0, (rand11(id) * 2.0 - 1.0) * 0.25, 0.0);
vec3 its = intersect(ro, rd, bp, vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0));
if (its.x > 0.0)
{
vec2 pp = its.yz;
float spd = (1.0 + rand11(id) * 3.0) * 2.5;
pp.y += time * spd;
pp += (rand21(id) * 2.0 - 1.0) * vec2(0.3, 1.0);
float rep = rand11(id) + 1.5;
pp.y = mod(pp.y, rep * 2.0) - rep;
float d = box(pp, vec2(0.02, 0.3), 0.1);
float foc = 0.0;
float v = 1.0 - smoothstep(0.0, 0.03, abs(d) - 0.001);
float g = min(exp(d * -20.0), 2.0);
inten += (v + g * 0.7) * 0.5;
}
}
inten *= 0.4 + (sin(time) * 0.5 + 0.5) * 0.6;
// find a color for the computed intensity
#ifdef GREEN_VERSION
vec3 col = pow(vec3(inten), vec3(2.0, 0.15, 9.0));
#else
vec3 col = pow(vec3(inten), 1.5 * vec3(0.15, 2.0, 9.0));
#endif
gl_FragColor = vec4(col, 1.0);
}
);

View File

@ -28,7 +28,6 @@
#include <fstream> #include <fstream>
#include <string.h> #include <string.h>
#include "spine/spine.h" #include "spine/spine.h"
#include "renderer/Colorizer.h"
USING_NS_AX; USING_NS_AX;
using namespace std; using namespace std;
@ -146,7 +145,6 @@ bool SpineTestLayer::init()
SET_UNIFORM(skeleton1PS, "resolution", resolution); SET_UNIFORM(skeleton1PS, "resolution", resolution);
SET_UNIFORM(skeleton1PS, "blurRadius", blurRadius); SET_UNIFORM(skeleton1PS, "blurRadius", blurRadius);
SET_UNIFORM(skeleton1PS, "sampleNum", sampleNum); SET_UNIFORM(skeleton1PS, "sampleNum", sampleNum);
skeleton1PS->hashOfUniforms();
} }
} }
@ -364,7 +362,11 @@ bool MixAndMatchExample::init()
SCALE_SKELETON_NODE(skeletonNode); SCALE_SKELETON_NODE(skeletonNode);
Colorizer::enableNodeIntelliShading(skeletonNode, Vec3(92.0f, 1.0f, 1.2f), Vec3::ZERO); // load hsv as custom, we don't want batch draw
auto hsvProg = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, hsv_frag);
auto ps1 = new backend::ProgramState(hsvProg);
SET_UNIFORM(ps1, "u_hsv", Vec3(92.0f, 1.0f, 1.2f));
skeletonNode->setProgramState(ps1, true);
/* -------- skeletonNode2 with same spine animation file ------------ */ /* -------- skeletonNode2 with same spine animation file ------------ */
auto skeletonNode2 = SkeletonAnimation::createWithBinaryFile("mix-and-match-pro.skel", "mix-and-match.atlas", 0.5); auto skeletonNode2 = SkeletonAnimation::createWithBinaryFile("mix-and-match-pro.skel", "mix-and-match.atlas", 0.5);
@ -392,7 +394,9 @@ bool MixAndMatchExample::init()
SCALE_SKELETON_NODE(skeletonNode2); SCALE_SKELETON_NODE(skeletonNode2);
Colorizer::enableNodeIntelliShading(skeletonNode2, Vec3(45.0f, 1.0f, 1.2f), Vec3::ZERO); auto ps2 = new backend::ProgramState(hsvProg);
SET_UNIFORM(ps2, "u_hsv", Vec3(-45.0f, 1.0f, 1.2f));
skeletonNode2->setProgramState(ps2, true);
return true; return true;
} }
@ -516,11 +520,9 @@ bool SpineboyExample::init()
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20)); skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
addChild(skeletonNode); addChild(skeletonNode);
auto programCache = backend::ProgramCache::getInstance(); auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs",
programCache->registerCustomProgram(101, positionTextureColor_vert, VertexLayoutType::Sprite);
FileUtils::getInstance()->getStringFromFile("Shaders/example_Blur.fsh"), VertexLayoutHelper::setupSprite); skeletonNode->setProgramState(new backend::ProgramState(program), true);
auto program = programCache->getCustomProgram(101);
skeletonNode->setProgramState(new backend::ProgramState(program), false);
//auto skeleton1PS = skeletonNode->getProgramState(); //auto skeleton1PS = skeletonNode->getProgramState();

View File

@ -722,13 +722,9 @@ function FogTestDemo:createLayer3D()
self:addChild(layer3D,0) self:addChild(layer3D,0)
self._layer3D = layer3D self._layer3D = layer3D
local vertexShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/fog.vert") local program = axb.ProgramManager:getInstance():loadProgram('custom/fog_vs', 'custom/fog_fs')
local fragmentShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/fog.frag")
local program = ccb.Device:getInstance():newProgram(vertexShader, fragmentShader)
self._shader1 = ccb.ProgramState:new(program) self._shader1 = ccb.ProgramState:new(program)
self._shader2 = self._shader1:clone() self._shader2 = self._shader1:clone()
program:release()
self._sprite3D1 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") self._sprite3D1 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b")
self._sprite3D2 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") self._sprite3D2 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b")

View File

@ -312,11 +312,8 @@ function Scene3DTest:create3DWorld()
--then, create skybox --then, create skybox
--create and set our custom shader --create and set our custom shader
local cmVert = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.vert") local program = axb.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs')
local cmFrag = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.frag")
local program = ccb.Device:getInstance():newProgram(cmVert, cmFrag)
local state = ccb.ProgramState:new(program) local state = ccb.ProgramState:new(program)
program:release()
--create the second texture for cylinder --create the second texture for cylinder
self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg",
"MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg",

View File

@ -1123,11 +1123,8 @@ function Sprite3DCubeMapTest:addNewSpriteWithCoords(pos)
--create a teapot --create a teapot
self._teapot = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") self._teapot = cc.Sprite3D:create("MeshRendererTest/teapot.c3b")
local vertexShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.vert") local program = axb.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs')
local fragmentShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.frag")
local program = ccb.Device:getInstance():newProgram(vertexShader, fragmentShader)
local programState = ccb.ProgramState:new(program) local programState = ccb.ProgramState:new(program)
program:release()
self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg",
"MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg",

View File

@ -157,16 +157,18 @@ bool DrawNode3D::init()
const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); const auto& attributeInfo = _programState->getProgram()->getActiveAttributes();
auto iter = attributeInfo.find("a_position"); auto iter = attributeInfo.find("a_position");
auto vertexLayout = _programState->getMutableVertexLayout();
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib(iter->first, iter->second.location, backend::VertexFormat::FLOAT3, 0, false); vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::FLOAT3, 0, false);
} }
iter = attributeInfo.find("a_color"); iter = attributeInfo.find("a_color");
if (iter != attributeInfo.end()) if (iter != attributeInfo.end())
{ {
_programState->setVertexAttrib(iter->first, iter->second.location, backend::VertexFormat::UBYTE4, sizeof(Vec3), true); vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::UBYTE4, sizeof(Vec3),
true);
} }
_programState->setVertexStride(sizeof(V3F_C4B)); vertexLayout->setStride(sizeof(V3F_C4B));
_customCommand.createVertexBuffer(sizeof(V3F_C4B), INITIAL_VERTEX_BUFFER_LENGTH, _customCommand.createVertexBuffer(sizeof(V3F_C4B), INITIAL_VERTEX_BUFFER_LENGTH,
CustomCommand::BufferUsage::DYNAMIC); CustomCommand::BufferUsage::DYNAMIC);