Browse Source

libcygnets and hello-triangle

opengl-renderer-broken
Martin Dørum 4 years ago
parent
commit
84eb225142

+ 1
- 1
CMakeLists.txt View File

@@ -52,7 +52,6 @@ else()
message(FATAL_ERROR "CMAKE_BUILD_TYPE must be Debug or Release.")
endif()


# We want to be able to use C++20 designated initializers,
# but Clang doesn't support them yet.
# Remove once Clang 9.1 or something comes out.
@@ -63,6 +62,7 @@ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib

add_subdirectory(third-party)
add_subdirectory(tracy-tools)
add_subdirectory(libcygnet)
add_subdirectory(libswan)
add_subdirectory(core.mod)


+ 11
- 0
libcygnet/CMakeLists.txt View File

@@ -0,0 +1,11 @@
add_library(cygnet SHARED
src/GlProgram.cc
src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 GLESv2)
target_include_directories(cygnet
PUBLIC include
PRIVATE include/cygnet)

add_executable(cygnet-hello-triangle
samples/hello-triangle/hello-triangle.cc)
target_link_libraries(cygnet-hello-triangle PUBLIC cygnet)

+ 43
- 0
libcygnet/include/cygnet/GlProgram.h View File

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

#include <vector>
#include <initializer_list>
#include <functional>
#include <SDL_opengles2.h>

#include "util.h"

namespace Cygnet {

class GlShader: NonCopyable {
public:
enum class Type {
VERTEX,
FRAGMENT,
};

GlShader(const char *source, Type type);
~GlShader();

GLuint id() { return id_; }

private:
GLuint id_;
bool valid_ = false;
};

class GlProgram: NonCopyable {
public:
GlProgram(std::initializer_list<std::reference_wrapper<GlShader>> shaders);
~GlProgram();

void use() { glUseProgram(id_); }
GLuint id() { return id_; }
GLuint getLocation(const char *name) { return glGetAttribLocation(id_, name); }

private:
GLuint id_;
bool valid_ = false;
};

}

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

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

#include <SDL.h>
#include <stdint.h>

#include "util.h"

namespace Cygnet {

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

void makeCurrent();
void clear();
void flip();

private:
CPtr<SDL_Window, SDL_DestroyWindow> win_;
SDL_GLContext glctx_;
};

}

+ 37
- 0
libcygnet/include/cygnet/util.h View File

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

#include <memory>

/*
* This file mostly just contains copy-pasted stuff from libswan.
* I don't love the code duplication, but it feels overkill to have a
* library which both libcygnet and libswan depends on just for this stuff.
*/

namespace Cygnet {

// Inherit from this class to make a class non-copyable
class NonCopyable {
public:
NonCopyable(const NonCopyable &) = delete;
NonCopyable(NonCopyable &&) noexcept = default;
NonCopyable &operator=(const NonCopyable &) = delete;
NonCopyable &operator=(NonCopyable &&) = default;

protected:
NonCopyable() = default;
~NonCopyable() = default;
};

// Take a deleter function, turn it into a class with an operator() for unique_ptr
template<typename T, void (*Func)(T *)>
class CPtrDeleter {
public:
void operator()(T *ptr) { Func(ptr); }
};

// This is just a bit nicer to use than using unique_ptr directly
template<typename T, void (*Func)(T *)>
using CPtr = std::unique_ptr<T, CPtrDeleter<T, Func>>;

}

+ 57
- 0
libcygnet/samples/hello-triangle/hello-triangle.cc View File

@@ -0,0 +1,57 @@
#include <cygnet/Window.h>
#include <cygnet/GlProgram.h>
#include <iostream>

const char *vertexSource = R"(
attribute vec4 position;
void main() {
gl_Position = vec4(position.xyz, 1.0);
}
)";

const char *fragmentSource = R"(
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
)";

int main() {
SDL_Init(SDL_INIT_VIDEO);
Cygnet::Window win("Hello Triangle", 640, 480);

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

GLfloat vertixes[] = {
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
};

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

win.clear();

glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertixes);
glEnableVertexAttribArray(positionAttrib);
glDrawArrays(GL_TRIANGLES, 0, 3);

win.flip();
}

exit:
SDL_Quit();
}

+ 76
- 0
libcygnet/src/GlProgram.cc View File

@@ -0,0 +1,76 @@
#include "GlProgram.h"

#include <iostream>
#include <stdexcept>

namespace Cygnet {

GlShader::GlShader(const char *source, Type type) {
switch (type) {
case Type::VERTEX:
id_ = glCreateShader(GL_VERTEX_SHADER);
break;
case Type::FRAGMENT:
id_ = glCreateShader(GL_FRAGMENT_SHADER);
break;
}

glShaderSource(id_, 1, &source, NULL);
glCompileShader(id_);

char log[4096];
GLsizei length;
glGetShaderInfoLog(id_, sizeof(log), &length, log);
if (length != 0) {
std::cerr << "Shader compile info:\n" << log << '\n';
}

GLint status;
glGetShaderiv(id_, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
id_ = -1;
throw std::runtime_error("GL shader compilation failed.");
}

valid_ = true;
}

GlShader::~GlShader() {
if (valid_) {
glDeleteShader(id_);
}
}

GlProgram::GlProgram(std::initializer_list<std::reference_wrapper<GlShader>> shaders) {
id_ = glCreateProgram();

for (GlShader &shader: shaders) {
glAttachShader(id_, shader.id());
}

glLinkProgram(id_);

char log[4096];
GLsizei length;
glGetProgramInfoLog(id_, sizeof(log), &length, log);
if (length != 0) {
std::cerr << "Program link info:\n" << log << '\n';
}

GLint status;
glGetProgramiv(id_, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
id_ = -1;
throw std::runtime_error("GL program link failed.");
}

valid_ = true;
}

GlProgram::~GlProgram() {
if (valid_) {
glDeleteProgram(id_);
}
}

}

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

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

#include <SDL_opengles2.h>
#include <assert.h>

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

assert(glctx_ = SDL_GL_CreateContext(win_.get()));
makeCurrent();
assert(SDL_GL_SetSwapInterval(1) == 0);
}

Window::~Window() {
SDL_GL_DeleteContext(glctx_);
}

void Window::makeCurrent() {
SDL_GL_MakeCurrent(win_.get(), glctx_);
}

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

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

}

}

Loading…
Cancel
Save