Commit fafcfaa5 authored by Jack Andersen's avatar Jack Andersen

Huge shader refactor

parent 550955b0
......@@ -91,3 +91,4 @@ list(APPEND SPECTER_SOURCES
atdna_FontCache.cpp)
add_library(specter ${SPECTER_SOURCES} ${SPECTER_HEADERS})
add_dependencies(specter hecl-light)
......@@ -8,14 +8,28 @@ namespace specter
class Control;
class Button;
enum class ControlType
{
Button,
Float,
Int,
String,
CVar
};
struct IControlBinding
{
virtual ControlType type() const = 0;
virtual std::string_view name(const Control* control) const=0;
virtual std::string_view help(const Control* control) const {return {};}
};
struct IButtonBinding : IControlBinding
{
ControlType type() const { return ControlType::Button; }
static IButtonBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr; }
/** Pressed/Released while Hovering action,
* cancellable by holding the button and releasing outside */
virtual void activated(const Button* button, const boo::SWindowCoord& coord) {}
......@@ -43,6 +57,9 @@ struct IButtonBinding : IControlBinding
struct IFloatBinding : IControlBinding
{
ControlType type() const { return ControlType::Float; }
static IFloatBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr; }
virtual float getDefault(const Control* control) const {return 0.0;}
virtual std::pair<float,float> getBounds(const Control* control) const {return std::make_pair(FLT_MIN, FLT_MAX);}
virtual void changed(const Control* control, float val)=0;
......@@ -50,6 +67,9 @@ struct IFloatBinding : IControlBinding
struct IIntBinding : IControlBinding
{
ControlType type() const { return ControlType::Int; }
static IIntBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr; }
virtual int getDefault(const Control* control) const {return 0;}
virtual std::pair<int,int> getBounds(const Control* control) const {return std::make_pair(INT_MIN, INT_MAX);}
virtual void changed(const Control* control, int val)=0;
......@@ -57,6 +77,9 @@ struct IIntBinding : IControlBinding
struct IStringBinding : IControlBinding
{
ControlType type() const { return ControlType::String; }
static IStringBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr; }
virtual std::string getDefault(const Control* control) const {return "";}
virtual void changed(const Control* control, std::string_view val)=0;
};
......@@ -66,6 +89,9 @@ struct CVarControlBinding : IControlBinding
hecl::CVar* m_cvar;
CVarControlBinding(hecl::CVar* cvar)
: m_cvar(cvar) {}
ControlType type() const { return ControlType::CVar; }
static CVarControlBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::CVar ? static_cast<CVarControlBinding*>(bind) : nullptr; }
std::string_view name(const Control* control) const {return m_cvar->name();}
std::string_view help(const Control* control) const {return m_cvar->rawHelp();}
};
......
......@@ -8,6 +8,7 @@
#include <hecl/Runtime.hpp>
#include <athena/FileReader.hpp>
#include <athena/FileWriter.hpp>
#include <athena/DNA.hpp>
namespace specter
{
......
......@@ -17,7 +17,6 @@ class NumericField : public View
boo::IGraphicsBufferD* m_bBlockBuf;
boo::IGraphicsBufferD* m_bVertsBuf;
boo::IVertexFormat* m_bVtxFmt; /* OpenGL only */
boo::IShaderDataBinding* m_bShaderBinding;
int m_nomWidth, m_nomHeight;
......
......@@ -74,7 +74,10 @@ public:
if (m_toolbar.m_view)
m_toolbar.m_view->setMultiplyColor(color);
}
bool isSpace() const { return true; }
};
inline Space* View::castToSpace() { return isSpace() ? static_cast<Space*>(this) : nullptr; }
}
......
......@@ -112,7 +112,10 @@ public:
if (m_views[1].m_view)
m_views[1].m_view->setMultiplyColor(color);
}
bool isSplitView() const { return true; }
};
inline SplitView* View::castToSplitView() { return isSplitView() ? static_cast<SplitView*>(this) : nullptr; }
}
......
......@@ -2,10 +2,7 @@
#define SPECTER_TEXTVIEW_HPP
#include "View.hpp"
#include <boo/graphicsdev/GL.hpp>
#include <boo/graphicsdev/D3D.hpp>
#include <boo/graphicsdev/Metal.hpp>
#include <boo/graphicsdev/Vulkan.hpp>
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "FontCache.hpp"
......@@ -62,7 +59,6 @@ private:
size_t m_capacity;
size_t m_curSize = 0;
hecl::VertexBufferPool<RenderGlyph>::Token m_glyphBuf;
boo::ObjToken<boo::IVertexFormat> m_vtxFmt; /* OpenGL only */
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
const FontAtlas& m_fontAtlas;
Alignment m_align;
......@@ -90,27 +86,14 @@ public:
FontCache* m_fcache = nullptr;
boo::ObjToken<boo::IShaderPipeline> m_regular;
boo::ObjToken<boo::IShaderPipeline> m_subpixel;
boo::ObjToken<boo::IVertexFormat> m_vtxFmt; /* Not OpenGL */
#if BOO_HAS_GL
void init(boo::GLDataFactory::Context& ctx, FontCache* fcache);
#endif
#if _WIN32
void init(boo::D3DDataFactory::Context& ctx, FontCache* fcache);
#endif
#if BOO_HAS_METAL
void init(boo::MetalDataFactory::Context& ctx, FontCache* fcache);
#endif
#if BOO_HAS_VULKAN
void init(boo::VulkanDataFactory::Context& ctx, FontCache* fcache);
#endif
void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache);
void destroy()
{
m_glyphPool.doDestroy();
m_regular.reset();
m_subpixel.reset();
m_vtxFmt.reset();
}
};
......
#ifndef SPECTER_VIEW_HPP
#define SPECTER_VIEW_HPP
#include <boo/boo.hpp>
#include "boo/boo.hpp"
#include "optional.hpp"
#include "zeus/CVector3f.hpp"
#include "zeus/CMatrix4f.hpp"
......@@ -11,11 +11,6 @@
#include "hecl/UniformBufferPool.hpp"
#include "hecl/VertexBufferPool.hpp"
#include <boo/graphicsdev/GL.hpp>
#include <boo/graphicsdev/D3D.hpp>
#include <boo/graphicsdev/Metal.hpp>
#include <boo/graphicsdev/Vulkan.hpp>
namespace specter
{
class IThemeData;
......@@ -81,6 +76,8 @@ public:
}
};
class Space;
class SplitView;
class View
{
public:
......@@ -111,7 +108,6 @@ public:
struct VertexBufferBinding
{
typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf;
boo::ObjToken<boo::IVertexFormat> m_vtxFmt; /* OpenGL only */
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
void load(const VertStruct* data, size_t count)
......@@ -165,24 +161,6 @@ private:
protected:
ViewBlock m_viewVertBlock;
#define SPECTER_GLSL_VIEW_VERT_BLOCK\
"UBINDING0 uniform SpecterViewBlock\n"\
"{\n"\
" mat4 mv;\n"\
" vec4 mulColor;\n"\
"};\n"
#define SPECTER_HLSL_VIEW_VERT_BLOCK\
"cbuffer SpecterViewBlock : register(b0)\n"\
"{\n"\
" float4x4 mv;\n"\
" float4 mulColor;\n"\
"};\n"
#define SPECTER_METAL_VIEW_VERT_BLOCK\
"struct SpecterViewBlock\n"\
"{\n"\
" float4x4 mv;\n"\
" float4 mulColor;\n"\
"};\n"
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
public:
......@@ -200,23 +178,9 @@ public:
}
boo::ObjToken<boo::IShaderPipeline> m_solidShader;
boo::ObjToken<boo::IVertexFormat> m_solidVtxFmt; /* Not OpenGL */
boo::ObjToken<boo::IShaderPipeline> m_texShader;
boo::ObjToken<boo::IVertexFormat> m_texVtxFmt; /* Not OpenGL */
#if BOO_HAS_GL
void init(boo::GLDataFactory::Context& ctx, const IThemeData& theme);
#endif
#if _WIN32
void init(boo::D3DDataFactory::Context& ctx, const IThemeData& theme);
#endif
#if BOO_HAS_METAL
void init(boo::MetalDataFactory::Context& ctx, const IThemeData& theme);
#endif
#if BOO_HAS_VULKAN
void init(boo::VulkanDataFactory::Context& ctx, const IThemeData& theme);
#endif
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy()
{
......@@ -225,9 +189,7 @@ public:
m_texPool.doDestroy();
m_solidShader.reset();
m_solidVtxFmt.reset();
m_texShader.reset();
m_texVtxFmt.reset();
}
};
......@@ -292,6 +254,11 @@ public:
const boo::SWindowRect& scissor) {resized(root, sub);}
virtual void think() {}
virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
virtual bool isSpace() const { return false; }
virtual bool isSplitView() const { return false; }
Space* castToSpace();
SplitView* castToSplitView();
};
template <class ViewPtrType>
......
......@@ -149,8 +149,7 @@ public:
class ViewResources
{
template <class FactoryCtx>
void init(FactoryCtx& factory, const IThemeData& theme, FontCache* fcache)
void init(boo::IGraphicsDataFactory::Context& factory, const IThemeData& theme, FontCache* fcache)
{
m_viewRes.init(factory, theme);
m_textRes.init(factory, fcache);
......
......@@ -320,7 +320,7 @@ void RootView::SplitMenuSystem::mouseUp(const boo::SWindowCoord& coord, boo::EMo
{
m_interactiveDown = false;
m_phase = Phase::Inactive;
Space* space = dynamic_cast<Space*>(m_splitView->m_views[m_interactiveSlot].m_view);
Space* space = m_splitView->m_views[m_interactiveSlot].m_view->castToSpace();
if (space && space->m_controller.spaceSplitAllowed())
{
ISplitSpaceController* ss = space->m_controller.spaceSplit(axis, 0);
......@@ -337,7 +337,7 @@ SplitView* RootView::recursiveTestSplitHover(SplitView* sv, const boo::SWindowCo
return sv;
for (int i=0 ; i<2 ; ++i)
{
SplitView* child = dynamic_cast<SplitView*>(sv->m_views[i].m_view);
SplitView* child = sv->m_views[i].m_view->castToSplitView();
if (child)
{
SplitView* res = recursiveTestSplitHover(child, coord);
......@@ -391,7 +391,7 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
{
for (View* v : m_views)
{
SplitView* sv = dynamic_cast<SplitView*>(v);
SplitView* sv = v->castToSplitView();
if (sv)
sv = recursiveTestSplitHover(sv, coord);
if (sv)
......
......@@ -267,7 +267,7 @@ void Space::CornerView::mouseLeave(const boo::SWindowCoord& coord)
SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side)
{
SplitView* ret = dynamic_cast<SplitView*>(&parentView());
SplitView* ret = parentView().castToSplitView();
View* test = this;
while (ret)
{
......@@ -277,7 +277,7 @@ SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side)
return ret;
else if (ret->m_views[side].m_view == test)
test = ret;
ret = dynamic_cast<SplitView*>(&ret->parentView());
ret = ret->parentView().castToSplitView();
}
return nullptr;
}
......
......@@ -123,7 +123,7 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
dirOut = ArrowDir::Up;
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
......@@ -140,7 +140,7 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
dirOut = ArrowDir::Down;
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
}
......@@ -160,7 +160,7 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
dirOut = ArrowDir::Right;
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
......@@ -177,7 +177,7 @@ bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlot
dirOut = ArrowDir::Left;
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
}
......@@ -199,7 +199,7 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
......@@ -212,7 +212,7 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
}
......@@ -228,7 +228,7 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
......@@ -241,7 +241,7 @@ void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir&
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
}
......@@ -265,7 +265,7 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
......@@ -281,7 +281,7 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
......@@ -300,7 +300,7 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
......@@ -316,7 +316,7 @@ bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut,
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
......@@ -339,7 +339,7 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
......@@ -352,7 +352,7 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
}
......@@ -368,7 +368,7 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
{
if (m_views[1].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[1].m_view);
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
......@@ -381,7 +381,7 @@ void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axi
{
if (m_views[0].m_view)
{
SplitView* chSplit = dynamic_cast<SplitView*>(m_views[0].m_view);
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
}
......
......@@ -33,8 +33,9 @@ void TextField::_setText()
m_textStr = m_deferredTextStr;
m_text->typesetGlyphs(m_textStr, m_error ? rootView().themeData().uiText() :
rootView().themeData().fieldText());
if (m_controlBinding && dynamic_cast<IStringBinding*>(m_controlBinding))
static_cast<IStringBinding&>(*m_controlBinding).changed(this, m_textStr);
if (m_controlBinding)
if (IStringBinding* strBind = IStringBinding::castTo(m_controlBinding))
strBind->changed(this, m_textStr);
m_hasTextSet = false;
if (m_deferredMarkStr.size())
m_hasMarkSet = true;
......
This diff is collapsed.
This diff is collapsed.
......@@ -17,31 +17,7 @@ void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache,
m_curveFont = fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi);
factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
switch (ctx.platform())
{
#if BOO_HAS_GL
case boo::IGraphicsDataFactory::Platform::OpenGL:
init<boo::GLDataFactory::Context>(static_cast<boo::GLDataFactory::Context&>(ctx), *theme, fcache);
break;
#endif
#if _WIN32
case boo::IGraphicsDataFactory::Platform::D3D11:
init<boo::D3DDataFactory::Context>(static_cast<boo::D3DDataFactory::Context&>(ctx), *theme, fcache);
break;
#endif
#if BOO_HAS_METAL
case boo::IGraphicsDataFactory::Platform::Metal:
init<boo::MetalDataFactory::Context>(static_cast<boo::MetalDataFactory::Context&>(ctx), *theme, fcache);
break;
#endif
#if BOO_HAS_VULKAN
case boo::IGraphicsDataFactory::Platform::Vulkan:
init<boo::VulkanDataFactory::Context>(static_cast<boo::VulkanDataFactory::Context&>(ctx), *theme, fcache);
break;
#endif
default:
Log.report(logvisor::Fatal, _S("unable to init view system for %s"), ctx.platformName());
}
init(ctx, *theme, fcache);
return true;
} BooTrace);
}
......
include_directories(../../hecl/include
../../hecl/extern/boo/include
../../hecl/extern/boo/logvisor/include)
add_shader(SpecterViewShaders)
add_shader(SpecterTextViewShaders)
#define SPECTER_GLSL_VIEW_VERT_BLOCK\
UBINDING0 uniform SpecterViewBlock\
{\
mat4 mv;\
vec4 mulColor;\
};
#define SPECTER_HLSL_VIEW_VERT_BLOCK\
cbuffer SpecterViewBlock : register(b0)\
{\
float4x4 mv;\
float4 mulColor;\
};
#define SPECTER_METAL_VIEW_VERT_BLOCK\
struct SpecterViewBlock\
{\
float4x4 mv;\
float4 mulColor;\
};
\ No newline at end of file
#include "SpecterCommon.shader"
#shader SpecterTextViewShader
#instattribute position4 0
#instattribute position4 1
#instattribute position4 2
#instattribute position4 3
#instattribute modelview 0
#instattribute modelview 1
#instattribute modelview 2
#instattribute modelview 3
#instattribute uv4 0
#instattribute uv4 1
#instattribute uv4 2
#instattribute uv4 3
#instattribute color
#srcfac srcalpha
#dstfac invsrcalpha
#primitive tristrips
#depthtest none
#depthwrite false
#culling none
#vertex glsl
layout(location=0) in vec3 posIn[4];
layout(location=4) in mat4 mvMtx;
layout(location=8) in vec3 uvIn[4];
layout(location=12) in vec4 colorIn;
SPECTER_GLSL_VIEW_VERT_BLOCK
struct VertToFrag
{
vec3 uv;
vec4 color;
};
SBINDING(0) out VertToFrag vtf;
void main()
{
vec3 pos = posIn[gl_VertexID];
vtf.uv = uvIn[gl_VertexID];
vtf.color = colorIn * mulColor;
gl_Position = mv * mvMtx * vec4(pos, 1.0);
gl_Position = FLIPFROMGL(gl_Position);
}
#fragment glsl
TBINDING0 uniform sampler2DArray fontTex;
struct VertToFrag
{
vec3 uv;
vec4 color;
};
SBINDING(0) in VertToFrag vtf;
layout(location=0) out vec4 colorOut;
void main()
{
colorOut = vtf.color;
colorOut.a *= texture(fontTex, vtf.uv).r;
}
#vertex hlsl
struct VertData
{
float3 posIn[4] : POSITION;
float4x4 mvMtx : MODELVIEW;
float3 uvIn[4] : UV;
float4 colorIn : COLOR;
};
SPECTER_HLSL_VIEW_VERT_BLOCK
struct VertToFrag
{
float4 position : SV_Position;
float3 uv : UV;
float4 color : COLOR;
};
VertToFrag main(in VertData v, in uint vertId : SV_VertexID)
{
VertToFrag vtf;
vtf.uv = v.uvIn[vertId];
vtf.color = v.colorIn * mulColor;
vtf.position = mul(mv, mul(v.mvMtx, float4(v.posIn[vertId], 1.0)));
return vtf;
}
#fragment hlsl
Texture2DArray fontTex : register(t0);
SamplerState samp : register(s0);
struct VertToFrag
{
float4 position : SV_Position;
float3 uv : UV;
float4 color : COLOR;
};
float4 main(in VertToFrag vtf) : SV_Target0
{
float4 colorOut = vtf.color;
colorOut.a *= fontTex.Sample(samp, vtf.uv).r;
return colorOut;
}
#vertex metal
struct VertData
{
float3 posIn[4];
float4x4 mvMtx;
float3 uvIn[4];
float4 colorIn;
};
SPECTER_METAL_VIEW_VERT_BLOCK
struct VertToFrag
{
float4 position [[ position ]];
float3 uv;
float4 color;
};
vertex VertToFrag vmain(constant VertData* va [[ buffer(1) ]],
uint vertId [[ vertex_id ]], uint instId [[ instance_id ]],
constant SpecterViewBlock& view [[ buffer(2) ]])
{
VertToFrag vtf;
constant VertData& v = va[instId];
vtf.uv = v.uvIn[vertId];
vtf.color = v.colorIn * view.mulColor;
vtf.position = view.mv * v.mvMtx * float4(v.posIn[vertId], 1.0);
return vtf;
}
#fragment metal
struct VertToFrag
{
float4 position [[ position ]];
float3 uv;
float4 color;
};
fragment float4 fmain(VertToFrag vtf [[ stage_in ]],
sampler samp [[ sampler(0) ]],
texture2d_array<float> fontTex [[ texture(0) ]])
{
float4 colorOut = vtf.color;
colorOut.a *= fontTex.sample(samp, vtf.uv.xy, vtf.uv.z).r;
return colorOut;
}
#shader SpecterTextViewShaderSubpixel : SpecterTextViewShader
#srcfac srccolor1
#dstfac invsrccolor1
#fragment glsl
TBINDING0 uniform sampler2DArray fontTex;
struct VertToFrag
{
vec3 uv;
vec4 color;
};
SBINDING(0) in VertToFrag vtf;
layout(location=0, index=0) out vec4 colorOut;
layout(location=0, index=1) out vec4 blendOut;
void main()
{
colorOut = vtf.color;
blendOut = colorOut.a * texture(fontTex, vtf.uv);
}
#fragment hlsl
Texture2DArray fontTex : register(t0);
SamplerState samp : register(s0);
struct VertToFrag
{
float4 position : SV_Position;
float3 uv : UV;
float4 color : COLOR;
};
struct BlendOut
{
float4 colorOut : SV_Target0;
float4 blendOut : SV_Target1;
};
BlendOut main(in VertToFrag vtf)
{