Преглед изворни кода

lots of cygnet stuff

opengl-renderer-broken
Martin Dørum пре 3 година
родитељ
комит
719e391df8

+ 14
- 2
libcygnet/CMakeLists.txt Прегледај датотеку

add_library(cygnet SHARED add_library(cygnet SHARED
src/BuiltinShaders.cc
src/builtins.cc
src/glutil.cc src/glutil.cc
src/GlWrappers.cc src/GlWrappers.cc
src/Image.cc
src/Window.cc) src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 GLESv2)
target_link_libraries(cygnet PUBLIC SDL2 SDL2_image GLESv2)
target_include_directories(cygnet target_include_directories(cygnet
PUBLIC include PUBLIC include
PRIVATE include/cygnet) PRIVATE include/cygnet)
add_executable(cygnet-hello-texture add_executable(cygnet-hello-texture
samples/hello-texture/hello-texture.cc) samples/hello-texture/hello-texture.cc)
target_link_libraries(cygnet-hello-texture PUBLIC cygnet) 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 Прегледај датотеку

#include <optional>

#include "GlWrappers.h"

namespace Cygnet {

struct BuiltinShaders {
BuiltinShaders();

GlShader textureVertex;
GlShader textureFragment;
GlShader whiteFragment;
};

}

+ 29
- 2
libcygnet/include/cygnet/GlWrappers.h Прегледај датотеку



void use() { glUseProgram(id_); } void use() { glUseProgram(id_); }
GLuint id() { return 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: private:
GLuint id_; 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 Прегледај датотеку

#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 Прегледај датотеку



#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 Window { class Window {
public: public:
Window(const char *name, int width, int height); Window(const char *name, int width, int height);

+ 11
- 0
libcygnet/include/cygnet/builtins.h Прегледај датотеку

#include <optional>

#include "GlWrappers.h"

namespace Cygnet {

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

}

BIN
libcygnet/samples/game/assets-src/player.xcf Прегледај датотеку


BIN
libcygnet/samples/game/assets/player.png Прегледај датотеку


+ 164
- 0
libcygnet/samples/game/game.cc Прегледај датотеку

#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 Прегледај датотеку

#include <cygnet/Window.h> #include <cygnet/Window.h>
#include <cygnet/GlWrappers.h> #include <cygnet/GlWrappers.h>
#include <cygnet/BuiltinShaders.h>
#include <cygnet/builtins.h>
#include <cygnet/glutil.h> #include <cygnet/glutil.h>
#include <iostream> #include <iostream>


Cygnet::Deferred<SDL_Quit> sdl; Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Hello Texture", 640, 480); 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(); program.use();


GLfloat vertexes[] = { GLfloat vertexes[] = {
0xa0, 0x55, 0x77, 0x00, 0xf0, 0x0f, 0xff, 0x00, 0xff, 0, 0, 0, 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 // Draw loop
while (true) { while (true) {
glEnableVertexAttribArray(texCoordLoc); glEnableVertexAttribArray(texCoordLoc);
Cygnet::glCheck(); 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); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
Cygnet::glCheck(); Cygnet::glCheck();



+ 1
- 1
libcygnet/samples/hello-triangle/hello-triangle.cc Прегледај датотеку

Cygnet::GlShader vertex(Cygnet::GlShader::Type::VERTEX, vertexSource); Cygnet::GlShader vertex(Cygnet::GlShader::Type::VERTEX, vertexSource);
Cygnet::GlShader fragment(Cygnet::GlShader::Type::FRAGMENT, fragmentSource); Cygnet::GlShader fragment(Cygnet::GlShader::Type::FRAGMENT, fragmentSource);
Cygnet::GlProgram program(vertex, fragment); Cygnet::GlProgram program(vertex, fragment);
GLuint positionAttrib = program.attribLocation("position");
GLuint positionAttrib = program.attribLoc("position");
program.use(); program.use();


GLfloat vertixes[] = { GLfloat vertixes[] = {

+ 21
- 0
libcygnet/src/GlWrappers.cc Прегледај датотеку

glDeleteProgram(id_); 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 Прегледај датотеку

#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 Прегледај датотеку

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

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


Window::~Window() { Window::~Window() {
} }


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


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

} }


} }

libcygnet/src/BuiltinShaders.cc → libcygnet/src/builtins.cc Прегледај датотеку

#include "BuiltinShaders.h"
#include "builtins.h"


namespace Cygnet { namespace Cygnet {


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


textureFragment(GlShader::Type::FRAGMENT, R"(
const GlShader &builtinTextureFragment() {
static GlShader shader(GlShader::Type::FRAGMENT, R"(
precision mediump float; precision mediump float;
varying vec2 v_texCoord; varying vec2 v_texCoord;
uniform sampler2D tex; uniform sampler2D tex;
void main() { void main() {
gl_FragColor = texture2D(tex, v_texCoord); 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; precision mediump float;
void main() { void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
} }
)") {}
)");
return shader;
}

} }

Loading…
Откажи
Сачувај