Procházet zdrojové kódy

progress, and almost-working hello-texture sample

opengl-renderer-broken
Martin Dørum před 4 roky
rodič
revize
c81d8bd54e

+ 7
- 1
libcygnet/CMakeLists.txt Zobrazit soubor

add_library(cygnet SHARED add_library(cygnet SHARED
src/GlProgram.cc
src/BuiltinShaders.cc
src/glutil.cc
src/GlWrappers.cc
src/Window.cc) src/Window.cc)
target_link_libraries(cygnet PUBLIC SDL2 GLESv2) target_link_libraries(cygnet PUBLIC SDL2 GLESv2)
target_include_directories(cygnet target_include_directories(cygnet
add_executable(cygnet-hello-triangle add_executable(cygnet-hello-triangle
samples/hello-triangle/hello-triangle.cc) samples/hello-triangle/hello-triangle.cc)
target_link_libraries(cygnet-hello-triangle PUBLIC cygnet) 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 Zobrazit soubor

#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 Zobrazit soubor

FRAGMENT, FRAGMENT,
}; };


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


GLuint id() const { return id_; } GLuint id() const { return id_; }


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


class GlProgram: NonCopyable { class GlProgram: NonCopyable {


void use() { glUseProgram(id_); } void use() { glUseProgram(id_); }
GLuint id() { return 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: private:
GLuint id_; GLuint id_;
bool valid_ = false;
}; };


} }

+ 9
- 0
libcygnet/include/cygnet/glutil.h Zobrazit soubor

#pragma once

namespace Cygnet {

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

}

+ 88
- 0
libcygnet/samples/hello-texture/hello-texture.cc Zobrazit soubor

#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 Zobrazit soubor

#include <cygnet/Window.h> #include <cygnet/Window.h>
#include <cygnet/GlProgram.h>
#include <cygnet/GlWrappers.h>
#include <iostream> #include <iostream>


const char *vertexSource = R"( const char *vertexSource = R"(
Cygnet::Deferred<SDL_Quit> sdl; Cygnet::Deferred<SDL_Quit> sdl;
Cygnet::Window win("Hello Triangle", 640, 480); 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); Cygnet::GlProgram program(vertex, fragment);
GLuint positionAttrib = program.getLocation("position");
GLuint positionAttrib = program.attribLocation("position");
program.use(); program.use();


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

+ 31
- 0
libcygnet/src/BuiltinShaders.cc Zobrazit soubor

#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 Zobrazit soubor

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


#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>


#include "glutil.h"

namespace Cygnet { namespace Cygnet {


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


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


char log[4096]; char log[4096];
GLsizei length;
GLsizei length = 0;
glGetShaderInfoLog(id_, sizeof(log), &length, log); glGetShaderInfoLog(id_, sizeof(log), &length, log);
glCheck();
if (length != 0) { 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); glGetShaderiv(id_, GL_COMPILE_STATUS, &status);
glCheck();
if (status == GL_FALSE) { if (status == GL_FALSE) {
id_ = -1;
throw std::runtime_error("GL shader compilation failed."); throw std::runtime_error("GL shader compilation failed.");
} }

valid_ = true;
} }


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


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


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


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

valid_ = true;
} }


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


} }

+ 5
- 3
libcygnet/src/Window.cc Zobrazit soubor

#include "Window.h" #include "Window.h"


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

#include "glutil.h"


namespace Cygnet { namespace Cygnet {


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


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


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

+ 36
- 0
libcygnet/src/glutil.cc Zobrazit soubor

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

}

Načítá se…
Zrušit
Uložit