Add settable bitmap patterns on Sprites

This commit is contained in:
Struma 2021-11-29 06:58:41 -05:00
parent 3da0f4c948
commit 6722a1e61a
7 changed files with 569 additions and 464 deletions

View file

@ -52,6 +52,7 @@ RB_METHOD(spriteInitialize) {
}
DEF_GFX_PROP_OBJ_REF(Sprite, Bitmap, Bitmap, "bitmap")
DEF_GFX_PROP_OBJ_REF(Sprite, Bitmap, Pattern, "pattern")
DEF_GFX_PROP_OBJ_VAL(Sprite, Rect, SrcRect, "src_rect")
DEF_GFX_PROP_OBJ_VAL(Sprite, Color, Color, "color")
DEF_GFX_PROP_OBJ_VAL(Sprite, Tone, Tone, "tone")
@ -64,6 +65,9 @@ DEF_GFX_PROP_I(Sprite, BushDepth)
DEF_GFX_PROP_I(Sprite, BushOpacity)
DEF_GFX_PROP_I(Sprite, Opacity)
DEF_GFX_PROP_I(Sprite, BlendType)
DEF_GFX_PROP_I(Sprite, PatternOpacity)
DEF_GFX_PROP_I(Sprite, PatternScrollX)
DEF_GFX_PROP_I(Sprite, PatternScrollY)
DEF_GFX_PROP_I(Sprite, WaveAmp)
DEF_GFX_PROP_I(Sprite, WaveLength)
DEF_GFX_PROP_I(Sprite, WaveSpeed)
@ -132,6 +136,11 @@ void spriteBindingInit() {
INIT_PROP_BIND(Sprite, BushOpacity, "bush_opacity");
INIT_PROP_BIND(Sprite, Pattern, "pattern");
INIT_PROP_BIND(Sprite, PatternOpacity, "pattern_opacity");
INIT_PROP_BIND(Sprite, PatternScrollX, "pattern_scroll_x");
INIT_PROP_BIND(Sprite, PatternScrollY, "pattern_scroll_y");
INIT_PROP_BIND(Sprite, WaveAmp, "wave_amp");
INIT_PROP_BIND(Sprite, WaveLength, "wave_length");
INIT_PROP_BIND(Sprite, WaveSpeed, "wave_speed");

View file

@ -9,15 +9,27 @@ uniform lowp vec4 color;
uniform float bushDepth;
uniform lowp float bushOpacity;
uniform sampler2D pattern;
uniform lowp float patternOpacity;
uniform bool renderPattern;
varying vec2 v_texCoord;
varying vec2 v_patCoord;
const vec3 lumaF = vec3(.299, .587, .114);
const vec2 repeat = vec2(1, 1);
void main()
{
/* Sample source color */
vec4 frag = texture2D(texture, v_texCoord);
/* Apply the pattern if needed */
if (renderPattern) {
vec4 pattfrag = texture2D(pattern, mod(v_patCoord, repeat));
frag.rgb = mix(frag.rgb, pattfrag.rgb, pattfrag.a * patternOpacity);
}
/* Apply gray */
float luma = dot(frag.rgb, lumaF);
frag.rgb = mix(frag.rgb, vec3(luma), tone.w);

View file

@ -4,14 +4,22 @@ uniform mat4 projMat;
uniform mat4 spriteMat;
uniform vec2 texSizeInv;
uniform vec2 patternSizeInv;
uniform vec2 patternScroll;
uniform bool renderPattern;
attribute vec2 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
varying vec2 v_patCoord;
void main()
{
gl_Position = projMat * spriteMat * vec4(position, 0, 1);
v_texCoord = texCoord * texSizeInv;
if (renderPattern) {
v_patCoord = (texCoord * patternSizeInv) - (patternScroll * patternSizeInv);
}
}

View file

@ -245,6 +245,11 @@ void Shader::initFromFile(const char *_vertFile, const char *_fragFile,
_vertFile, _fragFile, programName);
}
void Shader::setVec2Uniform(GLint location, const Vec2 &vec)
{
gl.Uniform2f(location, vec.x, vec.y);
}
void Shader::setVec4Uniform(GLint location, const Vec4 &vec)
{
gl.Uniform4f(location, vec.x, vec.y, vec.z, vec.w);
@ -463,6 +468,11 @@ SpriteShader::SpriteShader()
GET_U(opacity);
GET_U(bushDepth);
GET_U(bushOpacity);
GET_U(pattern);
GET_U(renderPattern);
GET_U(patternSizeInv);
GET_U(patternOpacity);
GET_U(patternScroll);
}
void SpriteShader::setSpriteMat(const float value[16])
@ -495,6 +505,27 @@ void SpriteShader::setBushOpacity(float value)
gl.Uniform1f(u_bushOpacity, value);
}
void SpriteShader::setPattern(const TEX::ID pattern, const Vec2 &dimensions)
{
setTexUniform(u_pattern, 1, pattern);
gl.Uniform2f(u_patternSizeInv, 1.f / dimensions.x, 1.f / dimensions.y);
}
void SpriteShader::setShouldRenderPattern(bool value)
{
gl.Uniform1i(u_renderPattern, value);
}
void SpriteShader::setPatternOpacity(float value)
{
gl.Uniform1f(u_patternOpacity, value);
}
void SpriteShader::setPatternScroll(const Vec2 &scroll)
{
setVec2Uniform(u_patternScroll, scroll);
}
PlaneShader::PlaneShader()
{

View file

@ -53,6 +53,7 @@ protected:
const char *programName);
static void setVec4Uniform(GLint location, const Vec4 &vec);
static void setVec2Uniform(GLint location, const Vec2 &vec);
static void setTexUniform(GLint location, unsigned unitIndex, TEX::ID texture);
GLuint vertShader, fragShader;
@ -190,9 +191,13 @@ public:
void setOpacity(float value);
void setBushDepth(float value);
void setBushOpacity(float value);
void setPattern(const TEX::ID pattern, const Vec2 &dimensions);
void setShouldRenderPattern(bool value);
void setPatternOpacity(float value);
void setPatternScroll(const Vec2 &scroll);
private:
GLint u_spriteMat, u_tone, u_opacity, u_color, u_bushDepth, u_bushOpacity;
GLint u_spriteMat, u_tone, u_opacity, u_color, u_bushDepth, u_bushOpacity, u_pattern, u_renderPattern, u_patternSizeInv, u_patternOpacity, u_patternScroll;
};
class PlaneShader : public ShaderBase

View file

@ -1,23 +1,23 @@
/*
** sprite.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
** sprite.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sprite.h"
@ -60,6 +60,10 @@ struct SpritePrivate
NormValue opacity;
BlendType blendType;
Bitmap *pattern;
NormValue patternOpacity;
Vec2 patternScroll;
IntRect sceneRect;
Vec2i sceneOrig;
@ -97,6 +101,8 @@ struct SpritePrivate
bushOpacity(128),
opacity(255),
blendType(BlendNormal),
pattern(0),
patternOpacity(255),
isVisible(false),
color(&tmp.color),
tone(&tmp.tone)
@ -109,6 +115,8 @@ struct SpritePrivate
prepareCon = shState->prepareDraw.connect
(&SpritePrivate::prepare, this);
patternScroll = Vec2(0,0);
wave.amp = 0;
wave.length = 180;
wave.speed = 360;
@ -299,7 +307,7 @@ struct SpritePrivate
};
Sprite::Sprite(Viewport *viewport)
: ViewportElement(viewport)
: ViewportElement(viewport)
{
p = new SpritePrivate;
onGeometryChange(scene->getGeometry());
@ -321,6 +329,7 @@ DEF_ATTR_RD_SIMPLE(Sprite, Angle, float, p->trans.getRotation())
DEF_ATTR_RD_SIMPLE(Sprite, Mirror, bool, p->mirrored)
DEF_ATTR_RD_SIMPLE(Sprite, BushDepth, int, p->bushDepth)
DEF_ATTR_RD_SIMPLE(Sprite, BlendType, int, p->blendType)
DEF_ATTR_RD_SIMPLE(Sprite, Pattern, Bitmap*, p->pattern)
DEF_ATTR_RD_SIMPLE(Sprite, Width, int, p->srcRect->width)
DEF_ATTR_RD_SIMPLE(Sprite, Height, int, p->srcRect->height)
DEF_ATTR_RD_SIMPLE(Sprite, WaveAmp, int, p->wave.amp)
@ -333,6 +342,9 @@ DEF_ATTR_SIMPLE(Sprite, Opacity, int, p->opacity)
DEF_ATTR_SIMPLE(Sprite, SrcRect, Rect&, *p->srcRect)
DEF_ATTR_SIMPLE(Sprite, Color, Color&, *p->color)
DEF_ATTR_SIMPLE(Sprite, Tone, Tone&, *p->tone)
DEF_ATTR_SIMPLE(Sprite, PatternOpacity, int, p->patternOpacity)
DEF_ATTR_SIMPLE(Sprite, PatternScrollX, int, p->patternScroll.x)
DEF_ATTR_SIMPLE(Sprite, PatternScrollY, int, p->patternScroll.y)
void Sprite::setBitmap(Bitmap *bitmap)
{
@ -476,15 +488,28 @@ void Sprite::setBlendType(int type)
}
}
void Sprite::setPattern(Bitmap *value)
{
guardDisposed();
if (p->pattern == value)
return;
p->pattern = value;
if (!nullOrDisposed(value))
value->ensureNonMega();
}
#define DEF_WAVE_SETTER(Name, name, type) \
void Sprite::setWave##Name(type value) \
{ \
guardDisposed(); \
if (p->wave.name == value) \
return; \
p->wave.name = value; \
p->wave.dirty = true; \
}
void Sprite::setWave##Name(type value) \
{ \
guardDisposed(); \
if (p->wave.name == value) \
return; \
p->wave.name = value; \
p->wave.dirty = true; \
}
DEF_WAVE_SETTER(Amp, amp, int)
DEF_WAVE_SETTER(Length, length, int)
@ -527,7 +552,8 @@ void Sprite::draw()
bool renderEffect = p->color->hasEffect() ||
p->tone->hasEffect() ||
flashing ||
p->bushDepth != 0;
p->bushDepth != 0 ||
(p->pattern && !p->pattern->isDisposed());
if (renderEffect)
{
@ -542,6 +568,16 @@ void Sprite::draw()
shader.setBushDepth(p->efBushDepth);
shader.setBushOpacity(p->bushOpacity.norm);
if (p->pattern) {
shader.setPattern(p->pattern->getGLTypes().tex, Vec2(p->pattern->width(), p->pattern->height()));
shader.setPatternOpacity(p->patternOpacity.norm);
shader.setPatternScroll(p->patternScroll);
shader.setShouldRenderPattern(true);
}
else {
shader.setShouldRenderPattern(false);
}
/* When both flashing and effective color are set,
* the one with higher alpha will be blended */
const Vec4 *blend = (flashing && flashColor.w > p->color->norm.w) ?

View file

@ -62,6 +62,10 @@ public:
DECL_ATTR( BlendType, int )
DECL_ATTR( Color, Color& )
DECL_ATTR( Tone, Tone& )
DECL_ATTR( Pattern, Bitmap* )
DECL_ATTR( PatternOpacity, int )
DECL_ATTR( PatternScrollX, int )
DECL_ATTR( PatternScrollY, int )
DECL_ATTR( WaveAmp, int )
DECL_ATTR( WaveLength, int )
DECL_ATTR( WaveSpeed, int )