Browse Source

lots of cygnet stuff

opengl-renderer-broken
Martin Dørum 3 years ago
parent
commit
719e391df8

+ 14
- 2
libcygnet/CMakeLists.txt View File

@@ -1,9 +1,10 @@
add_library(cygnet SHARED
src/BuiltinShaders.cc
src/builtins.cc
src/glutil.cc
src/GlWrappers.cc
src/Image.cc
src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 GLESv2)
target_link_libraries(cygnet PUBLIC SDL2 SDL2_image GLESv2)
target_include_directories(cygnet
PUBLIC include
PRIVATE include/cygnet)
@@ -15,3 +16,14 @@ target_link_libraries(cygnet-hello-triangle PUBLIC cygnet)
add_executable(cygnet-hello-texture
samples/hello-texture/hello-texture.cc)
target_link_libraries(cygnet-hello-texture PUBLIC cygnet)

add_executable(cygnet-game
samples/game/game.cc)
target_link_libraries(cygnet-game PUBLIC cygnet)

set(assets
samples/game/assets/player.png)
foreach(a ${assets})
configure_file("${a}" "${a}" COPYONLY)
endforeach(a)


+ 0
- 15
libcygnet/include/cygnet/BuiltinShaders.h View File

@@ -1,15 +0,0 @@
#include <optional>

#include "GlWrappers.h"

namespace Cygnet {

struct BuiltinShaders {
BuiltinShaders();

GlShader textureVertex;
GlShader textureFragment;
GlShader whiteFragment;
};

}

+ 29
- 2
libcygnet/include/cygnet/GlWrappers.h View File

@@ -37,11 +37,38 @@ public:

void use() { glUseProgram(id_); }
GLuint id() { return id_; }
GLint attribLocation(const char *name) { return glGetAttribLocation(id_, name); }
GLint uniformLocation(const char *name) { return glGetAttribLocation(id_, name); }
GLint attribLoc(const char *name);
GLint attribLoc(const char *name, GLuint index);
GLint uniformLoc(const char *name);

private:
GLuint id_;
};

class GlTexture: NonCopyable {
public:
GlTexture();

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

private:
GLuint id_;
};

inline GLint GlProgram::attribLoc(const char *name) {
return glGetAttribLocation(id_, name);
}

inline GLint GlProgram::attribLoc(const char *name, GLuint index) {
glBindAttribLocation(id_, index, name);
return index;
}

inline GLint GlProgram::uniformLoc(const char *name) {
return glGetUniformLocation(id_, name);
}

}

+ 26
- 0
libcygnet/include/cygnet/Image.h View File

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

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

#include "GlWrappers.h"

namespace Cygnet {

class Image {
public:
Image(std::string path);

GlTexture &texture();

private:
std::string path_;

int w_, h_, pitch_;
CPtr<void, free> bytes_;

GlTexture tex_;
bool tex_dirty_ = true;
};

}

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

@@ -2,11 +2,14 @@

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

#include "util.h"

namespace Cygnet {

struct GlTexture;

class Window {
public:
Window(const char *name, int width, int height);

+ 11
- 0
libcygnet/include/cygnet/builtins.h View File

@@ -0,0 +1,11 @@
#include <optional>

#include "GlWrappers.h"

namespace Cygnet {

const GlShader &builtinTextureVertex();
const GlShader &builtinTextureFragment();
const GlShader &builtinWhiteFragment();

}

BIN
libcygnet/samples/game/assets-src/player.xcf View File


BIN
libcygnet/samples/game/assets/player.png View File


+ 164
- 0
libcygnet/samples/game/game.cc View File

@@ -0,0 +1,164 @@
#include <cygnet/Window.h>
#include <cygnet/GlWrappers.h>
#include <cygnet/builtins.h>
#include <cygnet/glutil.h>
#include <cygnet/Image.h>
#include <stdio.h>
#include <memory>
#include <vector>

enum class Key {
UP, DOWN, LEFT, RIGHT, NONE,
};

struct State {
bool keys[(int)Key::NONE]{};
Cygnet::Window &win;
Cygnet::GlProgram &program;
};

class Entity {
public:
virtual void update(State &state, float dt) = 0;
virtual void draw(State &state) = 0;
};

class PlayerEntity: public Entity {
public:
PlayerEntity(float x, float y): x_(x), y_(y) {}

void update(State &state, float dt) override {
float fx{}, fy{};

if (state.keys[(int)Key::LEFT])
fx -= 1;
if (state.keys[(int)Key::RIGHT])
fx += 1;

vx_ += fx * dt;
vy_ += fy * dt;
x_ += vx_ * dt;
y_ += vy_ * dt;
}

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

private:
float x_, y_;
float vx_{}, vy_{};

Cygnet::Image image_{"libcygnet/samples/game/assets/player.png"};
};

Key keyFromSym(SDL_Keysym sym) {
switch (sym.scancode) {
case SDL_SCANCODE_W:
return Key::UP;
case SDL_SCANCODE_A:
return Key::LEFT;
case SDL_SCANCODE_S:
return Key::DOWN;
case SDL_SCANCODE_D:
return Key::RIGHT;
default:
return Key::NONE;
}
}

int main() {
SDL_Init(SDL_INIT_VIDEO);
Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Game", 640, 480);

Cygnet::GlProgram program(Cygnet::builtinTextureVertex(), Cygnet::builtinTextureFragment());
program.use();

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

std::vector<std::unique_ptr<Entity>> entities;
entities.emplace_back(std::make_unique<PlayerEntity>(0, 0));

SDL_Event evt;
while (true) {
while (SDL_PollEvent(&evt)) {
switch (evt.type) {
case SDL_QUIT:
goto exit;
break;

case SDL_KEYDOWN:
{
Key key = keyFromSym(evt.key.keysym);
if (key != Key::NONE) {
state.keys[(int)key] = true;
}
}
break;

case SDL_KEYUP:
{
Key key = keyFromSym(evt.key.keysym);
if (key != Key::NONE) {
state.keys[(int)key] = false;
}
}
break;
}
}

win.clear();

for (auto &ent: entities) {
ent->update(state, 1/60.0);
}

for (auto &ent: entities) {
ent->draw(state);
}

win.flip();
}

exit: ;
}

+ 9
- 26
libcygnet/samples/hello-texture/hello-texture.cc View File

@@ -1,6 +1,6 @@
#include <cygnet/Window.h>
#include <cygnet/GlWrappers.h>
#include <cygnet/BuiltinShaders.h>
#include <cygnet/builtins.h>
#include <cygnet/glutil.h>
#include <iostream>

@@ -9,8 +9,7 @@ int main() {
Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Hello Texture", 640, 480);

Cygnet::BuiltinShaders shaders;
Cygnet::GlProgram program(shaders.textureVertex, shaders.textureFragment);
Cygnet::GlProgram program(Cygnet::builtinTextureVertex(), Cygnet::builtinTextureFragment());
program.use();

GLfloat vertexes[] = {
@@ -35,21 +34,14 @@ int main() {
0xa0, 0x55, 0x77, 0x00, 0xf0, 0x0f, 0xff, 0x00, 0xff, 0, 0, 0,
};

GLuint texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
Cygnet::glCheck();
Cygnet::GlTexture tex;
tex.upload(3, 3, image, GL_RGB);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 3, 3, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
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);
Cygnet::glCheck();
GLint positionLoc = program.attribLoc("position", 0);
GLint texCoordLoc = program.attribLoc("texCoord", 1);
GLint texLoc = program.uniformLoc("tex");

GLint positionLoc = program.attribLocation("position");
GLint texCoordLoc = program.attribLocation("texCoord");
GLint texLoc = program.uniformLocation("tex");
glUniform1i(texLoc, 0);

// Draw loop
while (true) {
@@ -72,16 +64,7 @@ int main() {
glEnableVertexAttribArray(texCoordLoc);
Cygnet::glCheck();

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);
glUniform1i(texLoc, 0);
Cygnet::glCheck();

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);
glUniform1i(texLoc, 0);
Cygnet::glCheck();

tex.bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
Cygnet::glCheck();


+ 1
- 1
libcygnet/samples/hello-triangle/hello-triangle.cc View File

@@ -24,7 +24,7 @@ int main() {
Cygnet::GlShader vertex(Cygnet::GlShader::Type::VERTEX, vertexSource);
Cygnet::GlShader fragment(Cygnet::GlShader::Type::FRAGMENT, fragmentSource);
Cygnet::GlProgram program(vertex, fragment);
GLuint positionAttrib = program.attribLocation("position");
GLuint positionAttrib = program.attribLoc("position");
program.use();

GLfloat vertixes[] = {

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

@@ -72,4 +72,25 @@ GlProgram::~GlProgram() {
glDeleteProgram(id_);
}

GlTexture::GlTexture() {
glGenTextures(1, &id_);
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) {
bind();
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);
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();
}

}

+ 43
- 0
libcygnet/src/Image.cc View File

@@ -0,0 +1,43 @@
#include "Image.h"

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdexcept>

#include "util.h"

namespace Cygnet {

// TODO: Maybe this should be conditional based on endianness?
static SDL_PixelFormatEnum format = SDL_PIXELFORMAT_ABGR8888;

Image::Image(std::string path) {
CPtr<SDL_Surface, SDL_FreeSurface> surface(IMG_Load(path.c_str()));
if (!surface.get()) {
throw std::runtime_error("Failed to load " + path + ": " + IMG_GetError());
}

if (surface->format->format != format) {
printf("Converting pixel format for %s", path.c_str());
surface.reset(SDL_ConvertSurfaceFormat(surface.get(), format, 0));
if (!surface.get()) {
throw std::runtime_error("Failed convert " + path + ": " + SDL_GetError());
}
}

w_ = surface->w;
h_ = surface->h;
pitch_ = surface->pitch;
bytes_.reset(surface->pixels);
surface->pixels = nullptr;
}

GlTexture &Image::texture() {
if (tex_dirty_) {
tex_.upload(w_, h_, bytes_.get(), GL_RGBA);
}

return tex_;
}

}

+ 5
- 2
libcygnet/src/Window.cc View File

@@ -22,6 +22,10 @@ Window::Window(const char *name, int width, int height) {
sdlAssert(glctx_ = SDL_GL_CreateContext(win_.get()));
makeCurrent();
glCheck();

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glCheck();
}

Window::~Window() {
@@ -33,13 +37,12 @@ void Window::makeCurrent() {
}

void Window::clear() {
glClearColor(0, 0, 0, 1);
//glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
}

void Window::flip() {
SDL_GL_SwapWindow(win_.get());

}

}

libcygnet/src/BuiltinShaders.cc → libcygnet/src/builtins.cc View File

@@ -1,9 +1,9 @@
#include "BuiltinShaders.h"
#include "builtins.h"

namespace Cygnet {

BuiltinShaders::BuiltinShaders():
textureVertex(GlShader::Type::VERTEX, R"(
const GlShader &builtinTextureVertex() {
static GlShader shader(GlShader::Type::VERTEX, R"(
attribute vec4 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
@@ -11,21 +11,30 @@ BuiltinShaders::BuiltinShaders():
gl_Position = position;
v_texCoord = texCoord;
}
)"),
)");
return shader;
}

textureFragment(GlShader::Type::FRAGMENT, R"(
const GlShader &builtinTextureFragment() {
static GlShader shader(GlShader::Type::FRAGMENT, R"(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, v_texCoord);
}
)"),
)");
return shader;
}

whiteFragment(GlShader::Type::FRAGMENT, R"(
const GlShader &builtinWhiteFragment() {
static GlShader shader(GlShader::Type::FRAGMENT, R"(
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
)") {}
)");
return shader;
}

}

Loading…
Cancel
Save