Browse Source

chunk rendering

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

+ 0
- 1
libcygnet/CMakeLists.txt View File

@@ -9,7 +9,6 @@ add_library(libcygnet SHARED
target_include_directories(libcygnet
PUBLIC "include"
PRIVATE "include/cygnet")
set_target_properties(libcygnet PROPERTIES OUTPUT_NAME cygnet)
target_link_libraries(libcygnet swan-common GLESv2 ${libraries})

install(TARGETS libcygnet DESTINATION swan/libcygnet)

+ 1
- 4
libcygnet/include/cygnet/GlWrappers.h View File

@@ -44,13 +44,11 @@ public:
template <typename... T>
GlProgram(const T &... shaders): GlProgram() { (addShader(shaders), ...); link(); }
GlProgram();
~GlProgram();
virtual ~GlProgram();

void use();
GLuint id() const { return id_; }

protected:

GLint attribLoc(const char *name);
GLint uniformLoc(const char *name);

@@ -65,7 +63,6 @@ class GlTexture {
public:
GlTexture();

void bind();
void upload(GLsizei width, GLsizei height, void *data,
GLenum format, GLenum type);
GLuint id() { return id_; }

+ 5
- 2
libcygnet/include/cygnet/shaders.h View File

@@ -2,7 +2,10 @@

namespace Cygnet::Shaders {

extern const char *texturedVx;
extern const char *texturedFr;
extern const char *spriteVx;
extern const char *spriteFr;

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

}

+ 1
- 11
libcygnet/src/GlWrappers.cc View File

@@ -58,11 +58,6 @@ GlProgram::~GlProgram() {
glCheck();
}

void GlProgram::use() {
glUseProgram(id_);
glCheck();
}

void GlProgram::addShader(const GlShader &shader) {
glAttachShader(id_, shader.id());
glCheck();
@@ -102,16 +97,11 @@ GlTexture::GlTexture() {
glCheck();
}

void GlTexture::bind() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, id_);
}

void GlTexture::upload(GLsizei width, GLsizei height, void *data,
GLenum format, GLenum type) {
w_ = width;
h_ = height;
bind();
glBindTexture(GL_TEXTURE_2D, id_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, type, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

+ 147
- 36
libcygnet/src/Renderer.cc View File

@@ -12,21 +12,127 @@

namespace Cygnet {

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

GLint camera = uniformLoc("camera");
GLint transform = uniformLoc("transform");
GLint vertex = attribLoc("vertex");
GLint texCoord = attribLoc("texCoord");
GLint tex = uniformLoc("tex");

GLuint vbo;

static constexpr GLfloat vertexes[] = {
-0.5f, 0.5f, // pos 0: top left
0.0f, 0.0f, // tex 0: top left
-0.5f, -0.5f, // pos 1: bottom left
0.0f, 1.0f, // tex 1: bottom left
0.5f, -0.5f, // pos 2: bottom right
1.0f, 1.0f, // tex 2: bottom right
0.5f, -0.5f, // pos 2: bottom right
1.0f, 1.0f, // tex 2: bottom right
0.5f, 0.5f, // pos 3: top right
1.0f, 0.0f, // tex 3: top right
-0.5f, 0.5f, // pos 0: top left
0.0f, 0.0f, // tex 0: top left
};

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

void disable() {
glDisableVertexAttribArray(vertex);
glDisableVertexAttribArray(texCoord);
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 ChunkProg: public GlProgram {
template<typename... T>
ChunkProg(const T &... shaders): GlProgram(shaders...) { init(); }
~ChunkProg() { deinit(); }

GLint camera = uniformLoc("camera");
GLint pos = uniformLoc("pos");
GLint vertex = attribLoc("vertex");
GLint tileTex = uniformLoc("tileTex");
GLint tileTexWidth = uniformLoc("tileTexWidth");
GLint tileTexHeight = uniformLoc("tileTexHeight");
GLint tiles = uniformLoc("tiles");

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();
}

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 RendererState {
GlVxShader texturedVx{Shaders::texturedVx};
GlFrShader texturedFr{Shaders::texturedFr};
GlVxShader spriteVx{Shaders::spriteVx};
GlFrShader spriteFr{Shaders::spriteFr};
GlVxShader chunkVx{Shaders::chunkVx};
GlFrShader chunkFr{Shaders::chunkFr};

TexturedProg texturedProg{texturedVx, texturedFr};
SpriteProg spriteProg{spriteVx, spriteFr};
ChunkProg chunkProg{chunkVx, chunkFr};

TileAtlas atlas;
GlTexture atlasTex;
@@ -39,43 +145,52 @@ Renderer::Renderer(): state_(std::make_unique<RendererState>()) {}
Renderer::~Renderer() = default;

void Renderer::draw() {
state_->texturedProg.use();
state_->chunkProg.enable();

float tw = (6 * SwanCommon::TILE_SIZE) / (float)state_->atlasTex.width();
GLfloat vertexes[] = {
-0.5f, 0.5f, // pos 0: top left
0.0f, 0.0f, // tex 0: top left
-0.5f, -0.5f, // pos 1: bottom left
0.0f, 1.0f, // tex 1: bottom left
0.5f, -0.5f, // pos 2: bottom right
tw, 1.0f, // tex 2: bottom right
0.5f, 0.5f, // pos 3: top right
tw, 0.0f, // tex 3: top right
};
state_->camera.reset().translate(-0.5, 0.5).scale(0.25, 0.25);
glUniformMatrix3fv(state_->chunkProg.camera, 1, GL_TRUE, state_->camera.data());
glCheck();

GLushort indexes[] = {
0, 1, 2, // top left -> bottom left -> bottom right
2, 3, 0, // bottom right -> top right -> top left
};
GLint tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT] = {0};
tiles[0] = 3;
tiles[1] = 1;
glUniform1iv(state_->chunkProg.tiles, sizeof(tiles) / sizeof(*tiles), tiles);
glCheck();

glUniform1f(state_->chunkProg.tileTexWidth,
(float)(int)(state_->atlasTex.width() / SwanCommon::TILE_SIZE));
glUniform1f(state_->chunkProg.tileTexHeight,
(float)(int)(state_->atlasTex.height() / SwanCommon::TILE_SIZE));
glCheck();

glUniformMatrix3fv(state_->texturedProg.transform, 1, GL_TRUE, Mat3gf::IDENTITY.data());
glUniformMatrix3fv(state_->texturedProg.camera, 1, GL_TRUE, state_->camera.data());
glVertexAttribPointer(state_->texturedProg.vertex, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), vertexes);
glVertexAttribPointer(state_->texturedProg.texCoord, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), &vertexes[2]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,state_->atlasTex.id()); // Necessary?
glUniform1i(state_->chunkProg.tileTex, 0);
glCheck();

glEnableVertexAttribArray(state_->texturedProg.vertex);
glEnableVertexAttribArray(state_->texturedProg.texCoord);
glDrawArrays(GL_TRIANGLES, 0, 6);
glCheck();

state_->atlasTex.bind();
glUniform1i(state_->texturedProg.tex, 0);
state_->chunkProg.disable();

/*
state_->spriteProg.enable();

state_->camera.translate(-0.00001, 0);
glUniformMatrix3fv(state_->spriteProg.transform, 1, GL_TRUE, Mat3gf::IDENTITY.data());
glUniformMatrix3fv(state_->spriteProg.camera, 1, GL_TRUE, state_->camera.data());
glCheck();

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,state_->atlasTex.id()); // Necessary?
glUniform1i(state_->spriteProg.tex, 0);
glCheck();

glDrawArrays(GL_TRIANGLES, 0, 6);
glCheck();

state_->spriteProg.disable();
*/
}

void Renderer::registerTileTexture(size_t tileId, const void *data, size_t len) {
@@ -87,10 +202,6 @@ void Renderer::uploadTileTexture() {
const unsigned char *data = state_->atlas.getImage(&w, &h);
state_->atlasTex.upload(w, h, (void *)data, GL_RGBA, GL_UNSIGNED_BYTE);
std::cerr << "Uploaded image of size " << w << 'x' << h << '\n';

FILE *f = fopen("lol.rgb", "w");
fwrite(data, 1, w * h * 4, f);
fclose(f);
}

}

+ 1
- 1
libcygnet/src/TileAtlas.cc View File

@@ -21,7 +21,7 @@ struct AtlasState {
TileAtlas::TileAtlas(): state_(std::make_unique<AtlasState>()) {
GLint size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
state_->tilesPerLine = std::min(size / SwanCommon::TILE_SIZE, 1024);
state_->tilesPerLine = std::min(size / SwanCommon::TILE_SIZE, 8);
}

TileAtlas::~TileAtlas() = default;

+ 45
- 2
libcygnet/src/shaders.cc View File

@@ -2,12 +2,13 @@

namespace Cygnet::Shaders {

const char *texturedVx = R"glsl(
const char *spriteVx = R"glsl(
uniform mat3 camera;
uniform mat3 transform;
attribute vec2 vertex;
attribute vec2 texCoord;
varying vec2 v_texCoord;

void main() {
vec3 pos = camera * transform * vec3(vertex, 1);
gl_Position = vec4(pos.x, pos.y, 0, 1);
@@ -15,13 +16,55 @@ const char *texturedVx = R"glsl(
}
)glsl";

const char *texturedFr = R"glsl(
const char *spriteFr = R"glsl(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D tex;

void main() {
gl_FragColor = texture2D(tex, v_texCoord);
}
)glsl";

const char *chunkVx = R"glsl(
uniform mat3 camera;
uniform vec2 pos;
attribute vec2 vertex;
varying vec2 v_tileCoord;

void main() {
vec3 pos = camera * vec3(pos + vertex, 1);
gl_Position = vec4(pos.x, pos.y, 0, 1);
v_tileCoord = vertex;
}
)glsl";

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

varying vec2 v_tileCoord;
uniform sampler2D tileTex;
uniform float tileTexWidth;
uniform float tileTexHeight;
uniform int tiles[CHUNK_WIDTH * CHUNK_HEIGHT];

void main() {
float tileX = floor(v_tileCoord.x);
float tileY = floor(-v_tileCoord.y);
int tileIndex = int(tileY * float(CHUNK_WIDTH) + tileX);
float tileID = float(tiles[tileIndex]);

float atlasX = floor(mod(tileID, tileTexWidth)) + v_tileCoord.x - tileX;
float atlasY = floor(tileID / tileTexWidth) + (-v_tileCoord.y - tileY);

float x = atlasX / tileTexWidth;
float y = atlasY / tileTexHeight;

gl_FragColor = texture2D(tileTex, vec2(x, y));
}
)glsl";

}

+ 1
- 1
src/cygnet-test.cc View File

@@ -18,7 +18,7 @@ int main() {
Cygnet::Context ctx;
IMG_Init(IMG_INIT_PNG);
//Cygnet::Window win("Cygnet Test", 640, 480);
Cygnet::Window win("Cygnet Test", 1280, 256);
Cygnet::Window win("Cygnet Test", 680, 680);
Cygnet::Renderer rnd;

for (auto path: {

Loading…
Cancel
Save