Browse Source

integrate shadows

feature/replace-renderer
Martin Dørum 3 years ago
parent
commit
1f787baf78

+ 22
- 0
libcygnet/include/cygnet/Renderer.h View File

GLuint tex; GLuint tex;
}; };


struct RenderChunkShadow {
GLuint tex;
};

struct RenderSprite { struct RenderSprite {
GLuint tex; GLuint tex;
SwanCommon::Vec2 scale; SwanCommon::Vec2 scale;
~Renderer(); ~Renderer();


void drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos); void drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos);
void drawChunkShadow(RenderChunkShadow shadow, SwanCommon::Vec2 pos);
void drawTile(TileID id, Mat3gf mat); void drawTile(TileID id, Mat3gf mat);
void drawSprite(RenderSprite sprite, Mat3gf mat, int y = 0); void drawSprite(RenderSprite sprite, Mat3gf mat, int y = 0);
void drawRect(SwanCommon::Vec2 pos, SwanCommon::Vec2 size); void drawRect(SwanCommon::Vec2 pos, SwanCommon::Vec2 size);
void modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id); void modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id);
void destroyChunk(RenderChunk chunk); void destroyChunk(RenderChunk chunk);


RenderChunkShadow createChunkShadow(
uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]);
void modifyChunkShadow(
RenderChunkShadow shadow,
uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]);
void destroyChunkShadow(RenderChunkShadow chunk);

RenderSprite createSprite(void *data, int width, int height, int fh); RenderSprite createSprite(void *data, int width, int height, int fh);
RenderSprite createSprite(void *data, int width, int height); RenderSprite createSprite(void *data, int width, int height);
void destroySprite(RenderSprite sprite); void destroySprite(RenderSprite sprite);
RenderChunk chunk; RenderChunk chunk;
}; };


struct DrawShadow {
SwanCommon::Vec2 pos;
RenderChunkShadow shadow;
};

struct DrawTile { struct DrawTile {
Mat3gf transform; Mat3gf transform;
TileID id; TileID id;
std::unique_ptr<RendererState> state_; std::unique_ptr<RendererState> state_;


std::vector<DrawChunk> drawChunks_; std::vector<DrawChunk> drawChunks_;
std::vector<DrawShadow> drawChunkShadows_;
std::vector<DrawTile> drawTiles_; std::vector<DrawTile> drawTiles_;
std::vector<DrawSprite> drawSprites_; std::vector<DrawSprite> drawSprites_;
std::vector<DrawRect> drawRects_; std::vector<DrawRect> drawRects_;
drawChunks_.push_back({pos, chunk}); drawChunks_.push_back({pos, chunk});
} }


inline void Renderer::drawChunkShadow(RenderChunkShadow shadow, SwanCommon::Vec2 pos) {
drawChunkShadows_.push_back({pos, shadow});
}

inline void Renderer::drawTile(TileID id, Mat3gf mat) { inline void Renderer::drawTile(TileID id, Mat3gf mat) {
drawTiles_.push_back({mat, id}); drawTiles_.push_back({mat, id});
} }

+ 3
- 0
libcygnet/include/cygnet/shaders.h View File

extern const char *chunkVx; extern const char *chunkVx;
extern const char *chunkFr; extern const char *chunkFr;


extern const char *chunkShadowVx;
extern const char *chunkShadowFr;

extern const char *tileVx; extern const char *tileVx;
extern const char *tileFr; extern const char *tileFr;



+ 115
- 0
libcygnet/src/Renderer.cc View File

} }
}; };


struct ChunkShadowProg: public GlProgram {
template<typename... T>
ChunkShadowProg(const T &... shaders): GlProgram(shaders...) { init(); }
~ChunkShadowProg() { deinit(); }

GLint camera = uniformLoc("camera");
GLint pos = uniformLoc("pos");
GLint vertex = attribLoc("vertex");
GLint tex = uniformLoc("tex");

GLuint vbo;

static constexpr float ch = (float)SwanCommon::CHUNK_HEIGHT;
static constexpr float cw = (float)SwanCommon::CHUNK_WIDTH;
static constexpr GLfloat vertexes[] = {
0.0f, 0.0f, // pos 0: top left
0.0f, ch , // pos 1: bottom left
cw, ch, // pos 2: bottom right
cw, ch, // pos 2: bottom right
cw, 0.0f, // pos 3: top right
0.0f, 0.0f, // pos 0: top left
};

void enable() {
glUseProgram(id());
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
glEnableVertexAttribArray(vertex);
glCheck();

glUniform1i(tex, 0);
}

void disable() {
glDisableVertexAttribArray(vertex);
glCheck();
}

void init() {
glGenBuffers(1, &vbo);
glCheck();

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
glCheck();
}

void deinit() {
glDeleteBuffers(1, &vbo);
glCheck();
}
};

struct TileProg: public GlProgram { struct TileProg: public GlProgram {
template<typename... T> template<typename... T>
TileProg(const T &... shaders): GlProgram(shaders...) { init(); } TileProg(const T &... shaders): GlProgram(shaders...) { init(); }
struct RendererState { struct RendererState {
GlVxShader chunkVx{Shaders::chunkVx}; GlVxShader chunkVx{Shaders::chunkVx};
GlFrShader chunkFr{Shaders::chunkFr}; GlFrShader chunkFr{Shaders::chunkFr};
GlVxShader chunkShadowVx{Shaders::chunkShadowVx};
GlFrShader chunkShadowFr{Shaders::chunkShadowFr};
GlVxShader tileVx{Shaders::tileVx}; GlVxShader tileVx{Shaders::tileVx};
GlFrShader tileFr{Shaders::tileFr}; GlFrShader tileFr{Shaders::tileFr};
GlVxShader spriteVx{Shaders::spriteVx}; GlVxShader spriteVx{Shaders::spriteVx};
GlFrShader rectFr{Shaders::rectFr}; GlFrShader rectFr{Shaders::rectFr};


ChunkProg chunkProg{chunkVx, chunkFr}; ChunkProg chunkProg{chunkVx, chunkFr};
ChunkShadowProg chunkShadowProg{chunkShadowVx, chunkShadowFr};
TileProg tileProg{tileVx, tileFr}; TileProg tileProg{tileVx, tileFr};
SpriteProg spriteProg{spriteVx, spriteFr}; SpriteProg spriteProg{spriteVx, spriteFr};
RectProg rectProg{rectVx, rectFr}; RectProg rectProg{rectVx, rectFr};
} }


auto &chunkProg = state_->chunkProg; auto &chunkProg = state_->chunkProg;
auto &chunkShadowProg = state_->chunkShadowProg;
auto &tileProg = state_->tileProg; auto &tileProg = state_->tileProg;
auto &spriteProg = state_->spriteProg; auto &spriteProg = state_->spriteProg;
auto &rectProg = state_->rectProg; auto &rectProg = state_->rectProg;
drawRects_.clear(); drawRects_.clear();
rectProg.disable(); rectProg.disable();
} }

{
chunkShadowProg.enable();
glUniformMatrix3fv(chunkShadowProg.camera, 1, GL_TRUE, camMat.data());
glCheck();

glActiveTexture(GL_TEXTURE0);
for (auto [pos, shadow]: drawChunkShadows_) {
glUniform2f(chunkShadowProg.pos, pos.x, pos.y);
glBindTexture(GL_TEXTURE_2D, shadow.tex);
glDrawArrays(GL_TRIANGLES, 0, 6);
glCheck();
}

drawChunkShadows_.clear();
chunkShadowProg.disable();
}
} }


void Renderer::uploadTileAtlas(const void *data, int width, int height) { void Renderer::uploadTileAtlas(const void *data, int width, int height) {
glCheck(); glCheck();
} }


RenderChunkShadow Renderer::createChunkShadow(
uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
RenderChunkShadow shadow;
glGenTextures(1, &shadow.tex);
glCheck();

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow.tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheck();

glTexImage2D(
GL_TEXTURE_2D, 0, GL_LUMINANCE,
SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glCheck();

return shadow;
}

void Renderer::modifyChunkShadow(
RenderChunkShadow shadow,
uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadow.tex);

glTexImage2D(
GL_TEXTURE_2D, 0, GL_LUMINANCE,
SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glCheck();
}

void Renderer::destroyChunkShadow(RenderChunkShadow shadow) {
glDeleteTextures(1, &shadow.tex);
glCheck();
}

RenderSprite Renderer::createSprite(void *data, int width, int height, int fh) { RenderSprite Renderer::createSprite(void *data, int width, int height, int fh) {
RenderSprite sprite; RenderSprite sprite;
sprite.scale = { sprite.scale = {

+ 29
- 0
libcygnet/src/shaders.cc View File

} }
)glsl"; )glsl";


const char *chunkShadowVx = R"glsl(
precision mediump float;
#define CHUNK_WIDTH 64
#define CHUNK_HEIGHT 64

uniform mat3 camera;
uniform vec2 pos;
attribute vec2 vertex;
varying vec2 v_texCoord;

void main() {
vec3 pos = camera * vec3(pos + vertex, 1);
gl_Position = vec4(pos.xy, 0, 1);
v_texCoord = vertex / vec2(CHUNK_WIDTH, CHUNK_HEIGHT);
}
)glsl";

const char *chunkShadowFr = R"glsl(
precision mediump float;

varying vec2 v_texCoord;
uniform sampler2D tex;

void main() {
vec4 color = texture2D(tex, v_texCoord);
gl_FragColor = vec4(0, 0, 0, 1.0 - color.r);
}
)glsl";

const char *tileVx = R"glsl( const char *tileVx = R"glsl(
precision mediump float; precision mediump float;
uniform mat3 camera; uniform mat3 camera;

+ 1
- 0
libswan/include/swan/Chunk.h View File



ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed
Cygnet::RenderChunk renderChunk_; Cygnet::RenderChunk renderChunk_;
Cygnet::RenderChunkShadow renderChunkShadow_;
bool needChunkRender_ = true; bool needChunkRender_ = true;
bool needLightRender_ = false; bool needLightRender_ = false;
float deactivateTimer_ = DEACTIVATE_INTERVAL; float deactivateTimer_ = DEACTIVATE_INTERVAL;

+ 12
- 2
libswan/src/Chunk.cc View File

} }


rnd.destroyChunk(renderChunk_); rnd.destroyChunk(renderChunk_);
rnd.destroyChunkShadow(renderChunkShadow_);
} }


void Chunk::decompress() { void Chunk::decompress() {
return; return;


if (needChunkRender_) { if (needChunkRender_) {
renderChunk_ = rnd.createChunk((Tile::ID *)data_.get());
renderChunk_ = rnd.createChunk(getTileData());
renderChunkShadow_ = rnd.createChunkShadow(getLightData());
needChunkRender_ = false; needChunkRender_ = false;
needLightRender_ = false;
} else { } else {
for (auto &change: changeList_) { for (auto &change: changeList_) {
rnd.modifyChunk(renderChunk_, change.first, change.second); rnd.modifyChunk(renderChunk_, change.first, change.second);
} }
} }


rnd.drawChunk(renderChunk_, (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT});
if (needLightRender_) {
rnd.modifyChunkShadow(renderChunkShadow_, getLightData());
needLightRender_ = false;
}

Vec2 pos = (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT};
rnd.drawChunk(renderChunk_, pos);
rnd.drawChunkShadow(renderChunkShadow_, pos);
} }


Chunk::TickAction Chunk::tick(float dt) { Chunk::TickAction Chunk::tick(float dt) {

Loading…
Cancel
Save