Ver código fonte

RenderQueue and transformation matrixes and stuff

opengl-renderer-broken
Martin Dørum 3 anos atrás
pai
commit
44fc1f3748

+ 1
- 0
libcygnet/CMakeLists.txt Ver arquivo

src/glutil.cc src/glutil.cc
src/GlWrappers.cc src/GlWrappers.cc
src/Image.cc src/Image.cc
src/RenderQueue.cc
src/Window.cc) src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 SDL2_image GLESv2) target_link_libraries(cygnet PUBLIC SDL2 SDL2_image GLESv2)
target_include_directories(cygnet target_include_directories(cygnet

+ 4
- 0
libcygnet/include/cygnet/GlWrappers.h Ver arquivo

void upload(GLsizei width, GLsizei height, void *data, void upload(GLsizei width, GLsizei height, void *data,
GLenum format, GLenum type = GL_UNSIGNED_BYTE); GLenum format, GLenum type = GL_UNSIGNED_BYTE);
GLuint id() { return id_; } GLuint id() { return id_; }
int width() { return w_; }
int height() { return h_; }


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


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

+ 3
- 2
libcygnet/include/cygnet/Image.h Ver arquivo

#pragma once #pragma once


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


#include "GlWrappers.h" #include "GlWrappers.h"


Image(std::string path); Image(std::string path);


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


private: private:
std::string path_; std::string path_;


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


GlTexture tex_; GlTexture tex_;
bool tex_dirty_ = true; bool tex_dirty_ = true;

+ 64
- 0
libcygnet/include/cygnet/RenderQueue.h Ver arquivo

#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 Ver arquivo



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


#include "util.h" #include "util.h"


namespace Cygnet { namespace Cygnet {


struct GlTexture;
class GlTexture;


class Window { class Window {
public: public:

+ 48
- 37
libcygnet/samples/game/game.cc Ver arquivo

#include <cygnet/builtins.h> #include <cygnet/builtins.h>
#include <cygnet/glutil.h> #include <cygnet/glutil.h>
#include <cygnet/Image.h> #include <cygnet/Image.h>
#include <cygnet/RenderQueue.h>
#include <stdio.h> #include <stdio.h>
#include <memory> #include <memory>
#include <vector> #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 { enum class Key {
UP, DOWN, LEFT, RIGHT, NONE, UP, DOWN, LEFT, RIGHT, NONE,
}; };
bool keys[(int)Key::NONE]{}; bool keys[(int)Key::NONE]{};
Cygnet::Window &win; Cygnet::Window &win;
Cygnet::GlProgram &program; Cygnet::GlProgram &program;
Cygnet::RenderQueue &q;
}; };


class Entity { class Entity {
public: public:
virtual ~Entity() = default;
virtual void update(State &state, float dt) = 0; virtual void update(State &state, float dt) = 0;
virtual void draw(State &state) = 0; virtual void draw(State &state) = 0;
}; };
fx -= 1; fx -= 1;
if (state.keys[(int)Key::RIGHT]) if (state.keys[(int)Key::RIGHT])
fx += 1; 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; vx_ += fx * dt;
vy_ += fy * dt; vy_ += fy * dt;
} }


void draw(State &state) override { 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: private:
Cygnet::Deferred<SDL_Quit> sdl; Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Game", 640, 480); 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(); program.use();


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

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


std::vector<std::unique_ptr<Entity>> entities; std::vector<std::unique_ptr<Entity>> entities;
goto exit; goto exit;
break; 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: case SDL_KEYDOWN:
{ {
Key key = keyFromSym(evt.key.keysym); Key key = keyFromSym(evt.key.keysym);
ent->draw(state); ent->draw(state);
} }


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



+ 2
- 0
libcygnet/src/GlWrappers.cc Ver arquivo



void GlTexture::upload(GLsizei width, GLsizei height, void *data, void GlTexture::upload(GLsizei width, GLsizei height, void *data,
GLenum format, GLenum type) { GLenum format, GLenum type) {
w_ = width;
h_ = height;
bind(); bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, type, data); 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_MIN_FILTER, GL_NEAREST);

+ 2
- 2
libcygnet/src/Image.cc Ver arquivo

w_ = surface->w; w_ = surface->w;
h_ = surface->h; h_ = surface->h;
pitch_ = surface->pitch; 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() { GlTexture &Image::texture() {

+ 51
- 0
libcygnet/src/RenderQueue.cc Ver arquivo

#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 Ver arquivo

namespace Cygnet { namespace Cygnet {


Window::Window(const char *name, int width, int height) { 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_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 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())); sdlAssert(glctx_ = SDL_GL_CreateContext(win_.get()));
makeCurrent(); makeCurrent();

Carregando…
Cancelar
Salvar