experiment shaders in outfit
This commit is contained in:
parent
5ec386b35f
commit
04ee85dc92
|
@ -0,0 +1,49 @@
|
|||
uniform float opacity;
|
||||
uniform vec4 color;
|
||||
uniform float ticks;
|
||||
|
||||
uniform sampler2D texture; // outfit texture
|
||||
varying vec2 textureCoords; // outfit texture coords
|
||||
uniform sampler2D maskTexture; // outfit color mask
|
||||
|
||||
uniform vec4 headColor;
|
||||
uniform vec4 bodyColor;
|
||||
uniform vec4 legsColor;
|
||||
uniform vec4 feetColor;
|
||||
|
||||
vec4 calcPixel(vec2 texCoord)
|
||||
{
|
||||
vec4 pixel = texture2D(texture, texCoord);
|
||||
vec4 maskColor = texture2D(maskTexture, texCoord);
|
||||
|
||||
vec4 outColor = vec4(0);
|
||||
if(maskColor.r == 1.0 && maskColor.g == 1.0) {
|
||||
outColor = headColor;
|
||||
} else if(maskColor.r == 1.0) {
|
||||
outColor = bodyColor;
|
||||
} else if(maskColor.g == 1.0) {
|
||||
outColor = legsColor;
|
||||
} else if(maskColor.b == 1.0) {
|
||||
outColor = feetColor;
|
||||
}
|
||||
|
||||
if(outColor.a != 0.0)
|
||||
pixel = pixel * outColor;
|
||||
return pixel;
|
||||
}
|
||||
void main()
|
||||
{
|
||||
vec4 pixel = calcPixel(textureCoords);
|
||||
int num = 16;
|
||||
|
||||
vec4 sum = vec4(0);
|
||||
int i, j;
|
||||
for(i=-num/2;i<num/2;++i) {
|
||||
for(j=-num/2;j<num/2;++j) {
|
||||
sum += calcPixel(textureCoords + vec2(i+1, j+1)*0.005) * 1.0/(num*num);
|
||||
}
|
||||
}
|
||||
sum = sin(ticks/500.0)*sum;
|
||||
|
||||
gl_FragColor = pixel * color * opacity + sum;
|
||||
}
|
|
@ -1,3 +1,38 @@
|
|||
varying vec2 textureCoords;
|
||||
uniform float opacity;
|
||||
uniform vec4 color;
|
||||
uniform float ticks;
|
||||
uniform sampler2D texture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(texture, textureCoords) * color * opacity;
|
||||
}
|
||||
|
||||
/*
|
||||
varying vec2 textureCoords;
|
||||
uniform vec4 color;
|
||||
uniform float ticks;
|
||||
uniform sampler2D texture;
|
||||
|
||||
void main()
|
||||
{
|
||||
int num = 4;
|
||||
vec4 sum = vec4(0);
|
||||
int i, j;
|
||||
for(i=-num/2;i<num/2;++i) {
|
||||
for(j=-num/2;j<num/2;++j) {
|
||||
sum += texture2D(texture, textureCoords + vec2(i+1, j+1)*0.001) * 1.0/(num*num);
|
||||
}
|
||||
}
|
||||
|
||||
float period = ticks/1000.0;
|
||||
float a = (sin(period)+1.0)/2.0;
|
||||
sum.a = 0;
|
||||
gl_FragColor = vec4(1,1,1,2) - texture2D(texture, textureCoords);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
uniform sampler2D texture;
|
||||
varying vec2 textureCoords;
|
||||
|
||||
|
@ -31,7 +66,7 @@ void main()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
uniform sampler2D texture;
|
||||
varying vec2 textureCoords;
|
||||
|
|
|
@ -51,11 +51,7 @@ void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3])
|
|||
void PainterShaderProgram::setColor(const Color& color)
|
||||
{
|
||||
bind();
|
||||
setUniformValue(COLOR_UNIFORM,
|
||||
color.r() / 255.0f,
|
||||
color.g() / 255.0f,
|
||||
color.b() / 255.0f,
|
||||
color.a() / 255.0f);
|
||||
setUniformValue(COLOR_UNIFORM, color);
|
||||
}
|
||||
|
||||
void PainterShaderProgram::setOpacity(GLfloat opacity)
|
||||
|
@ -64,6 +60,15 @@ void PainterShaderProgram::setOpacity(GLfloat opacity)
|
|||
setUniformValue(OPACITY_UNIFORM, opacity);
|
||||
}
|
||||
|
||||
void PainterShaderProgram::setUniformTexture(int location, const TexturePtr& texture, int index)
|
||||
{
|
||||
if(!texture)
|
||||
return;
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getId());
|
||||
setUniformValue(location, index);
|
||||
}
|
||||
|
||||
void PainterShaderProgram::setTexture(const TexturePtr& texture)
|
||||
{
|
||||
if(!texture)
|
||||
|
@ -78,9 +83,7 @@ void PainterShaderProgram::setTexture(const TexturePtr& texture)
|
|||
};
|
||||
|
||||
bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getId());
|
||||
setUniformValue(TEXTURE_UNIFORM, 0);
|
||||
setUniformTexture(TEXTURE_UNIFORM, texture, 0);
|
||||
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
void setColor(const Color& color);
|
||||
void setOpacity(GLfloat opacity);
|
||||
void setTexture(const TexturePtr& texture);
|
||||
void setUniformTexture(int location, const TexturePtr& texture, int index);
|
||||
void draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||
|
||||
private:
|
||||
|
|
|
@ -139,6 +139,6 @@ void ShaderProgram::bindAttributeLocation(int location, const char* name)
|
|||
void ShaderProgram::bindUniformLocation(int location, const char* name)
|
||||
{
|
||||
assert(m_linked);
|
||||
assert(location >= 0 && location < 10);
|
||||
assert(location >= 0 && location < MAX_UNIFORM_LOCATIONS);
|
||||
m_uniformLocations[location] = glGetUniformLocation(m_programId, name);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class ShaderProgram
|
||||
{
|
||||
enum {
|
||||
MAX_UNIFORM_LOCATIONS = 10
|
||||
MAX_UNIFORM_LOCATIONS = 30
|
||||
};
|
||||
public:
|
||||
ShaderProgram();
|
||||
|
@ -62,6 +62,7 @@ public:
|
|||
void setAttributeValue(const char *name, GLfloat x, GLfloat y) { glVertexAttrib2f(getAttributeLocation(name), x, y); }
|
||||
void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(getAttributeLocation(name), x, y, z); }
|
||||
|
||||
void setUniformValue(int location, const Color& color) { glUniform4f(m_uniformLocations[location], color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); }
|
||||
void setUniformValue(int location, GLint value) { glUniform1i(m_uniformLocations[location], value); }
|
||||
void setUniformValue(int location, GLfloat value) { glUniform1f(m_uniformLocations[location], value); }
|
||||
void setUniformValue(int location, GLfloat x, GLfloat y) { glUniform2f(m_uniformLocations[location], x, y); }
|
||||
|
@ -69,6 +70,7 @@ public:
|
|||
void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(m_uniformLocations[location], x, y, z, w); }
|
||||
void setUniformValue(int location, GLfloat mat2[2][2], bool transpose) { glUniformMatrix2fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); }
|
||||
void setUniformValue(int location, GLfloat mat3[3][3], bool transpose) { glUniformMatrix3fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); }
|
||||
void setUniformValue(const char *name, const Color& color) { glUniform4f(glGetUniformLocation(m_programId, name), color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); }
|
||||
void setUniformValue(const char *name, GLint value) { glUniform1i(glGetUniformLocation(m_programId, name), value); }
|
||||
void setUniformValue(const char *name, GLfloat value) { glUniform1f(glGetUniformLocation(m_programId, name), value); }
|
||||
void setUniformValue(const char *name, GLfloat x, GLfloat y) { glUniform2f(glGetUniformLocation(m_programId, name), x, y); }
|
||||
|
|
|
@ -250,14 +250,6 @@ namespace Otc
|
|||
ClientGetObjectInfo = 243
|
||||
};
|
||||
|
||||
enum SpriteMask {
|
||||
SpriteRedMask = 0,
|
||||
SpriteGreenMask,
|
||||
SpriteBlueMask,
|
||||
SpriteYellowMask,
|
||||
SpriteNoMask = 255
|
||||
};
|
||||
|
||||
enum InventorySlots {
|
||||
InventorySlotHead = 1,
|
||||
InventorySlotNecklace,
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/clock.h>
|
||||
|
||||
#include <framework/graphics/paintershaderprogram.h>
|
||||
#include <framework/graphics/paintershadersources.h>
|
||||
#include "spritemanager.h"
|
||||
|
||||
Creature::Creature() : Thing()
|
||||
{
|
||||
m_healthPercent = 0;
|
||||
|
@ -43,6 +47,13 @@ Creature::Creature() : Thing()
|
|||
m_informationFont = g_fonts.getFont("verdana-11px-rounded");
|
||||
}
|
||||
|
||||
PainterShaderProgramPtr outfitProgram;
|
||||
int HEAD_COLOR_UNIFORM = 10;
|
||||
int BODY_COLOR_UNIFORM = 11;
|
||||
int LEGS_COLOR_UNIFORM = 12;
|
||||
int FEET_COLOR_UNIFORM = 13;
|
||||
int MASK_TEXTURE_UNIFORM = 14;
|
||||
|
||||
void Creature::draw(const Point& p)
|
||||
{
|
||||
// TODO: activate on attack, follow, discover how 'attacked' works
|
||||
|
@ -51,6 +62,18 @@ void Creature::draw(const Point& p)
|
|||
g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2);
|
||||
}
|
||||
|
||||
if(!outfitProgram) {
|
||||
outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram);
|
||||
outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
|
||||
outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/outfit.frag");
|
||||
assert(outfitProgram->link());
|
||||
outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor");
|
||||
outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor");
|
||||
outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor");
|
||||
outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor");
|
||||
outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture");
|
||||
}
|
||||
|
||||
// Render creature
|
||||
for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) {
|
||||
|
||||
|
@ -58,35 +81,52 @@ void Creature::draw(const Point& p)
|
|||
if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1))))
|
||||
continue;
|
||||
|
||||
// draw white item
|
||||
g_painter.setColor(Fw::white);
|
||||
internalDraw(p + m_walkOffset, 0);
|
||||
g_painter.setCustomProgram(outfitProgram);
|
||||
|
||||
// draw mask if exists
|
||||
outfitProgram->bind();
|
||||
outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor());
|
||||
outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor());
|
||||
outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor());
|
||||
outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor());
|
||||
|
||||
for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) {
|
||||
for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) {
|
||||
int sprIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases])
|
||||
* m_type->dimensions[ThingType::PatternZ] + m_zPattern)
|
||||
* m_type->dimensions[ThingType::PatternY] + m_yPattern)
|
||||
* m_type->dimensions[ThingType::PatternX] + m_xPattern)
|
||||
* m_type->dimensions[ThingType::Layers] + 0)
|
||||
* m_type->dimensions[ThingType::Height] + yi)
|
||||
* m_type->dimensions[ThingType::Width] + xi;
|
||||
if(m_type->dimensions[ThingType::Layers] > 1) {
|
||||
// switch to blend color mode
|
||||
g_painter.setCompositionMode(Painter::CompositionMode_ColorizeDest);
|
||||
|
||||
// head
|
||||
g_painter.setColor(m_outfit.getHeadColor());
|
||||
internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask);
|
||||
|
||||
// body
|
||||
g_painter.setColor(m_outfit.getBodyColor());
|
||||
internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask);
|
||||
|
||||
// legs
|
||||
g_painter.setColor(m_outfit.getLegsColor());
|
||||
internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask);
|
||||
|
||||
// feet
|
||||
g_painter.setColor(m_outfit.getFeetColor());
|
||||
internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask);
|
||||
|
||||
// restore default blend func
|
||||
g_painter.setCompositionMode(Painter::CompositionMode_SourceOver);
|
||||
g_painter.setColor(Fw::white);
|
||||
int maskIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases])
|
||||
* m_type->dimensions[ThingType::PatternZ] + m_zPattern)
|
||||
* m_type->dimensions[ThingType::PatternY] + m_yPattern)
|
||||
* m_type->dimensions[ThingType::PatternX] + m_xPattern)
|
||||
* m_type->dimensions[ThingType::Layers] + 1)
|
||||
* m_type->dimensions[ThingType::Height] + yi)
|
||||
* m_type->dimensions[ThingType::Width] + xi;
|
||||
int spriteId = m_type->sprites[maskIndex];
|
||||
if(!spriteId)
|
||||
continue;
|
||||
TexturePtr maskTex = g_sprites.getSpriteTexture(spriteId);
|
||||
outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1);
|
||||
}
|
||||
|
||||
int spriteId = m_type->sprites[sprIndex];
|
||||
if(!spriteId)
|
||||
continue;
|
||||
|
||||
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
|
||||
|
||||
Rect drawRect(((p + m_walkOffset).x - xi*32) - m_type->parameters[ThingType::DisplacementX],
|
||||
((p + m_walkOffset).y - yi*32) - m_type->parameters[ThingType::DisplacementY],
|
||||
32, 32);
|
||||
g_painter.drawTexturedRect(drawRect, spriteTex);
|
||||
}
|
||||
}
|
||||
|
||||
g_painter.releaseCustomProgram();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,30 +118,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id)
|
|||
return TexturePtr(new Texture(32, 32, 4, pixels));
|
||||
}
|
||||
|
||||
TexturePtr SpriteManager::loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask)
|
||||
{
|
||||
auto pixels = spriteTex->getPixels();
|
||||
|
||||
static uint32 maskColors[4] = { Fw::red, Fw::green, Fw::blue, Fw::yellow };
|
||||
uint32 maskColor = maskColors[mask];
|
||||
uint32 whiteColor = Fw::white;
|
||||
uint32 alphaColor = Fw::alpha;
|
||||
|
||||
// convert pixels
|
||||
// masked color -> white color
|
||||
// any other color -> alpha color
|
||||
for(int i=0;i<4096;i+=4) {
|
||||
uint32& currentColor = *(uint32*)&pixels[i];
|
||||
if(currentColor == maskColor)
|
||||
currentColor = whiteColor;
|
||||
else
|
||||
currentColor = alphaColor;
|
||||
}
|
||||
|
||||
return TexturePtr(new Texture(32, 32, 4, &pixels[0]));
|
||||
}
|
||||
|
||||
TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask)
|
||||
TexturePtr SpriteManager::getSpriteTexture(int id)
|
||||
{
|
||||
if(id == 0)
|
||||
return g_graphics.getEmptyTexture();
|
||||
|
@ -149,17 +126,11 @@ TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask)
|
|||
assert(id > 0 && id <= m_spritesCount);
|
||||
|
||||
// load sprites on demand
|
||||
Sprite& sprite = m_sprites[id-1];
|
||||
if(!sprite.texture)
|
||||
sprite.texture = loadSpriteTexture(id);
|
||||
TexturePtr& sprite = m_sprites[id-1];
|
||||
if(!sprite)
|
||||
sprite = loadSpriteTexture(id);
|
||||
|
||||
//TODO: release unused sprites textures after X seconds
|
||||
// to avoid massive texture allocations
|
||||
|
||||
if(mask != Otc::SpriteNoMask) {
|
||||
if(!sprite.masks[mask])
|
||||
sprite.masks[mask] = loadSpriteMask(sprite.texture, mask);
|
||||
return sprite.masks[mask];
|
||||
} else
|
||||
return sprite.texture;
|
||||
return sprite;
|
||||
}
|
||||
|
|
|
@ -26,11 +26,6 @@
|
|||
#include "declarations.h"
|
||||
#include <framework/graphics/texture.h>
|
||||
|
||||
struct Sprite {
|
||||
TexturePtr texture;
|
||||
TexturePtr masks[4];
|
||||
};
|
||||
|
||||
class SpriteManager
|
||||
{
|
||||
public:
|
||||
|
@ -42,16 +37,15 @@ public:
|
|||
uint32 getSignature() { return m_signature; }
|
||||
int getSpritesCount() { return m_spritesCount; }
|
||||
|
||||
TexturePtr getSpriteTexture(int id, Otc::SpriteMask mask = Otc::SpriteNoMask);
|
||||
TexturePtr getSpriteTexture(int id);
|
||||
|
||||
private:
|
||||
TexturePtr loadSpriteTexture(int id);
|
||||
TexturePtr loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask);
|
||||
|
||||
uint32 m_signature;
|
||||
uint16 m_spritesCount;
|
||||
std::stringstream m_fin;
|
||||
std::vector<Sprite> m_sprites;
|
||||
std::vector<TexturePtr> m_sprites;
|
||||
TexturePtr m_transparentSprite;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ Thing::Thing() : m_id(0)
|
|||
m_type = g_thingsType.getEmptyThingType();
|
||||
}
|
||||
|
||||
void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask)
|
||||
void Thing::internalDraw(const Point& p, int layers)
|
||||
{
|
||||
for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) {
|
||||
for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) {
|
||||
|
@ -50,7 +50,7 @@ void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask)
|
|||
if(!spriteId)
|
||||
continue;
|
||||
|
||||
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId, mask);
|
||||
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
|
||||
|
||||
Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX],
|
||||
(p.y - yi*32) - m_type->parameters[ThingType::DisplacementY],
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
virtual LocalPlayerPtr asLocalPlayer() { return nullptr; }
|
||||
|
||||
protected:
|
||||
void internalDraw(const Point& p, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask);
|
||||
void internalDraw(const Point& p, int layers);
|
||||
|
||||
uint32 m_id;
|
||||
Position m_position;
|
||||
|
|
Loading…
Reference in New Issue