mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
graphicsdriver: Optimize shaders for the case of FILTER_SCREEN
Assume a color matrix or color vertex values are not used when the filter is FILTER_SCREEN.
This commit is contained in:
parent
cbb0a1da95
commit
3aa6eb3a66
@ -115,10 +115,10 @@ inline float2 AdjustTexelByAddress<ADDRESS_REPEAT>(float2 p, float4 tex_region)
|
||||
}
|
||||
|
||||
template<uint8_t filter, uint8_t address>
|
||||
struct GetColorFromTexel;
|
||||
struct ColorFromTexel;
|
||||
|
||||
template<uint8_t address>
|
||||
struct GetColorFromTexel<FILTER_NEAREST, address> {
|
||||
struct ColorFromTexel<FILTER_NEAREST, address> {
|
||||
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
|
||||
float2 p = AdjustTexelByAddress<address>(v.tex, v.tex_region);
|
||||
if (v.tex_region[0] <= p.x &&
|
||||
@ -133,7 +133,7 @@ struct GetColorFromTexel<FILTER_NEAREST, address> {
|
||||
};
|
||||
|
||||
template<uint8_t address>
|
||||
struct GetColorFromTexel<FILTER_LINEAR, address> {
|
||||
struct ColorFromTexel<FILTER_LINEAR, address> {
|
||||
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
|
||||
constexpr sampler texture_sampler(filter::nearest);
|
||||
const float2 texel_size = 1 / source_size;
|
||||
@ -172,7 +172,7 @@ struct GetColorFromTexel<FILTER_LINEAR, address> {
|
||||
};
|
||||
|
||||
template<uint8_t address>
|
||||
struct GetColorFromTexel<FILTER_SCREEN, address> {
|
||||
struct ColorFromTexel<FILTER_SCREEN, address> {
|
||||
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
|
||||
constexpr sampler texture_sampler(filter::nearest);
|
||||
const float2 texel_size = 1 / source_size;
|
||||
@ -193,26 +193,41 @@ struct GetColorFromTexel<FILTER_SCREEN, address> {
|
||||
};
|
||||
|
||||
template<bool useColorM, uint8_t filter, uint8_t address>
|
||||
float4 FragmentShaderImpl(
|
||||
VertexOut v,
|
||||
texture2d<float> texture,
|
||||
constant float2& source_size,
|
||||
constant float4x4& color_matrix_body,
|
||||
constant float4& color_matrix_translation,
|
||||
constant float& scale) {
|
||||
float4 c = GetColorFromTexel<filter, address>().Do(v, texture, source_size, scale);
|
||||
if (useColorM) {
|
||||
c.rgb /= c.a + (1.0 - sign(c.a));
|
||||
c = (color_matrix_body * c) + color_matrix_translation;
|
||||
c *= v.color;
|
||||
c.rgb *= c.a;
|
||||
} else {
|
||||
float4 s = v.color;
|
||||
c *= float4(s.r, s.g, s.b, 1.0) * s.a;
|
||||
struct FragmentShaderImpl {
|
||||
inline float4 Do(
|
||||
VertexOut v,
|
||||
texture2d<float> texture,
|
||||
constant float2& source_size,
|
||||
constant float4x4& color_matrix_body,
|
||||
constant float4& color_matrix_translation,
|
||||
constant float& scale) {
|
||||
float4 c = ColorFromTexel<filter, address>().Do(v, texture, source_size, scale);
|
||||
if (useColorM) {
|
||||
c.rgb /= c.a + (1.0 - sign(c.a));
|
||||
c = (color_matrix_body * c) + color_matrix_translation;
|
||||
c *= v.color;
|
||||
c.rgb *= c.a;
|
||||
} else {
|
||||
float4 s = v.color;
|
||||
c *= float4(s.r, s.g, s.b, 1.0) * s.a;
|
||||
}
|
||||
c = min(c, c.a);
|
||||
return c;
|
||||
}
|
||||
c = min(c, c.a);
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
template<bool useColorM, uint8_t address>
|
||||
struct FragmentShaderImpl<useColorM, FILTER_SCREEN, address> {
|
||||
inline float4 Do(
|
||||
VertexOut v,
|
||||
texture2d<float> texture,
|
||||
constant float2& source_size,
|
||||
constant float4x4& color_matrix_body,
|
||||
constant float4& color_matrix_translation,
|
||||
constant float& scale) {
|
||||
return ColorFromTexel<FILTER_SCREEN, address>().Do(v, texture, source_size, scale);
|
||||
}
|
||||
};
|
||||
|
||||
// Define Foo and FooCp macros to force macro replacement.
|
||||
// See "6.10.3.1 Argument substitution" in ISO/IEC 9899.
|
||||
@ -228,7 +243,7 @@ float4 FragmentShaderImpl(
|
||||
constant float4x4& color_matrix_body [[buffer(3)]], \
|
||||
constant float4& color_matrix_translation [[buffer(4)]], \
|
||||
constant float& scale [[buffer(5)]]) { \
|
||||
return FragmentShaderImpl<useColorM, filter, address>( \
|
||||
return FragmentShaderImpl<useColorM, filter, address>().Do( \
|
||||
v, texture, source_size, color_matrix_body, color_matrix_translation, scale); \
|
||||
}
|
||||
|
||||
|
@ -197,12 +197,13 @@ void main(void) {
|
||||
|
||||
#if defined(FILTER_NEAREST)
|
||||
pos = adjustTexelByAddress(pos, varying_tex_region);
|
||||
color = vec4(0, 0, 0, 0);
|
||||
if (varying_tex_region[0] <= pos.x &&
|
||||
varying_tex_region[1] <= pos.y &&
|
||||
pos.x < varying_tex_region[2] &&
|
||||
pos.y < varying_tex_region[3]) {
|
||||
color = texture2D(texture, pos);
|
||||
} else {
|
||||
color = vec4(0, 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -240,6 +241,7 @@ void main(void) {
|
||||
#endif
|
||||
|
||||
#if defined(FILTER_SCREEN)
|
||||
|
||||
highp vec2 p0 = pos - texel_size / 2.0 / scale;
|
||||
highp vec2 p1 = pos + texel_size / 2.0 / scale;
|
||||
|
||||
@ -253,8 +255,10 @@ void main(void) {
|
||||
|
||||
vec2 rateCenter = vec2(1.0, 1.0) - texel_size / 2.0 / scale;
|
||||
vec2 rate = clamp(((fract(p0 * source_size) - rateCenter) * scale) + rateCenter, 0.0, 1.0);
|
||||
color = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y);
|
||||
#endif
|
||||
gl_FragColor = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y);
|
||||
// Assume that a color matrix and color vector values are not used with FILTER_SCREEN.
|
||||
|
||||
#else
|
||||
|
||||
#if defined(USE_COLOR_MATRIX)
|
||||
// Un-premultiply alpha.
|
||||
@ -273,6 +277,9 @@ void main(void) {
|
||||
color = min(color, color.a);
|
||||
|
||||
gl_FragColor = color;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
`
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user