Browse Source

RenderQueue and transformation matrixes and stuff

opengl-renderer-broken
Martin Dørum 3 years ago
parent
commit
44fc1f3748

+ 1
- 0
libcygnet/CMakeLists.txt View File

@@ -3,6 +3,7 @@ add_library(cygnet SHARED
src/glutil.cc
src/GlWrappers.cc
src/Image.cc
src/RenderQueue.cc
src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 SDL2_image GLESv2)
target_include_directories(cygnet

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

@@ -53,9 +53,13 @@ public:
void upload(GLsizei width, GLsizei height, void *data,
GLenum format, GLenum type = GL_UNSIGNED_BYTE);
GLuint id() { return id_; }
int width() { return w_; }
int height() { return h_; }

private:
GLuint id_;
int w_;
int h_;
};

inline GLint GlProgram::attribLoc(const char *name) {

+ 3
- 2
libcygnet/include/cygnet/Image.h View File

@@ -1,7 +1,6 @@
#pragma once

#include <memory>
#include <stdlib.h>

#include "GlWrappers.h"

@@ -12,12 +11,14 @@ public:
Image(std::string path);

GlTexture &texture();
int width() { return w_; }
int height() { return h_; }

private:
std::string path_;

int w_, h_, pitch_;
CPtr<void, free> bytes_;
std::unique_ptr<unsigned char[]> bytes_;

GlTexture tex_;
bool tex_dirty_ = true;

+ 64
- 0
libcygnet/include/cygnet/RenderQueue.h View File

@@ -0,0 +1,64 @@
#pragma once

#include <vector>

#include "GlWrappers.h"

namespace Cygnet {

class RenderQueue {
public:
struct Locs {
GLint transform;
GLint position;
GLint texCoord;
GLint tex;
};

RenderQueue(Locs locs, float scale):
locs_(std::move(locs)), pixScale_(scale) {};
RenderQueue(GlProgram &prog, float scale):
RenderQueue({
prog.uniformLoc("transform"),
prog.attribLoc("position"),
prog.attribLoc("texCoord"),
prog.uniformLoc("tex"),
}, scale) {}

void show(float x, float y, GlTexture &tex) { show(x, y, tex.width(), tex.height(), tex.id()); }
void show(float x, float y, float w, float h, GLuint tex) {
queue_.push_back({ x, y, w * pixScale_, h * pixScale_, tex });
}

float pixScale() { return pixScale_; }
void pixScale(float scale) { pixScale_ = scale; }

float scaleX() { return mat_[0]; }
void scaleX(float sx) { mat_[0] = sx; }
float scaleY() { return -mat_[4]; }
void scaleY(float sy) { mat_[4] = -sy; }
float translateX() { return mat_[2]; }
void translateX(float tx) { mat_[2] = tx; }
float translateY() { return mat_[5]; }
void translateY(float ty) { mat_[5] = ty; }

void draw();

private:
struct Entry {
float x, y, w, h;
GLuint tex;
};

Locs locs_;
float pixScale_;
GLfloat mat_[9] = {
1, 0, 0, // scaleX, 0, translateX,
0, -1, 0, // 0, -scaleY, translateY,
0, 0, 1, // 0, 0, 1
};

std::vector<Entry> queue_;
};

}

+ 1
- 2
libcygnet/include/cygnet/Window.h View File

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

#include <SDL.h>
#include <stdint.h>
#include <glm/mat4x4.hpp>

#include "util.h"

namespace Cygnet {

struct GlTexture;
class GlTexture;

class Window {
public:

+ 48
- 37
libcygnet/samples/game/game.cc View File

@@ -3,10 +3,32 @@
#include <cygnet/builtins.h>
#include <cygnet/glutil.h>
#include <cygnet/Image.h>
#include <cygnet/RenderQueue.h>
#include <stdio.h>
#include <memory>
#include <vector>

const char *vertexShader = R"(
uniform mat3 transform;
attribute vec2 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
void main() {
vec3 pos = transform * vec3(position, 0);
gl_Position = vec4(pos.x, pos.y, 0, 1);
v_texCoord = texCoord;
}
)";

const char *fragmentShader = R"(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, v_texCoord);
}
)";

enum class Key {
UP, DOWN, LEFT, RIGHT, NONE,
};
@@ -15,10 +37,12 @@ struct State {
bool keys[(int)Key::NONE]{};
Cygnet::Window &win;
Cygnet::GlProgram &program;
Cygnet::RenderQueue &q;
};

class Entity {
public:
virtual ~Entity() = default;
virtual void update(State &state, float dt) = 0;
virtual void draw(State &state) = 0;
};
@@ -34,6 +58,13 @@ public:
fx -= 1;
if (state.keys[(int)Key::RIGHT])
fx += 1;
if (state.keys[(int)Key::UP])
fy -= 1;
if (state.keys[(int)Key::DOWN])
fy += 1;

fy += vy_ * -0.9;
fx += vx_ * -0.9;

vx_ += fx * dt;
vy_ += fy * dt;
@@ -42,42 +73,7 @@ public:
}

void draw(State &state) override {
printf("\ram at (%f,%f)", x_, y_);
fflush(stdout);

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

static const GLushort indexes[] = {
0, 1, 2, // top left -> bottom left -> bottom right
2, 3, 0, // bottom right -> top right -> top left
};

GLint positionLoc = state.program.attribLoc("position", 0);
GLint texCoordLoc = state.program.attribLoc("texCoord", 1);
GLint texLoc = state.program.uniformLoc("tex");

glUniform1i(texLoc, 0);

glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vertexes);
glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vertexes[3]);
Cygnet::glCheck();

glEnableVertexAttribArray(positionLoc);
glEnableVertexAttribArray(texCoordLoc);
Cygnet::glCheck();

image_.texture().bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
Cygnet::glCheck();
state.q.show(x_, y_, image_.texture());
}

private:
@@ -107,13 +103,19 @@ int main() {
Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Game", 640, 480);

Cygnet::GlProgram program(Cygnet::builtinTextureVertex(), Cygnet::builtinTextureFragment());
Cygnet::GlProgram program(
Cygnet::GlShader(Cygnet::GlShader::Type::VERTEX, vertexShader),
Cygnet::GlShader(Cygnet::GlShader::Type::FRAGMENT, fragmentShader));
program.use();

Cygnet::RenderQueue q(program, 1/32.0);
q.scaleX(1 / (640.0 / 480.0));

State state{
.keys{},
.win = win,
.program = program,
.q = q,
};

std::vector<std::unique_ptr<Entity>> entities;
@@ -127,6 +129,14 @@ int main() {
goto exit;
break;

case SDL_WINDOWEVENT:
if (evt.window.event == SDL_WINDOWEVENT_RESIZED) {
glViewport(0, 0, evt.window.data1, evt.window.data2);
float ratio = (float)evt.window.data1 / (float)evt.window.data2;
q.scaleX(1 / ratio);
}
break;

case SDL_KEYDOWN:
{
Key key = keyFromSym(evt.key.keysym);
@@ -157,6 +167,7 @@ int main() {
ent->draw(state);
}

q.draw();
win.flip();
}


+ 2
- 0
libcygnet/src/GlWrappers.cc View File

@@ -84,6 +84,8 @@ void GlTexture::bind() {

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

+ 2
- 2
libcygnet/src/Image.cc View File

@@ -28,8 +28,8 @@ Image::Image(std::string path) {
w_ = surface->w;
h_ = surface->h;
pitch_ = surface->pitch;
bytes_.reset(surface->pixels);
surface->pixels = nullptr;
bytes_.reset(new unsigned char[(size_t)pitch_ * h_]);
memcpy(bytes_.get(), surface->pixels, (size_t)pitch_ * h_);
}

GlTexture &Image::texture() {

+ 51
- 0
libcygnet/src/RenderQueue.cc View File

@@ -0,0 +1,51 @@
#include "RenderQueue.h"

#include "glutil.h"

namespace Cygnet {

static const GLfloat texCoords[] = {
0.0f, 0.0f, // tex 0: top left
0.0f, 1.0f, // tex 1: bottom left
1.0f, 1.0f, // tex 2: bottom right
1.0f, 0.0f, // tex 3: top right
};

static const GLushort indexes[] = {
0, 1, 2, // top left -> bottom left -> bottom right
2, 3, 0, // bottom right -> top right -> top left
};

void RenderQueue::draw() {
glUniform1i(locs_.tex, 0);
glVertexAttribPointer(locs_.texCoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), texCoords);
glEnableVertexAttribArray(locs_.texCoord);
glCheck();

glUniformMatrix3fv(locs_.transform, 1, GL_TRUE, mat_);
glCheck();

glActiveTexture(GL_TEXTURE0);

for (auto &entry: queue_) {
GLfloat vertexes[] = {
entry.x, entry.y, // top left
entry.x, entry.y + entry.h, // bottom left
entry.x + entry.w, entry.y + entry.h, // bottom right
entry.x + entry.w, entry.y, // top right
};

glVertexAttribPointer(locs_.position, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), vertexes);
glEnableVertexAttribArray(locs_.position);
glCheck();

glBindTexture(GL_TEXTURE_2D, entry.tex);
glCheck();

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
}

queue_.clear();
}

}

+ 7
- 6
libcygnet/src/Window.cc View File

@@ -7,17 +7,18 @@
namespace Cygnet {

Window::Window(const char *name, int width, int height) {
win_.reset(SDL_CreateWindow(
name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE |
SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL));

SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
glCheck();
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);

win_.reset(SDL_CreateWindow(
name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE |
SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL));

sdlAssert(glctx_ = SDL_GL_CreateContext(win_.get()));
makeCurrent();

Loading…
Cancel
Save