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

@@ -17,6 +17,10 @@ struct RenderChunk {
GLuint tex;
};

struct RenderChunkShadow {
GLuint tex;
};

struct RenderSprite {
GLuint tex;
SwanCommon::Vec2 scale;
@@ -37,6 +41,7 @@ public:
~Renderer();

void drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos);
void drawChunkShadow(RenderChunkShadow shadow, SwanCommon::Vec2 pos);
void drawTile(TileID id, Mat3gf mat);
void drawSprite(RenderSprite sprite, Mat3gf mat, int y = 0);
void drawRect(SwanCommon::Vec2 pos, SwanCommon::Vec2 size);
@@ -51,6 +56,13 @@ public:
void modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id);
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);
void destroySprite(RenderSprite sprite);
@@ -63,6 +75,11 @@ private:
RenderChunk chunk;
};

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

struct DrawTile {
Mat3gf transform;
TileID id;
@@ -84,6 +101,7 @@ private:
std::unique_ptr<RendererState> state_;

std::vector<DrawChunk> drawChunks_;
std::vector<DrawShadow> drawChunkShadows_;
std::vector<DrawTile> drawTiles_;
std::vector<DrawSprite> drawSprites_;
std::vector<DrawRect> drawRects_;
@@ -93,6 +111,10 @@ inline void Renderer::drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos) {
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) {
drawTiles_.push_back({mat, id});
}

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

@@ -5,6 +5,9 @@ namespace Cygnet::Shaders {
extern const char *chunkVx;
extern const char *chunkFr;

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

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


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

@@ -73,6 +73,59 @@ struct ChunkProg: public GlProgram {
}
};

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 {
template<typename... T>
TileProg(const T &... shaders): GlProgram(shaders...) { init(); }
@@ -231,6 +284,8 @@ struct RectProg: public GlProgram {
struct RendererState {
GlVxShader chunkVx{Shaders::chunkVx};
GlFrShader chunkFr{Shaders::chunkFr};
GlVxShader chunkShadowVx{Shaders::chunkShadowVx};
GlFrShader chunkShadowFr{Shaders::chunkShadowFr};
GlVxShader tileVx{Shaders::tileVx};
GlFrShader tileFr{Shaders::tileFr};
GlVxShader spriteVx{Shaders::spriteVx};
@@ -239,6 +294,7 @@ struct RendererState {
GlFrShader rectFr{Shaders::rectFr};

ChunkProg chunkProg{chunkVx, chunkFr};
ChunkShadowProg chunkShadowProg{chunkShadowVx, chunkShadowFr};
TileProg tileProg{tileVx, tileFr};
SpriteProg spriteProg{spriteVx, spriteFr};
RectProg rectProg{rectVx, rectFr};
@@ -270,6 +326,7 @@ void Renderer::draw(const RenderCamera &cam) {
}

auto &chunkProg = state_->chunkProg;
auto &chunkShadowProg = state_->chunkShadowProg;
auto &tileProg = state_->tileProg;
auto &spriteProg = state_->spriteProg;
auto &rectProg = state_->rectProg;
@@ -356,6 +413,23 @@ void Renderer::draw(const RenderCamera &cam) {
drawRects_.clear();
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) {
@@ -459,6 +533,47 @@ void Renderer::destroyChunk(RenderChunk chunk) {
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 sprite;
sprite.scale = {

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

@@ -43,6 +43,35 @@ const char *chunkFr = R"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(
precision mediump float;
uniform mat3 camera;

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

@@ -89,6 +89,7 @@ private:

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

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

@@ -46,6 +46,7 @@ void Chunk::compress(Cygnet::Renderer &rnd) {
}

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

void Chunk::decompress() {
@@ -79,15 +80,24 @@ void Chunk::draw(const Context &ctx, Cygnet::Renderer &rnd) {
return;

if (needChunkRender_) {
renderChunk_ = rnd.createChunk((Tile::ID *)data_.get());
renderChunk_ = rnd.createChunk(getTileData());
renderChunkShadow_ = rnd.createChunkShadow(getLightData());
needChunkRender_ = false;
needLightRender_ = false;
} else {
for (auto &change: changeList_) {
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) {

Loading…
Cancel
Save