Browse Source

progress, and almost-working hello-texture sample

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

+ 7
- 1
libcygnet/CMakeLists.txt View File

@@ -1,5 +1,7 @@
add_library(cygnet SHARED
src/GlProgram.cc
src/BuiltinShaders.cc
src/glutil.cc
src/GlWrappers.cc
src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 GLESv2)
target_include_directories(cygnet
@@ -9,3 +11,7 @@ target_include_directories(cygnet
add_executable(cygnet-hello-triangle
samples/hello-triangle/hello-triangle.cc)
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)

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

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

#include "GlWrappers.h"

namespace Cygnet {

struct BuiltinShaders {
BuiltinShaders();

GlShader textureVertex;
GlShader textureFragment;
GlShader whiteFragment;
};

}

libcygnet/include/cygnet/GlProgram.h → libcygnet/include/cygnet/GlWrappers.h View File

@@ -16,14 +16,13 @@ public:
FRAGMENT,
};

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

GLuint id() const { return id_; }

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

class GlProgram: NonCopyable {
@@ -38,11 +37,11 @@ public:

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

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

}

+ 9
- 0
libcygnet/include/cygnet/glutil.h View File

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

namespace Cygnet {

const char *glErrorString(int err);
void glCheck();
void sdlAssert(bool val);

}

+ 88
- 0
libcygnet/samples/hello-texture/hello-texture.cc View File

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

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

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

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

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

uint8_t image[] = {
0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xff, 0x00, 0xba,
0xaa, 0xaa, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xa0, 0x55, 0x77, 0x00, 0xf0, 0x0f, 0xff, 0x00, 0xff,
};

GLuint texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
Cygnet::glCheck();

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.attribLocation("position");
GLint texCoordLoc = program.attribLocation("texCoord");
GLint texLoc = program.uniformLocation("tex");

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

win.clear();

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

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

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

win.flip();
}

exit:
return EXIT_SUCCESS;
}

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

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

const char *vertexSource = R"(
@@ -21,10 +21,10 @@ int main() {
Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Hello Triangle", 640, 480);

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

GLfloat vertixes[] = {

+ 31
- 0
libcygnet/src/BuiltinShaders.cc View File

@@ -0,0 +1,31 @@
#include "BuiltinShaders.h"

namespace Cygnet {

BuiltinShaders::BuiltinShaders():
textureVertex(GlShader::Type::VERTEX, R"(
attribute vec4 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
void main() {
gl_Position = position;
v_texCoord = texCoord;
}
)"),

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

whiteFragment(GlShader::Type::FRAGMENT, R"(
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
)") {}
}

libcygnet/src/GlProgram.cc → libcygnet/src/GlWrappers.cc View File

@@ -1,71 +1,75 @@
#include "GlProgram.h"
#include "GlWrappers.h"

#include <iostream>
#include <stdexcept>

#include "glutil.h"

namespace Cygnet {

GlShader::GlShader(const char *source, Type type) {
GlShader::GlShader(Type type, const char *source) {
switch (type) {
case Type::VERTEX:
id_ = glCreateShader(GL_VERTEX_SHADER);
glCheck();
std::cerr << "compiling vertex shader...\n";
break;
case Type::FRAGMENT:
id_ = glCreateShader(GL_FRAGMENT_SHADER);
glCheck();
std::cerr << "compiling fragment shader...\n";
break;
}

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

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

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

valid_ = true;
}

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

void GlProgram::link() {
std::cout << "link\n";
glLinkProgram(id_);
glCheck();

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

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

valid_ = true;
}

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

}

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

@@ -1,7 +1,8 @@
#include "Window.h"

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

#include "glutil.h"

namespace Cygnet {

@@ -16,10 +17,11 @@ Window::Window(const char *name, int width, int height) {
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();

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

Window::~Window() {

+ 36
- 0
libcygnet/src/glutil.cc View File

@@ -0,0 +1,36 @@
#include "glutil.h"

#include <SDL.h>
#include <SDL_opengles2.h>
#include <stdexcept>

namespace Cygnet {

const char *glErrorString(int err) {
#define errcase(x) case x: return #x
switch (err) {
errcase(GL_NO_ERROR);
errcase(GL_INVALID_ENUM);
errcase(GL_INVALID_VALUE);
errcase(GL_INVALID_OPERATION);
errcase(GL_INVALID_FRAMEBUFFER_OPERATION);
errcase(GL_OUT_OF_MEMORY);
default: return "(unknown)";
}
#undef errcase
}

void glCheck() {
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
throw std::runtime_error(glErrorString(err));
}
}

void sdlAssert(bool val) {
if (!val) {
throw std::runtime_error(SDL_GetError());
}
}

}

Loading…
Cancel
Save