@@ -1,6 +1,6 @@ | |||||
[vert.glsl] | [vert.glsl] | ||||
#version 130 | |||||
#version 120 | |||||
attribute vec3 in_Position; | attribute vec3 in_Position; | ||||
attribute vec2 in_TexCoord; | attribute vec2 in_TexCoord; | ||||
@@ -19,22 +19,22 @@ void main() | |||||
[frag.glsl] | [frag.glsl] | ||||
#version 130 | |||||
#version 120 | |||||
#if defined GL_ES | #if defined GL_ES | ||||
precision mediump float; | precision mediump float; | ||||
#endif | #endif | ||||
uniform sampler1D u_palette; | |||||
uniform sampler2D u_texture; | uniform sampler2D u_texture; | ||||
uniform sampler2D u_palette; | |||||
uniform vec2 u_texsize; | uniform vec2 u_texsize; | ||||
varying vec2 pass_TexCoord; | varying vec2 pass_TexCoord; | ||||
void main() | void main() | ||||
{ | { | ||||
vec4 pal_pos = texture2D(u_texture, pass_TexCoord); | |||||
vec4 col = texture2D(u_palette, pal_pos.x); | |||||
if (col.a == 0.0) | |||||
vec4 pal = texture2D(u_texture, pass_TexCoord); | |||||
vec4 col = texture2D(u_palette, vec2(pal.x, 0.f)); | |||||
if (pal.x == 0.0) | |||||
discard; | discard; | ||||
gl_FragColor = col; | gl_FragColor = col; | ||||
} | } | ||||
@@ -203,10 +203,10 @@ bool ZedImageData::Open(char const *path) | |||||
//Store size type | //Store size type | ||||
{ | { | ||||
ivec2 size_16 = size; | ivec2 size_16 = size; | ||||
int32_t s_16 = 16; | |||||
int32_t s_16 = 8; | |||||
while (1) | while (1) | ||||
{ | { | ||||
if (size_16.x <= s_16) | |||||
if (size_16.x < s_16) | |||||
{ | { | ||||
size_16.x = s_16; | size_16.x = s_16; | ||||
break; | break; | ||||
@@ -216,7 +216,7 @@ bool ZedImageData::Open(char const *path) | |||||
s_16 = 8; | s_16 = 8; | ||||
while (1) | while (1) | ||||
{ | { | ||||
if (size_16.y <= s_16) | |||||
if (size_16.y < s_16) | |||||
{ | { | ||||
size_16.y = s_16; | size_16.y = s_16; | ||||
break; | break; | ||||
@@ -67,11 +67,11 @@ static inline void DebugAbort() | |||||
2, 1, TOO_FEW_ARGUMENTS)) | 2, 1, TOO_FEW_ARGUMENTS)) | ||||
#define LOL_COUNT_TO_12(...) \ | #define LOL_COUNT_TO_12(...) \ | ||||
LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 10,10,10,10,10,10,10,10,10,10,\ | |||||
10,10,10,10,10,10,10,10,10,10,\ | |||||
10,10,10,10,10,10,10,10,10,10,\ | |||||
10,10,10,10,10,10,10,10,10,10,\ | |||||
10,10,10,10,10,10,10,10,10,10,\ | |||||
LOL_EVAL(LOL_GET_63RD(__VA_ARGS__, 12,12,12,12,12,12,12,12,12,12,\ | |||||
12,12,12,12,12,12,12,12,12,12,\ | |||||
12,12,12,12,12,12,12,12,12,12,\ | |||||
12,12,12,12,12,12,12,12,12,12,\ | |||||
12,12,12,12,12,12,12,12,12,12,\ | |||||
12,11,10,9, 8, 7, 6, 5, 4, 3, \ | 12,11,10,9, 8, 7, 6, 5, 4, 3, \ | ||||
2, 1, TOO_FEW_ARGUMENTS)) | 2, 1, TOO_FEW_ARGUMENTS)) | ||||
@@ -28,6 +28,37 @@ typedef Real<16> real; | |||||
/* The “half” type used for 16-bit floating point numbers. */ | /* The “half” type used for 16-bit floating point numbers. */ | ||||
class half; | class half; | ||||
#define DEFINE_ENUM(NEW_ENUM) struct NEW_ENUM { | |||||
#define START_VALUE enum Value { | |||||
#define ADD_VALUE(NEW_VALUE) E##NEW_VALUE, | |||||
#define END_VALUE MAX } m_value; | |||||
#define START_TEXT \ | |||||
inline String C() \ | |||||
{ \ | |||||
static String text[] = { | |||||
#define ADD_TEXT(NEW_TEXT) #NEW_TEXT, | |||||
#define END_TEXT \ | |||||
}; \ | |||||
if (m_value >= MAX) \ | |||||
return "INVALID"; \ | |||||
return text[m_value]; \ | |||||
}; \ | |||||
#define END_ENUM(NEW_ENUM) \ | |||||
inline NEW_ENUM() : m_value(MAX) {} \ | |||||
inline NEW_ENUM(Value v) : m_value(v) {} \ | |||||
inline NEW_ENUM(int v) : m_value((Value)v) {} \ | |||||
inline NEW_ENUM(float v) : m_value((Value)(int)v) {} \ | |||||
bool operator==(const NEW_ENUM& v) { return m_value == v.m_value; } \ | |||||
bool operator==(const int& v) { return m_value == NEW_ENUM(v); } \ | |||||
bool operator==(const float& v) { return m_value == NEW_ENUM(v); } \ | |||||
inline operator Value() { return m_value; } \ | |||||
}; \ | |||||
bool operator== (int e1, NEW_ENUM& e2) { return (e2 == e1); } \ | |||||
bool operator== (float e1, NEW_ENUM& e2){ return (e2 == e1); } | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
#endif // __LOL_BASE_TYPES_H__ | #endif // __LOL_BASE_TYPES_H__ | ||||
@@ -113,9 +113,10 @@ public: | |||||
bool Start(); | bool Start(); | ||||
//Stop the threads | //Stop the threads | ||||
bool Stop(); | bool Stop(); | ||||
protected: | |||||
//Work stuff | //Work stuff | ||||
bool AddWork(ThreadJob* job); | bool AddWork(ThreadJob* job); | ||||
protected: | |||||
//Fetch Results | |||||
bool FetchResult(Array<ThreadJob*>& results); | bool FetchResult(Array<ThreadJob*>& results); | ||||
//Base thread work function | //Base thread work function | ||||
static void *BaseThreadWork(void* data); | static void *BaseThreadWork(void* data); | ||||
@@ -141,6 +142,8 @@ public: | |||||
char const *GetName() { return "<GenericThreadManager>"; } | char const *GetName() { return "<GenericThreadManager>"; } | ||||
//Work stuff | |||||
bool AddJob(ThreadJob* job) { return AddWork(job); } | |||||
bool GetWorkResult(Array<ThreadJob*>& results) | bool GetWorkResult(Array<ThreadJob*>& results) | ||||
{ | { | ||||
results += m_job_result; | results += m_job_result; | ||||
@@ -404,6 +404,7 @@ | |||||
<LolFxCompile Include="gpu\defaultmaterial.lolfx" /> | <LolFxCompile Include="gpu\defaultmaterial.lolfx" /> | ||||
<LolFxCompile Include="gpu\emptymaterial.lolfx" /> | <LolFxCompile Include="gpu\emptymaterial.lolfx" /> | ||||
<LolFxCompile Include="gpu\line.lolfx" /> | <LolFxCompile Include="gpu\line.lolfx" /> | ||||
<LolFxCompile Include="gpu\palette.lolfx" /> | |||||
<LolFxCompile Include="gpu\testmaterial.lolfx" /> | <LolFxCompile Include="gpu\testmaterial.lolfx" /> | ||||
<LolFxCompile Include="gpu\tile.lolfx" /> | <LolFxCompile Include="gpu\tile.lolfx" /> | ||||
<LolFxCompile Include="gradient.lolfx" /> | <LolFxCompile Include="gradient.lolfx" /> | ||||
@@ -732,6 +732,9 @@ | |||||
<LolFxCompile Include="easymesh\shinyflat.lolfx"> | <LolFxCompile Include="easymesh\shinyflat.lolfx"> | ||||
<Filter>easymesh</Filter> | <Filter>easymesh</Filter> | ||||
</LolFxCompile> | </LolFxCompile> | ||||
<LolFxCompile Include="gpu\palette.lolfx"> | |||||
<Filter>...</Filter> | |||||
</LolFxCompile> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<None Include="easymesh\easymesh-parser.y"> | <None Include="easymesh\easymesh-parser.y"> | ||||
@@ -23,6 +23,7 @@ | |||||
#include "lolgl.h" | #include "lolgl.h" | ||||
LOLFX_RESOURCE_DECLARE(tile); | LOLFX_RESOURCE_DECLARE(tile); | ||||
LOLFX_RESOURCE_DECLARE(palette); | |||||
LOLFX_RESOURCE_DECLARE(line); | LOLFX_RESOURCE_DECLARE(line); | ||||
namespace lol | namespace lol | ||||
@@ -72,9 +73,11 @@ private: | |||||
int m_tile_cam; | int m_tile_cam; | ||||
Array<Tile> m_tiles; | Array<Tile> m_tiles; | ||||
Array<Tile> m_palettes; | |||||
Array<Light *> m_lights; | Array<Light *> m_lights; | ||||
Shader *m_tile_shader; | Shader *m_tile_shader; | ||||
Shader *m_palette_shader; | |||||
VertexDeclaration *m_tile_vdecl; | VertexDeclaration *m_tile_vdecl; | ||||
Array<VertexBuffer *> m_tile_bufs; | Array<VertexBuffer *> m_tile_bufs; | ||||
@@ -97,6 +100,7 @@ Scene::Scene(ivec2 size) | |||||
data->m_tile_cam = -1; | data->m_tile_cam = -1; | ||||
data->m_tile_shader = 0; | data->m_tile_shader = 0; | ||||
data->m_palette_shader = 0; | |||||
data->m_tile_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position), | data->m_tile_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position), | ||||
VertexStream<vec2>(VertexUsage::TexCoord)); | VertexStream<vec2>(VertexUsage::TexCoord)); | ||||
@@ -194,7 +198,10 @@ void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float | |||||
t.scale = scale; | t.scale = scale; | ||||
t.angle = angle; | t.angle = angle; | ||||
data->m_tiles.Push(t); | |||||
if (tileset->GetPalette()) | |||||
data->m_palettes.Push(t); | |||||
else | |||||
data->m_tiles.Push(t); | |||||
} | } | ||||
void Scene::SetLineTime(float new_time) { data->m_new_line_time = new_time; } | void Scene::SetLineTime(float new_time) { data->m_new_line_time = new_time; } | ||||
@@ -270,7 +277,7 @@ void Scene::RenderTiles() // XXX: rename to Blit() | |||||
RenderContext rc; | RenderContext rc; | ||||
/* Early test if nothing needs to be rendered */ | /* Early test if nothing needs to be rendered */ | ||||
if (!data->m_tiles.Count()) | |||||
if (!data->m_tiles.Count() && !data->m_palettes.Count()) | |||||
return; | return; | ||||
rc.SetDepthFunc(DepthFunc::LessOrEqual); | rc.SetDepthFunc(DepthFunc::LessOrEqual); | ||||
@@ -283,71 +290,96 @@ void Scene::RenderTiles() // XXX: rename to Blit() | |||||
#endif | #endif | ||||
if (!data->m_tile_shader) | if (!data->m_tile_shader) | ||||
data->m_tile_shader = Shader::Create(LOLFX_RESOURCE_NAME(tile)); | data->m_tile_shader = Shader::Create(LOLFX_RESOURCE_NAME(tile)); | ||||
if (!data->m_palette_shader) | |||||
data->m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(palette)); | |||||
ShaderUniform uni_mat, uni_tex, uni_texsize; | |||||
ShaderAttrib attr_pos, attr_tex; | |||||
attr_pos = data->m_tile_shader->GetAttribLocation(VertexUsage::Position, 0); | |||||
attr_tex = data->m_tile_shader->GetAttribLocation(VertexUsage::TexCoord, 0); | |||||
data->m_tile_shader->Bind(); | |||||
for (int p = 0; p < 2; p++) | |||||
{ | |||||
Shader *shader = (p == 0) ? data->m_tile_shader : data->m_palette_shader; | |||||
Array<Tile>& tiles = (p == 0) ? data->m_tiles : data->m_palettes; | |||||
uni_mat = data->m_tile_shader->GetUniformLocation("u_projection"); | |||||
data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetProjection()); | |||||
uni_mat = data->m_tile_shader->GetUniformLocation("u_view"); | |||||
data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetView()); | |||||
uni_mat = data->m_tile_shader->GetUniformLocation("u_model"); | |||||
data->m_tile_shader->SetUniform(uni_mat, mat4(1.f)); | |||||
if (tiles.Count() == 0) | |||||
continue; | |||||
uni_tex = data->m_tile_shader->GetUniformLocation("u_texture"); | |||||
data->m_tile_shader->SetUniform(uni_tex, 0); | |||||
uni_texsize = data->m_tile_shader->GetUniformLocation("u_texsize"); | |||||
ShaderUniform uni_mat, uni_tex, uni_pal, uni_texsize; | |||||
ShaderAttrib attr_pos, attr_tex; | |||||
attr_pos = shader->GetAttribLocation(VertexUsage::Position, 0); | |||||
attr_tex = shader->GetAttribLocation(VertexUsage::TexCoord, 0); | |||||
for (int buf = 0, i = 0, n; i < data->m_tiles.Count(); i = n, buf += 2) | |||||
{ | |||||
/* Count how many quads will be needed */ | |||||
for (n = i + 1; n < data->m_tiles.Count(); n++) | |||||
if (data->m_tiles[i].tileset != data->m_tiles[n].tileset) | |||||
break; | |||||
shader->Bind(); | |||||
/* Create a vertex array object */ | |||||
VertexBuffer *vb1 = new VertexBuffer(6 * (n - i) * sizeof(vec3)); | |||||
vec3 *vertex = (vec3 *)vb1->Lock(0, 0); | |||||
VertexBuffer *vb2 = new VertexBuffer(6 * (n - i) * sizeof(vec2)); | |||||
vec2 *texture = (vec2 *)vb2->Lock(0, 0); | |||||
uni_mat = shader->GetUniformLocation("u_projection"); | |||||
shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetProjection()); | |||||
uni_mat = shader->GetUniformLocation("u_view"); | |||||
shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetView()); | |||||
uni_mat = shader->GetUniformLocation("u_model"); | |||||
shader->SetUniform(uni_mat, mat4(1.f)); | |||||
data->m_tile_bufs.Push(vb1); | |||||
data->m_tile_bufs.Push(vb2); | |||||
uni_tex = shader->GetUniformLocation("u_texture"); | |||||
uni_pal = data->m_palette_shader->GetUniformLocation("u_palette"); | |||||
uni_texsize = shader->GetUniformLocation("u_texsize"); | |||||
for (int j = i; j < n; j++) | |||||
for (int buf = 0, i = 0, n; i < tiles.Count(); i = n, buf += 2) | |||||
{ | { | ||||
data->m_tiles[i].tileset->BlitTile(data->m_tiles[j].id, | |||||
data->m_tiles[j].pos, data->m_tiles[j].o, | |||||
data->m_tiles[j].scale, data->m_tiles[j].angle, | |||||
vertex + 6 * (j - i), texture + 6 * (j - i)); | |||||
/* Count how many quads will be needed */ | |||||
for (n = i + 1; n < tiles.Count(); n++) | |||||
if (tiles[i].tileset != tiles[n].tileset) | |||||
break; | |||||
/* Create a vertex array object */ | |||||
VertexBuffer *vb1 = new VertexBuffer(6 * (n - i) * sizeof(vec3)); | |||||
vec3 *vertex = (vec3 *)vb1->Lock(0, 0); | |||||
VertexBuffer *vb2 = new VertexBuffer(6 * (n - i) * sizeof(vec2)); | |||||
vec2 *texture = (vec2 *)vb2->Lock(0, 0); | |||||
data->m_tile_bufs.Push(vb1); | |||||
data->m_tile_bufs.Push(vb2); | |||||
for (int j = i; j < n; j++) | |||||
{ | |||||
tiles[i].tileset->BlitTile(tiles[j].id, | |||||
tiles[j].pos, tiles[j].o, | |||||
tiles[j].scale, tiles[j].angle, | |||||
vertex + 6 * (j - i), texture + 6 * (j - i)); | |||||
} | |||||
vb1->Unlock(); | |||||
vb2->Unlock(); | |||||
/* Bind texture */ | |||||
if (tiles[i].tileset->GetPalette()) | |||||
{ | |||||
if (tiles[i].tileset->GetTexture()) | |||||
shader->SetUniform(uni_tex, tiles[i].tileset->GetTexture()->GetTextureUniform(), 0); | |||||
if (tiles[i].tileset->GetPalette()->GetTexture()) | |||||
shader->SetUniform(uni_pal, tiles[i].tileset->GetPalette()->GetTexture()->GetTextureUniform(), 1); | |||||
} | |||||
else | |||||
{ | |||||
shader->SetUniform(uni_tex, 0); | |||||
if (tiles[i].tileset->GetTexture()) | |||||
shader->SetUniform(uni_tex, tiles[i].tileset->GetTexture()->GetTextureUniform(), 0); | |||||
tiles[i].tileset->Bind(); | |||||
} | |||||
shader->SetUniform(uni_texsize, | |||||
(vec2)tiles[i].tileset->GetTextureSize()); | |||||
/* Bind vertex and texture coordinate buffers */ | |||||
data->m_tile_vdecl->Bind(); | |||||
data->m_tile_vdecl->SetStream(vb1, attr_pos); | |||||
data->m_tile_vdecl->SetStream(vb2, attr_tex); | |||||
/* Draw arrays */ | |||||
data->m_tile_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6); | |||||
data->m_tile_vdecl->Unbind(); | |||||
tiles[i].tileset->Unbind(); | |||||
} | } | ||||
vb1->Unlock(); | |||||
vb2->Unlock(); | |||||
tiles.Empty(); | |||||
/* Bind texture */ | |||||
data->m_tiles[i].tileset->Bind(); | |||||
data->m_tile_shader->SetUniform(uni_texsize, | |||||
(vec2)data->m_tiles[i].tileset->GetTextureSize()); | |||||
/* Bind vertex and texture coordinate buffers */ | |||||
data->m_tile_vdecl->Bind(); | |||||
data->m_tile_vdecl->SetStream(vb1, attr_pos); | |||||
data->m_tile_vdecl->SetStream(vb2, attr_tex); | |||||
/* Draw arrays */ | |||||
data->m_tile_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6); | |||||
data->m_tile_vdecl->Unbind(); | |||||
data->m_tiles[i].tileset->Unbind(); | |||||
shader->Unbind(); | |||||
} | } | ||||
data->m_tiles.Empty(); | |||||
data->m_tile_shader->Unbind(); | |||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
/* TODO */ | /* TODO */ | ||||
@@ -80,7 +80,9 @@ class FileData | |||||
#elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
/* FIXME: no modes, no error checking, no nothing */ | /* FIXME: no modes, no error checking, no nothing */ | ||||
stat(file.C(), &m_stat); | stat(file.C(), &m_stat); | ||||
m_fd = fopen(file.C(), (!force_binary) ? ("r") : ("rb")); | |||||
String access = (mode == FileAccess::Write) ? ("w") : ("r"); | |||||
if (force_binary) access += "b"; | |||||
m_fd = fopen(file.C(), access.C()); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -293,13 +295,13 @@ File::~File() | |||||
//-- | //-- | ||||
void File::Open(StreamType stream) | void File::Open(StreamType stream) | ||||
{ | { | ||||
return m_data->Open(stream); | |||||
m_data->Open(stream); | |||||
} | } | ||||
//-- | //-- | ||||
void File::Open(String const &file, FileAccess mode, bool force_binary) | void File::Open(String const &file, FileAccess mode, bool force_binary) | ||||
{ | { | ||||
return m_data->Open(file, mode, force_binary); | |||||
m_data->Open(file, mode, force_binary); | |||||
} | } | ||||
//-- | //-- | ||||
@@ -101,6 +101,8 @@ void *BaseThreadManager::BaseThreadWork(void* data) | |||||
void BaseThreadManager::TickGame(float seconds) | void BaseThreadManager::TickGame(float seconds) | ||||
{ | { | ||||
Entity::TickGame(seconds); | |||||
//Start if needed | //Start if needed | ||||
Start(); | Start(); | ||||
@@ -147,6 +147,7 @@ void TileSet::Init(char const *path, Image* image) | |||||
{ | { | ||||
m_data->m_name = String("<tileset> ") + path; | m_data->m_name = String("<tileset> ") + path; | ||||
m_palette = nullptr; | |||||
m_data->m_texture = 0; | m_data->m_texture = 0; | ||||
m_data->m_image = image; | m_data->m_image = image; | ||||
m_data->m_image_size = m_data->m_image->GetSize(); | m_data->m_image_size = m_data->m_image->GetSize(); | ||||
@@ -258,6 +259,31 @@ Texture const * TileSet::GetTexture() const | |||||
return m_data->m_texture; | return m_data->m_texture; | ||||
} | } | ||||
Image * TileSet::GetImage() | |||||
{ | |||||
return m_data->m_image; | |||||
} | |||||
Image const * TileSet::GetImage() const | |||||
{ | |||||
return m_data->m_image; | |||||
} | |||||
void TileSet::SetPalette(TileSet* palette) | |||||
{ | |||||
m_palette = palette; | |||||
} | |||||
TileSet* TileSet::GetPalette() | |||||
{ | |||||
return m_palette; | |||||
} | |||||
TileSet const* TileSet::GetPalette() const | |||||
{ | |||||
return m_palette; | |||||
} | |||||
void TileSet::Bind() | void TileSet::Bind() | ||||
{ | { | ||||
if (!m_data->m_image && m_data->m_texture) | if (!m_data->m_image && m_data->m_texture) | ||||
@@ -53,6 +53,11 @@ public: | |||||
Texture * GetTexture(); | Texture * GetTexture(); | ||||
Texture const * GetTexture() const; | Texture const * GetTexture() const; | ||||
Image * GetImage(); | |||||
Image const * GetImage() const; | |||||
void SetPalette(TileSet* palette); | |||||
TileSet* GetPalette(); | |||||
TileSet const * GetPalette() const; | |||||
ivec2 GetTextureSize() const; | ivec2 GetTextureSize() const; | ||||
void Bind(); | void Bind(); | ||||
void Unbind(); | void Unbind(); | ||||
@@ -64,6 +69,7 @@ private: | |||||
void Init(char const *path, Image* image); | void Init(char const *path, Image* image); | ||||
TileSetData* m_data; | TileSetData* m_data; | ||||
TileSet* m_palette; | |||||
}; | }; | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||