More work on REAL 3D object decode/render; Some OpenGL stuff
This commit is contained in:
BIN
DejaVuSans.ttf
Normal file
BIN
DejaVuSans.ttf
Normal file
Binary file not shown.
4
Makefile
4
Makefile
@@ -15,10 +15,10 @@ font2png_CXXSRCS ::= font2png.cc
|
||||
font2png_LIBS ::= -lpng
|
||||
|
||||
mvedecode_CXXSRCS ::= mvedecode.cc TreFile.cc IffFile.cc util.cc MveDecoder.cc exceptions.cc decompress.cc $(render_CXXSRCS) $(game_CXXSRCS)
|
||||
mvedecode_LIBS ::= -lSDL2 -lglbinding
|
||||
mvedecode_LIBS ::= -lSDL2 -lSDL2_ttf -lglbinding
|
||||
|
||||
objdecode_CXXSRCS ::= objdecode.cc TreFile.cc IffFile.cc util.cc ObjDecoder.cc exceptions.cc decompress.cc PaletteDecoder.cc $(render_CXXSRCS) $(game_CXXSRCS)
|
||||
objdecode_LIBS ::= -lSDL2 -lglbinding
|
||||
objdecode_LIBS ::= -lSDL2 -lSDL2_ttf -lglbinding
|
||||
|
||||
progs ::= iffexplore treexplore mvedecode objdecode
|
||||
|
||||
|
||||
@@ -32,6 +32,28 @@ ObjDecoder::ObjDecoder(uint8_t const* base, size_t length)
|
||||
}
|
||||
}
|
||||
|
||||
ObjDecoder::Triangles ObjDecoder::getTriangles(unsigned lvl) const
|
||||
{
|
||||
Triangles ret;
|
||||
for (auto idx : detailLevels_.at(lvl)) {
|
||||
if (idx < triangles_.size())
|
||||
ret.push_back(triangles_[idx]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObjDecoder::Quads ObjDecoder::getQuads(unsigned lvl) const
|
||||
{
|
||||
Quads ret;
|
||||
for (auto idx : detailLevels_.at(lvl)) {
|
||||
if (idx >= triangles_.size())
|
||||
ret.push_back(quads_[idx-triangles_.size()]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObjDecoder::parseOBJT_(IffFile::Form const& form)
|
||||
{
|
||||
}
|
||||
@@ -73,7 +95,7 @@ void ObjDecoder::parsePOLY_(IffFile::Form const& form)
|
||||
} else if (itForm.getSubtype() == "QUAD") {
|
||||
parseQUAD_(itForm);
|
||||
} else if (itForm.getSubtype() == "DETA") {
|
||||
// NYI
|
||||
parseDETA_(itForm);
|
||||
} else if (itForm.getSubtype() == "TXMS") {
|
||||
parseTXMS_(itForm);
|
||||
} else if (itForm.getSubtype() == "GRUP") {
|
||||
@@ -84,6 +106,8 @@ void ObjDecoder::parsePOLY_(IffFile::Form const& form)
|
||||
// NYI
|
||||
} else if (it->getType() == "XATR") {
|
||||
// NYI
|
||||
} else if (it->getType() == "SUPR") {
|
||||
// NYI
|
||||
} else
|
||||
throw FormatException{"Unknown POLY child " + it->getType()};
|
||||
}
|
||||
@@ -117,7 +141,8 @@ void ObjDecoder::parseTRIS_(IffFile::Form const& form)
|
||||
throw FormatException{"Unexpected FACE size"};
|
||||
auto numTriangles = face->getSize()/8;
|
||||
if (maps->getSize() != numTriangles*16)
|
||||
throw FormatException{"Unexpected MAPS size"};
|
||||
printf("WARNING: Unexpected MAPS size\n");
|
||||
// throw FormatException{"Unexpected MAPS size"};
|
||||
|
||||
for (unsigned i = 0;i < numTriangles;++i) {
|
||||
Triangle tri;
|
||||
@@ -135,6 +160,8 @@ void ObjDecoder::parseTRIS_(IffFile::Form const& form)
|
||||
// tri.vertIdx[2], tri.texCoords[2][0], tri.texCoords[2][1]);
|
||||
triangles_.push_back(tri);
|
||||
}
|
||||
|
||||
printf("TC: %lu\n", triangles_.size());
|
||||
}
|
||||
|
||||
void ObjDecoder::parseQUAD_(IffFile::Form const& form)
|
||||
@@ -162,7 +189,8 @@ void ObjDecoder::parseQUAD_(IffFile::Form const& form)
|
||||
throw FormatException{"Unexpected FACE size"};
|
||||
auto numQuads = face->getSize()/10;
|
||||
if (maps->getSize() != numQuads*20)
|
||||
throw FormatException{"Unexpected MAPS size"};
|
||||
printf("WARNING: Unexpected MAPS size\n");
|
||||
//throw FormatException{"Unexpected MAPS size"};
|
||||
|
||||
for (unsigned i = 0;i < numQuads;++i) {
|
||||
Quad quad;
|
||||
@@ -181,6 +209,33 @@ void ObjDecoder::parseQUAD_(IffFile::Form const& form)
|
||||
// quad.vertIdx[3], quad.texCoords[3][0], quad.texCoords[3][1]);
|
||||
quads_.push_back(quad);
|
||||
}
|
||||
|
||||
printf("QC: %lu\n", quads_.size());
|
||||
}
|
||||
|
||||
void ObjDecoder::parseDETA_(IffFile::Form const& form)
|
||||
{
|
||||
if (form.getChildCount() < 1)
|
||||
throw FormatException{"Unexpected child count in DETA"};
|
||||
|
||||
unsigned lvl = 0;
|
||||
for (auto it = form.childrenBegin();it != form.childrenEnd();++it) {
|
||||
if (it->getType().substr(0, 3) != "LVL")
|
||||
throw FormatException{"Unexpected child " + it->getType() + " in DETA"};
|
||||
if (std::stoi(it->getType().substr(3)) != lvl)
|
||||
throw FormatException{"Unexpected detail level"};
|
||||
|
||||
if (it->getSize() < 4)
|
||||
throw FormatException{"DETA child too small"};
|
||||
|
||||
// uint32_t unkown = readU32LE(it->begin());
|
||||
detailLevels_.emplace_back();
|
||||
for (size_t pos = 4;pos < it->getSize()-1;pos += 2)
|
||||
detailLevels_.back().push_back(readU16LE(it->begin()+pos));
|
||||
|
||||
printf("LVL %u: %lu entries\n", lvl, detailLevels_.back().size());
|
||||
++lvl;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjDecoder::parseTXMS_(IffFile::Form const& form)
|
||||
|
||||
@@ -50,14 +50,16 @@ public:
|
||||
return vertices_;
|
||||
}
|
||||
|
||||
Triangles const& getTriangles() const {
|
||||
return triangles_;
|
||||
}
|
||||
|
||||
Quads const& getQuads() const {
|
||||
return quads_;
|
||||
Triangles getTriangles(unsigned lvl = 0) const;
|
||||
Quads getQuads(unsigned lvl = 0) const;
|
||||
|
||||
unsigned getDetailLevels() const {
|
||||
return detailLevels_.size();
|
||||
}
|
||||
|
||||
using DetailLevel = std::vector<uint16_t>;
|
||||
using DetailLevels = std::vector<DetailLevel>;
|
||||
|
||||
Textures const& getTextures() const {
|
||||
return textures_;
|
||||
}
|
||||
@@ -74,6 +76,7 @@ private:
|
||||
void parsePOLY_(IffFile::Form const& form);
|
||||
void parseTRIS_(IffFile::Form const& form);
|
||||
void parseQUAD_(IffFile::Form const& form);
|
||||
void parseDETA_(IffFile::Form const& form);
|
||||
void parseTXMS_(IffFile::Form const& form);
|
||||
|
||||
Vertices vertices_;
|
||||
@@ -81,6 +84,7 @@ private:
|
||||
Quads quads_;
|
||||
Textures textures_;
|
||||
TextureAnimations texAnims_;
|
||||
DetailLevels detailLevels_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,10 @@ namespace game {
|
||||
frameRGB_.resize(0);
|
||||
}
|
||||
|
||||
bool GSMvePlay::handleEvent(SDL_Event& event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GSMvePlay::draw(unsigned delta_ms)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace game {
|
||||
~GSMvePlay() override;
|
||||
|
||||
void draw(unsigned delta_ms) override;
|
||||
|
||||
bool handleEvent(SDL_Event& event) override;
|
||||
private:
|
||||
MveDecoder::Movie& movie_;
|
||||
std::unique_ptr<render::Overlay> overlay_;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "ObjDecoder.hh"
|
||||
|
||||
#include "GSShowObject.hh"
|
||||
@@ -7,7 +9,10 @@ namespace game {
|
||||
GSShowObject::GSShowObject(render::Renderer& renderer, ObjDecoder& obj,
|
||||
PaletteDecoder& palt)
|
||||
: GameState(renderer), obj_(obj),
|
||||
object_(nullptr), delta_(0)
|
||||
object_(nullptr), delta_(0),
|
||||
rotatingUD_(Direction::None), rotatingRL_(Direction::None),
|
||||
moveRL_(Direction::None), moveFB_(Direction::None),
|
||||
rotUD_(0.0f), rotRL_(0.0f), posX_(0.0f), posZ_(0.0f)
|
||||
{
|
||||
object_ = std::make_unique<render::Object>(renderer, obj, palt);
|
||||
}
|
||||
@@ -15,11 +20,108 @@ namespace game {
|
||||
GSShowObject::~GSShowObject()
|
||||
{
|
||||
}
|
||||
|
||||
bool GSShowObject::handleEvent(SDL_Event& event)
|
||||
{
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_UP:
|
||||
rotatingUD_ = Direction::Up;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
rotatingUD_ = Direction::Down;
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
rotatingRL_ = Direction::Left;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
rotatingRL_ = Direction::Right;
|
||||
break;
|
||||
case SDLK_w:
|
||||
moveFB_ = Direction::Back;
|
||||
break;
|
||||
case SDLK_s:
|
||||
moveFB_ = Direction::Front;
|
||||
break;
|
||||
case SDLK_a:
|
||||
moveRL_ = Direction::Left;
|
||||
break;
|
||||
case SDLK_d:
|
||||
moveRL_ = Direction::Right;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_UP:
|
||||
if (rotatingUD_ == Direction::Up)
|
||||
rotatingUD_ = Direction::None;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if (rotatingUD_ == Direction::Down)
|
||||
rotatingUD_ = Direction::None;
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
if (rotatingRL_ == Direction::Left)
|
||||
rotatingRL_ = Direction::None;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if (rotatingRL_ == Direction::Right)
|
||||
rotatingRL_ = Direction::None;
|
||||
break;
|
||||
case SDLK_w:
|
||||
if (moveFB_ == Direction::Back)
|
||||
moveFB_ = Direction::None;
|
||||
break;
|
||||
case SDLK_s:
|
||||
if (moveFB_ == Direction::Front)
|
||||
moveFB_ = Direction::None;
|
||||
break;
|
||||
case SDLK_a:
|
||||
if (moveRL_ == Direction::Left)
|
||||
moveRL_ = Direction::None;
|
||||
break;
|
||||
case SDLK_d:
|
||||
if (moveRL_ == Direction::Right)
|
||||
moveRL_ = Direction::None;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GSShowObject::draw(unsigned delta_ms)
|
||||
{
|
||||
const float ROTATE_SCALE = 0.0005f, MOVE_SCALE = 50.0f;
|
||||
|
||||
delta_ += delta_ms;
|
||||
object_->setRot(delta_*0.0005f);
|
||||
|
||||
if (rotatingUD_ == Direction::Up)
|
||||
rotUD_ += delta_ms*ROTATE_SCALE;
|
||||
else if (rotatingUD_ == Direction::Down)
|
||||
rotUD_ -= delta_ms*ROTATE_SCALE;
|
||||
|
||||
if (rotatingRL_ == Direction::Left)
|
||||
rotRL_ += delta_ms*ROTATE_SCALE;
|
||||
else if (rotatingRL_ == Direction::Right)
|
||||
rotRL_ -= delta_ms*ROTATE_SCALE;
|
||||
|
||||
if (moveFB_ == Direction::Back)
|
||||
posZ_ += delta_ms*MOVE_SCALE;
|
||||
else if (moveFB_ == Direction::Front)
|
||||
posZ_ -= delta_ms*MOVE_SCALE;
|
||||
|
||||
if (moveRL_ == Direction::Left)
|
||||
posX_ += delta_ms*MOVE_SCALE;
|
||||
else if (moveRL_ == Direction::Right)
|
||||
posX_ -= delta_ms*MOVE_SCALE;
|
||||
|
||||
object_->setTransform(glm::translate(glm::vec3(posX_, 0.0f, posZ_))*
|
||||
glm::rotate(rotUD_, glm::vec3(1.0f, 0.0f, 0.0f))*
|
||||
glm::rotate(rotRL_, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||
object_->setAnimFrame((delta_/125)%8);
|
||||
object_->draw();
|
||||
}
|
||||
|
||||
@@ -18,11 +18,24 @@ namespace game {
|
||||
~GSShowObject() override;
|
||||
|
||||
void draw(unsigned delta_ms) override;
|
||||
|
||||
bool handleEvent(SDL_Event& event) override;
|
||||
private:
|
||||
ObjDecoder& obj_;
|
||||
std::unique_ptr<render::Object> object_;
|
||||
unsigned delta_;
|
||||
|
||||
enum class Direction {
|
||||
Up,
|
||||
Left,
|
||||
Down,
|
||||
Right,
|
||||
None,
|
||||
Front,
|
||||
Back
|
||||
};
|
||||
|
||||
Direction rotatingUD_, rotatingRL_, moveRL_, moveFB_;
|
||||
float rotUD_, rotRL_, posX_, posZ_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef WC3RE_GAME_GAMESTATE_HH__
|
||||
#define WC3RE_GAME_GAMESTATE_HH__
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace render {
|
||||
class Renderer;
|
||||
}
|
||||
@@ -15,8 +17,16 @@ namespace game {
|
||||
virtual ~GameState() {
|
||||
}
|
||||
|
||||
/* Update and draw
|
||||
* delta_ms is number of milliseconds since last call to draw
|
||||
*/
|
||||
virtual void draw(unsigned delta_ms) = 0;
|
||||
|
||||
/* Handle the event. Return true if the handler changes the current
|
||||
* gamestate, false otherwise.
|
||||
*/
|
||||
virtual bool handleEvent(SDL_Event& event) = 0;
|
||||
|
||||
protected:
|
||||
render::Renderer& renderer_;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef WC3RE_RENDER_DRAWABLE_HH__
|
||||
#define WC3RE_RENDER_DRAWABLE_HH__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace render {
|
||||
class Renderer;
|
||||
|
||||
@@ -18,6 +20,25 @@ namespace render {
|
||||
protected:
|
||||
Renderer& renderer_;
|
||||
};
|
||||
|
||||
class TransformDrawable : public Drawable {
|
||||
public:
|
||||
TransformDrawable(Renderer& renderer)
|
||||
: Drawable(renderer), transformMatrix_() {
|
||||
}
|
||||
|
||||
virtual void setTransform(glm::mat4 matrix) {
|
||||
transformMatrix_ = matrix;
|
||||
}
|
||||
|
||||
virtual glm::mat4 const& getTransform() const {
|
||||
return transformMatrix_;
|
||||
}
|
||||
|
||||
protected:
|
||||
glm::mat4 transformMatrix_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
119
render/Object.cc
119
render/Object.cc
@@ -39,40 +39,6 @@ namespace render {
|
||||
}
|
||||
};
|
||||
|
||||
const std::array<uint32_t, 256> vgaPalette = {
|
||||
0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400, 0xa8a8a8,
|
||||
0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc, 0xfcfc54, 0xfcfcfc,
|
||||
0x000000, 0x141414, 0x202020, 0x2c2c2c, 0x383838, 0x444444, 0x505050, 0x606060,
|
||||
0x707070, 0x808080, 0x909090, 0xa0a0a0, 0xb4b4b4, 0xc8c8c8, 0xe0e0e0, 0xfcfcfc,
|
||||
0x0000fc, 0x4000fc, 0x7c00fc, 0xbc00fc, 0xfc00fc, 0xfc00bc, 0xfc007c, 0xfc0040,
|
||||
0xfc0000, 0xfc4000, 0xfc7c00, 0xfcbc00, 0xfcfc00, 0xbcfc00, 0x7cfc00, 0x40fc00,
|
||||
0x00fc00, 0x00fc40, 0x00fc7c, 0x00fcbc, 0x00fcfc, 0x00bcfc, 0x007cfc, 0x0040fc,
|
||||
0x7c7cfc, 0x9c7cfc, 0xbc7cfc, 0xdc7cfc, 0xfc7cfc, 0xfc7cdc, 0xfc7cbc, 0xfc7c9c,
|
||||
0xfc7c7c, 0xfc9c7c, 0xfcbc7c, 0xfcdc7c, 0xfcfc7c, 0xdcfc7c, 0xbcfc7c, 0x9cfc7c,
|
||||
0x7cfc7c, 0x7cfc9c, 0x7cfcbc, 0x7cfcdc, 0x7cfcfc, 0x7cdcfc, 0x7cbcfc, 0x7c9cfc,
|
||||
0xb4b4fc, 0xc4b4fc, 0xd8b4fc, 0xe8b4fc, 0xfcb4fc, 0xfcb4e8, 0xfcb4d8, 0xfcb4c4,
|
||||
0xfcb4b4, 0xfcc4b4, 0xfcd8b4, 0xfce8b4, 0xfcfcb4, 0xe8fcb4, 0xd8fcb4, 0xc4fcb4,
|
||||
0xb4fcb4, 0xb4fcc4, 0xb4fcd8, 0xb4fce8, 0xb4fcfc, 0xb4e8fc, 0xb4d8fc, 0xb4c4fc,
|
||||
0x000070, 0x1c0070, 0x380070, 0x540070, 0x700070, 0x700054, 0x700038, 0x70001c,
|
||||
0x700000, 0x701c00, 0x703800, 0x705400, 0x707000, 0x547000, 0x387000, 0x1c7000,
|
||||
0x007000, 0x00701c, 0x007038, 0x007054, 0x007070, 0x005470, 0x003870, 0x001c70,
|
||||
0x383870, 0x443870, 0x543870, 0x603870, 0x703870, 0x703860, 0x703854, 0x703844,
|
||||
0x703838, 0x704438, 0x705438, 0x706038, 0x707038, 0x607038, 0x547038, 0x447038,
|
||||
0x387038, 0x387044, 0x387054, 0x387060, 0x387070, 0x386070, 0x385470, 0x384470,
|
||||
0x505070, 0x585070, 0x605070, 0x685070, 0x705070, 0x705068, 0x705060, 0x705058,
|
||||
0x705050, 0x705850, 0x706050, 0x706850, 0x707050, 0x687050, 0x607050, 0x587050,
|
||||
0x507050, 0x507058, 0x507060, 0x507068, 0x507070, 0x506870, 0x506070, 0x505870,
|
||||
0x000040, 0x100040, 0x200040, 0x300040, 0x400040, 0x400030, 0x400020, 0x400010,
|
||||
0x400000, 0x401000, 0x402000, 0x403000, 0x404000, 0x304000, 0x204000, 0x104000,
|
||||
0x004000, 0x004010, 0x004020, 0x004030, 0x004040, 0x003040, 0x002040, 0x001040,
|
||||
0x202040, 0x282040, 0x302040, 0x382040, 0x402040, 0x402038, 0x402030, 0x402028,
|
||||
0x402020, 0x402820, 0x403020, 0x403820, 0x404020, 0x384020, 0x304020, 0x284020,
|
||||
0x204020, 0x204028, 0x204030, 0x204038, 0x204040, 0x203840, 0x203040, 0x202840,
|
||||
0x2c2c40, 0x302c40, 0x342c40, 0x3c2c40, 0x402c40, 0x402c3c, 0x402c34, 0x402c30,
|
||||
0x402c2c, 0x40302c, 0x40342c, 0x403c2c, 0x40402c, 0x3c402c, 0x34402c, 0x30402c,
|
||||
0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040, 0x2c3c40, 0x2c3440, 0x2c3040,
|
||||
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000};
|
||||
|
||||
struct TexAtlasInfo {
|
||||
unsigned x, y;
|
||||
unsigned alignWidth, alignHeight;
|
||||
@@ -89,27 +55,42 @@ namespace render {
|
||||
std::tie(maxTex, maxLayers) = getGLTextureMaximums();
|
||||
printf("Maximum texture size: %d, maximum array texture layers: %d\n", maxTex, maxLayers);
|
||||
|
||||
// If the atlas gets too large we may have problems with texture coordinate precision
|
||||
if (maxTex > 8192)
|
||||
maxTex = 8192;
|
||||
|
||||
unsigned minSize = std::numeric_limits<unsigned>::max();
|
||||
unsigned accumWidth = 0, maxHeight = 0;
|
||||
for (auto& tex : texs) {
|
||||
minSize = std::min<unsigned>(minSize, std::min<unsigned>(tex.width, tex.height));
|
||||
accumWidth += tex.width;
|
||||
maxHeight = std::max<unsigned>(maxHeight, tex.height);
|
||||
}
|
||||
unsigned minLg = ilog2(minSize), minPow2 = (1<<minLg);
|
||||
if (minPow2 < minSize) {
|
||||
++minLg;
|
||||
minPow2 <<= 1;
|
||||
}
|
||||
if (minPow2 < 32) {
|
||||
minPow2 = 32;
|
||||
minLg = 5;
|
||||
}
|
||||
printf("Minimum texture size %u, using %u alignment and %u mipmap levels\n",
|
||||
minSize, minPow2, minLg);
|
||||
|
||||
// Try to get an aprox. square atlas
|
||||
unsigned accumWidth2 = 1<<(ilog2(sqrt(accumWidth*maxHeight)));
|
||||
printf("Squarified target width %u\n", accumWidth2);
|
||||
|
||||
std::vector<TexAtlasInfo> ret;
|
||||
unsigned xpos = 0, ypos = 0, lineMaxHeight = 0;
|
||||
unsigned xpos = 0, ypos = 0, lineMaxHeight = 0, maxWidth = 0;
|
||||
for (auto& tex : texs) {
|
||||
unsigned alignWidth = (tex.width%minPow2 == 0)?tex.width:tex.width+(minPow2-tex.width%minPow2);
|
||||
unsigned alignHeight = (tex.height%minPow2 == 0)?tex.height:tex.height+(minPow2-tex.height%minPow2);
|
||||
|
||||
if (xpos + alignWidth > static_cast<unsigned>(maxTex)) {
|
||||
if (xpos + alignWidth > accumWidth2) {
|
||||
ypos += lineMaxHeight;
|
||||
maxWidth = std::max(maxWidth, xpos);
|
||||
lineMaxHeight = 0;
|
||||
xpos = 0;
|
||||
}
|
||||
@@ -122,12 +103,12 @@ namespace render {
|
||||
lineMaxHeight = std::max<unsigned>(lineMaxHeight, alignHeight);
|
||||
xpos += alignWidth;
|
||||
}
|
||||
unsigned atlasWidth = xpos, atlasHeight = ypos+lineMaxHeight;
|
||||
unsigned atlasWidth = std::max(xpos, maxWidth), atlasHeight = ypos+lineMaxHeight;
|
||||
printf("Texture atlas size: %ux%u\n", atlasWidth, atlasHeight);
|
||||
|
||||
TextureResource tex = create2DTexture(atlasWidth, atlasHeight, false, minLg+1);
|
||||
TextureResource tex = create2DTexture(atlasWidth, atlasHeight, true, minLg+1);
|
||||
|
||||
std::vector<uint8_t> pixels(atlasWidth*atlasHeight*3);
|
||||
std::vector<uint8_t> pixels(atlasWidth*atlasHeight*4);
|
||||
// Copy textures into atlas
|
||||
for (auto& info : ret) {
|
||||
info.xofs = (info.x+0.5f)/atlasWidth;
|
||||
@@ -153,13 +134,21 @@ namespace render {
|
||||
col = info.tex.pixels[info.tex.height*info.tex.width - 1];
|
||||
}
|
||||
}
|
||||
pixels[(y+info.y)*atlasWidth*3+(info.x+x)*3] = palt[col*3]; //vgaPalette[col]>>16;
|
||||
pixels[(y+info.y)*atlasWidth*3+(info.x+x)*3+1] = palt[col*3+1]; //vgaPalette[col]>>8;
|
||||
pixels[(y+info.y)*atlasWidth*3+(info.x+x)*3+2] = palt[col*3+2]; //vgaPalette[col];
|
||||
if (col == 0xff) {
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4] = 0u;
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+1] = 0u;
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+2] = 0u;
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+3] = 0u;
|
||||
} else {
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4] = palt[col*3+2]; //vgaPalette[col]>>16;
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+1] = palt[col*3+1]; //vgaPalette[col]>>8;
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+2] = palt[col*3]; //vgaPalette[col];
|
||||
pixels[(y+info.y)*atlasWidth*4+(info.x+x)*4+3] = 255u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlasWidth, atlasHeight, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlasWidth, atlasHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
return std::make_tuple(std::move(ret), std::move(tex));
|
||||
@@ -177,7 +166,7 @@ namespace render {
|
||||
if (width%4 != 0)
|
||||
width += 4 - (width%4);
|
||||
unsigned height = texAnim.height;
|
||||
TextureResource tex = create2DArrayTexture(width, height, texAnim.frames, false);
|
||||
TextureResource tex = create2DArrayTexture(width, height, texAnim.frames, true);
|
||||
|
||||
AnimTexInfo animInfo;
|
||||
animInfo.xofs = 0.5f/width;
|
||||
@@ -185,21 +174,29 @@ namespace render {
|
||||
animInfo.xscale = (texAnim.width-1.0f)/(width*texAnim.width);
|
||||
animInfo.yscale = (texAnim.height-1.0f)/(height*texAnim.height);
|
||||
|
||||
std::vector<uint8_t> pixels(texAnim.frames*width*height*3);
|
||||
std::vector<uint8_t> pixels(texAnim.frames*width*height*4);
|
||||
|
||||
for (unsigned f = 0;f < texAnim.frames;++f) {
|
||||
for (unsigned y = 0;y < texAnim.height;++y) {
|
||||
for (unsigned x = 0;x < texAnim.width;++x) {
|
||||
unsigned col = texAnim.pixels[f][y*texAnim.width+x];
|
||||
|
||||
pixels[f*width*height*3+y*width*3+x*3] = palt[col*3];
|
||||
pixels[f*width*height*3+y*width*3+x*3+1] = palt[col*3+1];
|
||||
pixels[f*width*height*3+y*width*3+x*3+2] = palt[col*3+2];
|
||||
|
||||
if (col == 0xff) {
|
||||
pixels[f*width*height*4+y*width*4+x*4] = 0u;
|
||||
pixels[f*width*height*4+y*width*4+x*4+1] = 0u;
|
||||
pixels[f*width*height*4+y*width*4+x*4+2] = 0u;
|
||||
pixels[f*width*height*4+y*width*4+x*4+3] = 0u;
|
||||
} else {
|
||||
pixels[f*width*height*4+y*width*4+x*4] = palt[col*3+2];
|
||||
pixels[f*width*height*4+y*width*4+x*4+1] = palt[col*3+1];
|
||||
pixels[f*width*height*4+y*width*4+x*4+2] = palt[col*3];
|
||||
pixels[f*width*height*4+y*width*4+x*4+3] = 255u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, texAnim.frames,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
|
||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
|
||||
return std::make_tuple(animInfo, std::move(tex));
|
||||
@@ -209,8 +206,8 @@ namespace render {
|
||||
genVertexAttribs(ObjDecoder& obj, std::vector<TexAtlasInfo>& atlasInfo,
|
||||
AnimTexInfo *animTex = nullptr)
|
||||
{
|
||||
auto& tris = obj.getTriangles();
|
||||
auto& quads = obj.getQuads();
|
||||
auto tris = obj.getTriangles();
|
||||
auto quads = obj.getQuads();
|
||||
|
||||
// Deduplicate vertex attributes, track indices
|
||||
std::map<VertexAttribs, size_t> vertexAttribsMap;
|
||||
@@ -302,7 +299,7 @@ namespace render {
|
||||
}
|
||||
|
||||
Object::Object(Renderer& renderer, ObjDecoder& obj, PaletteDecoder& palt)
|
||||
: Drawable(renderer),
|
||||
: TransformDrawable(renderer),
|
||||
vbo_(), rot_(0.0f), animFrame_(0)
|
||||
{
|
||||
// Acquire shader
|
||||
@@ -362,9 +359,9 @@ namespace render {
|
||||
2*numIndices_,
|
||||
indices.data());
|
||||
|
||||
mvp_ = glm::perspectiveFov(75.0f, static_cast<float>(renderer.getWidth()),
|
||||
vp_ = glm::perspectiveFov(75.0f, static_cast<float>(renderer.getWidth()),
|
||||
static_cast<float>(renderer.getHeight()),
|
||||
1000.f, 800000.0f) *
|
||||
7500.f, 800000.0f) *
|
||||
glm::lookAt(glm::vec3(0.0f, 0.0f, 200000),
|
||||
glm::vec3(0.0f, 0.0f, 0),
|
||||
glm::vec3(0, 1, 0));
|
||||
@@ -386,22 +383,24 @@ namespace render {
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
useProgram(program_);
|
||||
glUniformMatrix4fv(0, 1, GL_FALSE,
|
||||
glm::value_ptr(mvp_*glm::rotate(rot_, glm::vec3(1.0f, 0.0f, 0.0f))));
|
||||
glUniform1i(1, 0);
|
||||
glUniform1i(2, 1);
|
||||
glm::value_ptr(vp_));
|
||||
glUniformMatrix4fv(1, 1, GL_FALSE,
|
||||
glm::value_ptr(transformMatrix_));
|
||||
glUniform1i(2, 0);
|
||||
glUniform1i(3, 1);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex_);
|
||||
if (texAnim_) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texAnim_);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1ui(3, animFrame_);
|
||||
glUniform1ui(4, animFrame_);
|
||||
}
|
||||
|
||||
glBindVertexArray(vertexArray_);
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, maxIndex_,
|
||||
numIndices_, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(indexOfs_));
|
||||
numIndices_, GL_UNSIGNED_SHORT, vbo_.getOfs(indexOfs_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,10 @@ class ObjDecoder;
|
||||
class PaletteDecoder;
|
||||
|
||||
namespace render {
|
||||
class Object : public Drawable {
|
||||
class Object : public TransformDrawable {
|
||||
public:
|
||||
Object(Renderer& renderer, ObjDecoder& obj, PaletteDecoder& palt);
|
||||
|
||||
void setRot(float rot) {
|
||||
rot_ = rot;
|
||||
}
|
||||
|
||||
void setAnimFrame(unsigned frame) {
|
||||
animFrame_ = frame;
|
||||
}
|
||||
@@ -31,7 +27,7 @@ namespace render {
|
||||
gl::GLuint program_;
|
||||
VBOManager::VBOAlloc vbo_;
|
||||
TextureResource tex_, texAnim_;
|
||||
glm::mat4 mvp_;
|
||||
glm::mat4 vp_;
|
||||
uintptr_t indexOfs_;
|
||||
size_t numIndices_, maxIndex_;
|
||||
float rot_;
|
||||
|
||||
@@ -17,11 +17,11 @@ namespace render {
|
||||
struct VertexAttribs {
|
||||
int16_t vertex[2];
|
||||
uint16_t texCoords[2];
|
||||
} __attribute__((__packed__));
|
||||
};
|
||||
}
|
||||
|
||||
Overlay::Overlay(Renderer& renderer, int width, int height, int left, int top, int intWidth, int intHeight)
|
||||
: Drawable(renderer), texture_(create2DTexture(intWidth, intHeight, false, 1)),
|
||||
: Drawable(renderer), texture_(create2DTexture(intWidth, intHeight, true, 1)),
|
||||
vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)),
|
||||
width_(width), height_(height), top_(top), left_(left), intWidth_(intWidth), intHeight_(intHeight)
|
||||
{
|
||||
@@ -71,22 +71,32 @@ namespace render {
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
void Overlay::clear()
|
||||
{
|
||||
if (SDL_GL_ExtensionSupported("GL_ARB_clear_texture"))
|
||||
glClearTexImage(texture_, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
|
||||
else {
|
||||
std::vector<uint8_t> zeros(intWidth_*intHeight_*4, 0u);
|
||||
setContentBGRA8(zeros.data());
|
||||
}
|
||||
}
|
||||
|
||||
void Overlay::setContent(SDL_Surface *content)
|
||||
{
|
||||
if (!content ||
|
||||
(content->h != intHeight_) ||
|
||||
(content->w != intWidth_))
|
||||
(content->h > intHeight_) ||
|
||||
(content->w > intWidth_))
|
||||
throw Exception{"null or mismatched surface"};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
|
||||
if (content->format->format != SDL_PIXELFORMAT_RGB24) {
|
||||
SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_RGB24, 0));
|
||||
if (content->format->format != SDL_PIXELFORMAT_ARGB8888) {
|
||||
SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0));
|
||||
if (!tmpSurf)
|
||||
throw SDLException{};
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_RGB, GL_UNSIGNED_BYTE, tmpSurf->pixels);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels);
|
||||
} else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, content->w, content->h, GL_RGB, GL_UNSIGNED_BYTE, content->pixels);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels);
|
||||
}
|
||||
|
||||
void Overlay::setContentRGB8(void *data)
|
||||
@@ -94,4 +104,10 @@ namespace render {
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
void Overlay::setContentBGRA8(void *data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,11 @@ namespace render {
|
||||
|
||||
void draw() override;
|
||||
|
||||
void clear();
|
||||
|
||||
void setContent(SDL_Surface *content);
|
||||
void setContentRGB8(void *data);
|
||||
void setContentBGRA8(void *data);
|
||||
private:
|
||||
TextureResource texture_;
|
||||
VertexArrayResource vertexArray_;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include <glbinding/gl/gl.h>
|
||||
#include <glbinding/Binding.h>
|
||||
#include <glbinding/callbacks.h>
|
||||
#include <glbinding/Meta.h>
|
||||
|
||||
#include "Renderer.hh"
|
||||
#include "GlResource.hh"
|
||||
#include "game/GameState.hh"
|
||||
#include "exceptions.hh"
|
||||
#include "Overlay.hh"
|
||||
|
||||
using namespace gl;
|
||||
|
||||
@@ -57,10 +59,12 @@ namespace render {
|
||||
|
||||
|
||||
Renderer::Renderer()
|
||||
: sdlInit_(), window_(), context_()
|
||||
: sdlInit_(), ttfInit_(), window_(), context_()
|
||||
{
|
||||
glbinding::Binding::initialize();
|
||||
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
@@ -82,46 +86,95 @@ namespace render {
|
||||
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
int depth, stencil, aa, major, minor;
|
||||
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
|
||||
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil);
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &aa);
|
||||
int major, minor;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
|
||||
|
||||
printf("Depth: %d, Stencil: %d, AA: %d, GL %d.%d\n",
|
||||
depth, stencil, aa, major, minor);
|
||||
printf("GL %d.%d\n",
|
||||
major, minor);
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glViewport(0, 0, width_, height_);
|
||||
|
||||
fpsFont_.reset(TTF_OpenFont("DejaVuSans.ttf", 10));
|
||||
if (!fpsFont_)
|
||||
throw TTFException{};
|
||||
|
||||
SDL_Color white;
|
||||
white.r = 255;
|
||||
white.g = 255;
|
||||
white.b = 255;
|
||||
white.a = 255;
|
||||
SDLSurfaceUPtr fpsSurf(TTF_RenderUTF8_Blended(fpsFont_.get(), "0 FPS", white));
|
||||
if (!fpsSurf)
|
||||
throw TTFException{};
|
||||
|
||||
fpsOverlay_ = std::make_unique<Overlay>(*this, fpsSurf->w*2, fpsSurf->h, 0, 0, fpsSurf->w*2, fpsSurf->h);
|
||||
fpsOverlay_->clear();
|
||||
fpsOverlay_->setContent(fpsSurf.get());
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::run()
|
||||
{
|
||||
bool close = false;
|
||||
|
||||
auto last = SDL_GetTicks();
|
||||
unsigned fpsTime = 0, fpsCount = 0, lastFps = 0;
|
||||
|
||||
while (!close && gamestates_.size()) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym == SDLK_q)
|
||||
if (event.key.keysym.sym == SDLK_q) {
|
||||
close = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_CLOSE)
|
||||
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||
close = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (gamestates_.back()->handleEvent(event))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
auto now = SDL_GetTicks();
|
||||
auto delta = now-last;
|
||||
|
||||
gamestates_.back()->draw(delta);
|
||||
|
||||
gamestates_.back()->draw(now-last);
|
||||
if (fpsTime+delta > 1000) {
|
||||
if (fpsCount+1 != lastFps) {
|
||||
std::string fpsText{std::to_string(fpsCount+1) + " FPS"};
|
||||
SDLSurfaceUPtr fpsSurf(TTF_RenderUTF8_Blended(fpsFont_.get(), fpsText.c_str(),
|
||||
SDL_Color({255, 255, 255, 255})));
|
||||
if (!fpsSurf)
|
||||
throw TTFException{};
|
||||
fpsOverlay_->clear();
|
||||
fpsOverlay_->setContent(fpsSurf.get());
|
||||
lastFps = fpsCount+1;
|
||||
}
|
||||
fpsCount = 0;
|
||||
fpsTime = 0;
|
||||
} else {
|
||||
++fpsCount;
|
||||
fpsTime += delta;
|
||||
}
|
||||
|
||||
fpsOverlay_->draw();
|
||||
|
||||
SDL_GL_SwapWindow(window_.get());
|
||||
last = now;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef WC3RE_RENDER_RENDERER_HH__
|
||||
#define WC3RE_RENDER_RENDERER_HH__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "sdlutil.hh"
|
||||
|
||||
namespace game {
|
||||
@@ -8,10 +10,13 @@ namespace game {
|
||||
}
|
||||
|
||||
namespace render {
|
||||
class Overlay;
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer();
|
||||
|
||||
~Renderer();
|
||||
|
||||
void run();
|
||||
|
||||
int getWidth() const;
|
||||
@@ -21,10 +26,13 @@ namespace render {
|
||||
std::unique_ptr<game::GameState> popGS();
|
||||
private:
|
||||
SDLInit sdlInit_;
|
||||
TTFInit ttfInit_;
|
||||
SDLWindowUPtr window_;
|
||||
SDLGLContext context_;
|
||||
std::vector<std::unique_ptr<game::GameState> > gamestates_;
|
||||
int width_, height_;
|
||||
TTFFontUPtr fpsFont_;
|
||||
std::unique_ptr<Overlay> fpsOverlay_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace render {
|
||||
class VBO;
|
||||
|
||||
static const size_t default_size = 1048576;
|
||||
static const size_t alignment = 8;
|
||||
static const size_t alignment = 4;
|
||||
static const gl::GLenum default_type = gl::GL_STATIC_DRAW;
|
||||
|
||||
class AllocFailed {};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "exceptions.hh"
|
||||
|
||||
@@ -19,6 +20,17 @@ namespace render {
|
||||
return "SDLException: " + msg_;
|
||||
}
|
||||
};
|
||||
|
||||
class TTFException : public Exception {
|
||||
public:
|
||||
TTFException() : Exception(TTF_GetError()) {
|
||||
}
|
||||
|
||||
std::string toString() const override {
|
||||
return "TTFException: " + msg_;
|
||||
}
|
||||
};
|
||||
|
||||
// Some helpers to C++11-ify SDL
|
||||
|
||||
struct SDLSurfaceDeleter {
|
||||
@@ -36,6 +48,14 @@ namespace render {
|
||||
};
|
||||
|
||||
using SDLWindowUPtr = std::unique_ptr<SDL_Window, SDLWindowDeleter>;
|
||||
|
||||
struct TTFFontDeleter {
|
||||
void operator()(TTF_Font* font) const {
|
||||
TTF_CloseFont(font);
|
||||
}
|
||||
};
|
||||
|
||||
using TTFFontUPtr = std::unique_ptr<TTF_Font, TTFFontDeleter>;
|
||||
|
||||
|
||||
class SDLSurfaceScopedLock {
|
||||
@@ -94,6 +114,23 @@ namespace render {
|
||||
}
|
||||
};
|
||||
|
||||
// RAII wrapper for TTF_Init
|
||||
class TTFInit {
|
||||
public:
|
||||
TTFInit() {
|
||||
if (TTF_Init() < 0)
|
||||
throw TTFException{};
|
||||
}
|
||||
|
||||
TTFInit(TTFInit const& copy) = delete;
|
||||
TTFInit& operator=(TTFInit const& copy) = delete;
|
||||
|
||||
~TTFInit() {
|
||||
TTF_Quit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// RAII wrapper for SDL_GLContext
|
||||
class SDLGLContext {
|
||||
public:
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
#version 330 core
|
||||
#extension GL_ARB_explicit_uniform_location : enable
|
||||
#extension GL_ARB_conservative_depth : enable
|
||||
|
||||
layout(location = 1) uniform sampler2D texBase;
|
||||
layout(location = 2) uniform sampler2DArray texAnim;
|
||||
layout(location = 3) uniform uint animFrame;
|
||||
layout(location = 2) uniform sampler2D texBase;
|
||||
layout(location = 3) uniform sampler2DArray texAnim;
|
||||
layout(location = 4) uniform uint animFrame;
|
||||
layout(location = 5) uniform vec3 IDcolor;
|
||||
|
||||
in vec2 fragTC;
|
||||
flat in uint fragUseAnimTex;
|
||||
|
||||
out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 IDcolor_out;
|
||||
layout(depth_unchanged) out float gl_FragDepth;
|
||||
|
||||
void main(void) {
|
||||
vec2 texDx = dFdx(fragTC);
|
||||
vec2 texDy = dFdy(fragTC);
|
||||
|
||||
if (fragUseAnimTex > 0u)
|
||||
color = textureGrad(texAnim, vec3(fragTC, animFrame), texDx, texDy);
|
||||
//color = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
else
|
||||
color = textureGrad(texBase, fragTC, texDx, texDy);
|
||||
|
||||
if (color.w < 0.5)
|
||||
discard;
|
||||
|
||||
IDcolor_out = vec4(IDcolor, 1.0);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
#extension GL_ARB_explicit_uniform_location : enable
|
||||
|
||||
layout(location = 0) uniform mat4 mvp_matrix;
|
||||
layout(location = 0) uniform mat4 vp_matrix;
|
||||
layout(location = 1) uniform mat4 m_matrix;
|
||||
|
||||
layout(location = 0) in vec3 vertex;
|
||||
layout(location = 1) in vec2 vertexTC;
|
||||
@@ -12,8 +13,8 @@ out vec2 fragTC;
|
||||
flat out uint fragUseAnimTex;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = mvp_matrix * vec4(vertex, 1.0);
|
||||
gl_Position = vp_matrix * m_matrix * vec4(vertex, 1.0);
|
||||
|
||||
fragTC = vertexTC;
|
||||
fragUseAnimTex = useAnimTex;
|
||||
fragTC = vertexTC;
|
||||
fragUseAnimTex = useAnimTex;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@ layout(location = 1) uniform sampler2D texBase;
|
||||
|
||||
in vec2 fragTC;
|
||||
|
||||
out vec4 color;
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main(void) {
|
||||
color = texture(texBase, fragTC);
|
||||
vec4 texCol = texture(texBase, fragTC);
|
||||
color = texCol*texCol.w;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user