Added a small opengl test app that I wrote a while ago, to be further processed into an opengl renderer.

This commit is contained in:
Relintai 2021-11-16 08:56:43 +01:00
parent 19a70a5507
commit 70ffbbae20
36 changed files with 3621 additions and 0 deletions

View File

@ -0,0 +1,117 @@
#include "application.h"
#include <chrono>
Application *Application::_instance = nullptr;
void Application::event(const SDL_Event &ev) {
if (ev.type == SDL_QUIT) {
running = false;
}
scene->event(ev);
}
void Application::update(float delta) {
scene->update(delta);
}
void Application::render() {
scene->render();
SDL_GL_SwapWindow(window);
}
void Application::main_loop() {
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
//handle input
SDL_Event current_event;
while (SDL_PollEvent(&current_event)) {
event(current_event);
}
//update world
update(frame_delta);
//render
render();
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
double t = elapsed_seconds.count();
double tfps = 1.0 / static_cast<float>(target_fps);
double remaining = tfps - t;
if (remaining > 0) {
Uint32 fms = static_cast<Uint32>(remaining * 1000.0);
frame_delta = tfps;
SDL_Delay(fms);
} else {
frame_delta = t;
}
}
Application *Application::get_singleton() {
return _instance;
}
Application::Application() {
_instance = this;
running = true;
target_fps = 60;
scene = nullptr;
frame_delta = 0;
SDL_SetMainReady();
int error = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
if (error) {
SDL_Log("SDL_Init: %s", SDL_GetError());
running = false;
return;
}
#if _WIN64
//Use OpenGl 2.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#else
//Use OpenGl ES 2.0
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#endif
window = SDL_CreateWindow("SDL + OpenGL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) {
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
running = false;
return;
}
context = SDL_GL_CreateContext(window);
#ifdef _WIN64
gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress);
#endif
}
Application::~Application() {
SDL_DestroyWindow(window);
window = nullptr;
SDL_Quit();
}

View File

@ -0,0 +1,38 @@
#ifndef APPLICATION_H
#define APPLICATION_H
#include "sdl.inc.h"
#include "opengl.h"
#include <stdio.h>
#include "scene.h"
class Application {
public:
bool running;
int target_fps;
virtual void event(const SDL_Event &ev);
virtual void update(float delta);
virtual void render();
void main_loop();
Application();
virtual ~Application();
Scene *scene;
SDL_Window *window;
SDL_GLContext context;
static Application* get_singleton();
double frame_delta;
protected:
static Application* _instance;
};
#endif

View File

@ -0,0 +1,95 @@
#include "camera.h"
#include "./glm/gtc/matrix_transform.hpp"
Camera *Camera::current_camera = nullptr;
void Camera::bind() {
make_current();
model_view_matrix = glm::mat4(1);
}
void Camera::make_current() {
current_camera = this;
}
Camera::Camera() {
width = 2;
height = 2;
fov = glm::radians(45.0);
position = glm::vec3(0, 0, 0);
rotation = glm::vec3(0, 0, 0);
scale = glm::vec3(1, 1, 1);
}
Camera::~Camera() {
}
void OrthographicCamera::bind() {
Camera::bind();
//fixed function pipeline
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
//glOrtho(bottom_left.x, top_right.x, bottom_left.y, top_right.y, near, far);
//glTranslatef(position.x, position.y, 0);
//glRotatef(rotation.x, 1, 0, 0);
//glRotatef(rotation.y, 0, 1, 0);
//glRotatef(rotation.z, 0, 0, 1);
//glScalef(scale.x, scale.y, scale.z);
projection_matrix = glm::ortho<float>(-(width / 2.0), width / 2.0, -(height / 2.0), height / 2.0);
projection_matrix = glm::translate(projection_matrix, -position);
projection_matrix = glm::rotate(projection_matrix, rotation.x, glm::vec3(1, 0, 0));
projection_matrix = glm::rotate(projection_matrix, rotation.y, glm::vec3(0, 1, 0));
projection_matrix = glm::rotate(projection_matrix, rotation.z, glm::vec3(0, 0, 1));
projection_matrix = glm::scale(projection_matrix, scale);
}
OrthographicCamera::OrthographicCamera() : Camera() {
}
OrthographicCamera::~OrthographicCamera() {
}
void PerspectiveCamera::bind() {
Camera::bind();
//fixed fucntion pipeline
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
//glFrustum(bottom_left.x, top_right.x, bottom_left.y, top_right.y, near, far);
//glTranslatef(position.x, position.y, position.z);
//glRotatef(rotation.x, 1, 0, 0);
//glRotatef(rotation.y, 0, 1, 0);
//glRotatef(rotation.z, 0, 0, 1);
//glScalef(scale.x, scale.y, scale.z);
projection_matrix = glm::perspectiveFov<float>(fov, width, height, near, far);
projection_matrix = glm::translate(projection_matrix, -position);
projection_matrix = glm::rotate(projection_matrix, rotation.x, glm::vec3(1, 0, 0));
projection_matrix = glm::rotate(projection_matrix, rotation.y, glm::vec3(0, 1, 0));
projection_matrix = glm::rotate(projection_matrix, rotation.z, glm::vec3(0, 0, 1));
projection_matrix = glm::scale(projection_matrix, scale);
}
PerspectiveCamera::PerspectiveCamera() : Camera() {
near = 0.1;
far = 10;
}
PerspectiveCamera::~PerspectiveCamera() {
}

View File

@ -0,0 +1,52 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "opengl.h"
#include "./glm/vec3.hpp"
#include "./glm/matrix.hpp"
class Camera {
public:
virtual void bind();
void make_current();
Camera();
virtual ~Camera();
float width;
float height;
float fov;
glm::vec3 position;
glm::vec3 rotation;
glm::vec3 scale;
static Camera *current_camera;
glm::mat4x4 projection_matrix;
glm::mat4x4 model_view_matrix;
};
class OrthographicCamera : public Camera {
public:
void bind();
OrthographicCamera();
~OrthographicCamera();
};
class PerspectiveCamera : public Camera {
public:
float near;
float far;
void bind();
PerspectiveCamera();
~PerspectiveCamera();
};
#endif

View File

@ -0,0 +1,68 @@
#ifndef COLOR_MATERIAL_H
#define COLOR_MATERIAL_H
#include "material.h"
#include "glm/vec4.hpp"
#include "camera.h"
#include "./glm/gtc/type_ptr.hpp"
class ColorMaterial : public Material {
public:
int get_material_id() {
return 2;
}
void bind_uniforms() {
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->projection_matrix));
glUniformMatrix4fv(model_view_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->model_view_matrix));
}
void setup_uniforms() {
projection_matrix_location = get_uniform("u_proj_matrix");
model_view_matrix_location = get_uniform("u_model_view_matrix");
}
const GLchar** get_vertex_shader_source() {
static const GLchar *vertex_shader_source[] = {
"uniform mat4 u_proj_matrix;\n"
"uniform mat4 u_model_view_matrix;\n"
"\n"
"attribute vec4 a_position;\n"
"attribute vec4 a_color;\n"
"\n"
"varying vec4 v_color;\n"
"\n"
"void main() {\n"
" v_color = a_color;\n"
" gl_Position = u_proj_matrix * u_model_view_matrix * a_position;\n"
"}\n"
};
return vertex_shader_source;
}
const GLchar** get_fragment_shader_source() {
static const GLchar *fragment_shader_source[] = {
"precision mediump float;"
"varying vec4 v_color;\n"
"\n"
"void main() { gl_FragColor = v_color; }\n"
};
return fragment_shader_source;
}
ColorMaterial() {
color = glm::vec4(1, 1, 1, 1);
}
GLint projection_matrix_location;
GLint model_view_matrix_location;
glm::vec4 color;
};
#endif

View File

@ -0,0 +1,66 @@
#ifndef COLORED_MATERIAL_H
#define COLORED_MATERIAL_H
#include "material.h"
#include "glm/vec4.hpp"
#include "camera.h"
#include "./glm/gtc/type_ptr.hpp"
class ColoredMaterial : public Material {
public:
int get_material_id() {
return 1;
}
void bind_uniforms() {
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->projection_matrix));
glUniformMatrix4fv(model_view_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->model_view_matrix));
glUniform4f(tri_color_uniform_location, color.r, color.g, color.b, color.a);
}
void setup_uniforms() {
projection_matrix_location = get_uniform("u_proj_matrix");
model_view_matrix_location = get_uniform("u_model_view_matrix");
tri_color_uniform_location = get_uniform("fragment_color");
}
const GLchar** get_vertex_shader_source() {
static const GLchar *vertex_shader_source[] = {
"uniform mat4 u_proj_matrix;\n"
"uniform mat4 u_model_view_matrix;\n"
"\n"
"attribute vec4 a_position;\n"
"void main() { gl_Position = u_proj_matrix * u_model_view_matrix * a_position; }"
};
return vertex_shader_source;
}
const GLchar** get_fragment_shader_source() {
static const GLchar *fragment_shader_source[] = {
"precision mediump float;"
"uniform vec4 fragment_color = vec4(1, 1, 1, 1);"
""
"void main() { gl_FragColor = fragment_color; }"
};
return fragment_shader_source;
}
ColoredMaterial() {
color = glm::vec4(1, 1, 1, 1);
}
GLint projection_matrix_location;
GLint model_view_matrix_location;
GLint tri_color_uniform_location;
glm::vec4 color;
};
#endif

View File

@ -0,0 +1,20 @@
#ifndef GAME_APPLICATION_H
#define GAME_APPLICATION_H
#include "application.h"
#include "game_scene.h"
class GameApplication : public Application {
public:
GameApplication() : Application() {
scene = new GameScene();
}
~GameApplication() {
delete scene;
}
};
#endif

View File

@ -0,0 +1,165 @@
#include "game_scene.h"
#include "application.h"
void GameScene::event(const SDL_Event &ev) {
switch (ev.type) {
case SDL_WINDOWEVENT: {
switch (ev.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED: {
int width = ev.window.data1;
int height = ev.window.data2;
float ar = static_cast<float>(width) / static_cast<float>(height);
camera->width = camera->height * ar;
glViewport(0, 0, width, height);
break;
}
}
break;
}
case SDL_KEYDOWN: {
if (ev.key.keysym.scancode == SDL_SCANCODE_A) {
left = true;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_W) {
up = true;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_S) {
down = true;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_D) {
right = true;
}
break;
}
case SDL_KEYUP: {
if (ev.key.keysym.scancode == SDL_SCANCODE_A) {
left = false;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_W) {
up = false;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_S) {
down = false;
} else if (ev.key.keysym.scancode == SDL_SCANCODE_D) {
right = false;
}
break;
}
}
}
void GameScene::update(float delta) {
if (up) {
sprite->position.y += delta * 3.0;
}
if (down) {
sprite->position.y -= delta * 3.0;
}
if (left) {
sprite->position.x -= delta * 3.0;
}
if (right) {
sprite->position.x += delta * 3.0;
}
if (sprite->position.x < 1.5) {
sprite->position.x = 1.5;
}
if (sprite->position.x > 14.5) {
sprite->position.x = 14.5;
}
if (sprite->position.y < 1.5) {
sprite->position.y = 1.5;
}
if (sprite->position.y > 14.5) {
sprite->position.y = 14.5;
}
}
void GameScene::render() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
camera->bind();
tile_map->render();
sprite->render();
}
GameScene::GameScene() {
left = false;
right = false;
up = false;
down = false;
camera = new OrthographicCamera();
camera->width = 16;
camera->height = 16;
camera->position.x = 8;
camera->position.y = 8;
//camera->position.z = -2;
int w;
int h;
SDL_GetWindowSize(Application::get_singleton()->window, &w, &h);
float ar = static_cast<float>(w) / static_cast<float>(h);
camera->width = camera->height * ar;
texture = new Texture();
texture->load_image("download.bmp");
//ha a textúrának van alpha csatornája:
//texture->load_image("download.bmp", GL_RGBA, GL_RGBA);
material = new TextureMaterial();
material->texture = texture;
sprite = new Sprite();
sprite->mesh_instance->material = material;
sprite->position.x = 8;
sprite->position.y = 8;
sprite->region_x = 7.0 * (1.0 / 16.0);
sprite->region_y = 7.0 * (1.0 / 16.0);
sprite->region_width = 1.0 / 16.0;
sprite->region_height = 1.0 / 16.0;
sprite->update_mesh();
tile_map = new TileMap();
tile_map->material = material;
tile_map->atlas_size_x = 16;
tile_map->atlas_size_y = 16;
tile_map->allocate_data();
for (int x = 0; x < tile_map->size_x; ++x) {
for (int y = 0; y < tile_map->size_y; ++y) {
if (x == 0 || y == 0 || x == tile_map->size_x - 1 || y == tile_map->size_y - 1) {
tile_map->set_data(x, y, 2);
} else {
tile_map->set_data(x, y, 1);
}
}
}
tile_map->build_mesh();
}
GameScene::~GameScene() {
delete camera;
delete texture;
delete material;
delete tile_map;
delete sprite;
}

View File

@ -0,0 +1,34 @@
#ifndef GAME_SCENE_H
#define GAME_SCENE_H
#include "scene.h"
#include "camera.h"
#include "mesh_instance.h"
#include "texture.h"
#include "texture_material.h"
#include "tile_map.h"
#include "sprite.h"
class GameScene : public Scene {
public:
virtual void event(const SDL_Event &ev);
virtual void update(float delta);
virtual void render();
GameScene();
~GameScene();
bool left;
bool right;
bool up;
bool down;
Camera *camera;
Texture *texture;
TextureMaterial *material;
TileMap *tile_map;
Sprite *sprite;
};
#endif

View File

@ -0,0 +1,31 @@
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "application.h"
#include "game_application.h"
#define APPLICATION_CLASS GameApplication
Application *application = nullptr;
void handle_frame() {
application->main_loop();
}
int main(int argc, char *argv[]) {
application = new APPLICATION_CLASS();
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(handle_frame, 0, 1);
#else
while (application->running) {
application->main_loop();
}
#endif
delete application;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,422 @@
#include <stdio.h>
#include <vector>
#define SDL_MAIN_HANDLED
#include "sdl.inc.h"
#include "opengl.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include <math.h>
SDL_Window *window;
SDL_GLContext context;
bool running = true;
#include "colored_material.h"
#include "color_material.h"
#include "texture_material.h"
#include "mesh.h"
#include "mesh_instance.h"
#include "mesh_utils.h"
#include "texture.h"
#include "camera.h"
ColoredMaterial *colored_material = nullptr;
ColorMaterial *color_material = nullptr;
TextureMaterial *texture_material = nullptr;
Texture *texture = nullptr;
Mesh *mesh = nullptr;
MeshInstance *mi = nullptr;
MeshInstance *mic = nullptr;
Camera *camera = nullptr;
void first_2d_triangle() {
if (!colored_material) {
colored_material = new ColoredMaterial();
colored_material->color.r = 0;
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
colored_material->bind();
//immediate mode
/*
glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.5);
glVertex2f(0.5, -0.5);
glVertex2f(-0.5, -0.5);
glEnd();*/
SDL_GL_SwapWindow(window);
}
float color_count = 0;
void first_2d_triangle_uniforms() {
if (!colored_material) {
colored_material = new ColoredMaterial();
colored_material->color.r = 0;
}
if (!mesh) {
/*
//2d
mesh = new Mesh(2);
mesh->add_vertex2(-0.5, 0.5);
mesh->add_vertex2(0.5, -0.5);
mesh->add_vertex2(-0.5, -0.5);
mesh->add_vertex2(0.5, 0.5);
mesh->add_triangle(0, 1, 2);
mesh->add_triangle(0, 1, 3);
*/
//3d
mesh = new Mesh();
mesh->add_vertex3(-0.5, 0.5, 0);
mesh->add_vertex3(0.5, -0.5, 0);
mesh->add_vertex3(-0.5, -0.5, 0);
mesh->add_vertex3(0.5, 0.5, 0);
mesh->add_triangle(0, 1, 2);
mesh->add_triangle(0, 1, 3);
mesh->upload();
}
color_count += 0.01;
if (color_count > 1)
color_count = 0;
colored_material->color.r = color_count;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
colored_material->bind();
mesh->render();
SDL_GL_SwapWindow(window);
}
void first_2d_triangle_uniforms_mi() {
if (!colored_material) {
colored_material = new ColoredMaterial();
colored_material->color.r = 0;
}
if (!mesh) {
mesh = new Mesh();
mesh->add_vertex3(-0.5, 0.5, 0);
mesh->add_vertex3(0.5, -0.5, 0);
mesh->add_vertex3(-0.5, -0.5, 0);
mesh->add_vertex3(0.5, 0.5, 0);
mesh->add_triangle(0, 1, 2);
mesh->add_triangle(0, 1, 3);
mesh->upload();
mi = new MeshInstance();
mi->material = colored_material;
mi->mesh = mesh;
}
color_count += 0.01;
if (color_count > 1)
color_count = 0;
mi->position.x = color_count;
mi->rotation.z = color_count * 100;
mi->scale.x = color_count;
colored_material->color.r = color_count;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
mi->render();
SDL_GL_SwapWindow(window);
}
void first_2d_triangle_uniforms_mi_children() {
if (!colored_material) {
colored_material = new ColoredMaterial();
colored_material->color.r = 0;
}
if (!mesh) {
mesh = new Mesh();
mesh->add_vertex3(-0.5, 0.5, 0);
mesh->add_vertex3(0.5, -0.5, 0);
mesh->add_vertex3(-0.5, -0.5, 0);
mesh->add_vertex3(0.5, 0.5, 0);
mesh->add_triangle(0, 1, 2);
mesh->add_triangle(0, 1, 3);
mesh->upload();
mi = new MeshInstance();
mi->material = colored_material;
mi->mesh = mesh;
mic = new MeshInstance();
mic->material = colored_material;
mic->mesh = mesh;
mic->scale = glm::vec3(0.8, 0.8, 0.8);
//mic->position.x = 0.5;
mi->children.push_back(mic);
}
color_count += 0.01;
if (color_count > 1)
color_count = 0;
//mi->position.x = color_count;
//mi->rotation.z = color_count * 100;
//mi->scale.x = color_count;
mi->position.x = color_count;
mic->position.x = sin(color_count);
mic->position.y = cos(color_count);
colored_material->color.r = color_count;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
mi->render();
SDL_GL_SwapWindow(window);
}
void cone_perspective() {
if (!camera) {
camera = new PerspectiveCamera();
camera->position.z = -2;
}
if (!color_material) {
color_material = new ColorMaterial();
// color_material->color.r = 0;
}
if (!mesh) {
mesh = new Mesh();
MeshUtils::create_cone(mesh);
mesh->upload();
mi = new MeshInstance();
mi->material = color_material;
mi->mesh = mesh;
}
color_count += 0.01;
if (color_count > 3)
color_count = 0;
// mi->position.x = color_count;
//mi->rotation.x = 210;
mi->rotation.y = color_count;
// mi->scale.x = color_count;
// color_material->color.r = color_count;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
camera->bind();
mi->render();
SDL_GL_SwapWindow(window);
}
void first_2d_triangle_uvs() {
if (!camera) {
camera = new PerspectiveCamera();
camera->position.z = -2;
}
if (!texture) {
texture = new Texture();
texture->load_image("download.bmp");
}
if (!texture_material) {
texture_material = new TextureMaterial();
texture_material->texture = texture;
}
if (!mesh) {
mesh = new Mesh();
mesh->add_uv(0, 0);
mesh->add_vertex3(-0.5, 0.5, 0);
mesh->add_uv(1, 1);
mesh->add_vertex3(0.5, -0.5, 0);
mesh->add_uv(0, 1);
mesh->add_vertex3(-0.5, -0.5, 0);
mesh->add_uv(1, 0);
mesh->add_vertex3(0.5, 0.5, 0);
mesh->add_triangle(0, 1, 2);
mesh->add_triangle(0, 1, 3);
mesh->upload();
mi = new MeshInstance();
mi->material = texture_material;
mi->mesh = mesh;
}
color_count += 0.01;
if (color_count > 1)
color_count = 0;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
camera->position.x = color_count;
camera->bind();
mi->render();
SDL_GL_SwapWindow(window);
}
int current_demo = 5;
//gameloop
void handle_frame() {
//handle input
SDL_Event current_evevnt;
while(SDL_PollEvent(&current_evevnt)) {
if (current_evevnt.type == SDL_QUIT) {
running = false;
}
}
//update world
//most ez nem kell
//render
switch (current_demo) {
case 0:
first_2d_triangle();
break;
case 1:
first_2d_triangle_uniforms();
break;
case 2:
first_2d_triangle_uniforms_mi();
break;
case 3:
first_2d_triangle_uniforms_mi_children();
break;
case 4:
cone_perspective();
break;
case 5:
first_2d_triangle_uvs();
break;
}
}
int main(int argc, char *argv[]) {
SDL_SetMainReady();
int error = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
if (error) {
SDL_Log("SDL_Init: %s", SDL_GetError());
return 1;
}
#if _WIN64
//Use OpenGl 2.1
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#else
//Use OpenGl ES 2.0
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#endif
window = SDL_CreateWindow("SDL + OpenGL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
if (!window) {
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
return 1;
}
context = SDL_GL_CreateContext(window);
#ifdef _WIN64
gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress);
#endif
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(handle_frame, 0, 1);
#else
while (running) {
handle_frame();
}
#endif
printf("%s\n", glGetString(GL_VERSION));
//if (vbo_init) {
// glDeleteBuffers(1, &triange_VBO);
// }
if (colored_material) {
delete colored_material;
}
SDL_DestroyWindow(window);
window = nullptr;
SDL_Quit();
return 0;
}

View File

@ -0,0 +1,62 @@
#include "material.h"
#include <stdio.h>
Material* Material::current_material = nullptr;
void Material::bind() {
//csak a main thread fogja meghívni!
if (!shader) {
shader = ShaderCache::get_singleton()->get_shader(get_material_id());
if (!shader) {
shader = new Shader();
shader->set_vertex_shader_source(get_vertex_shader_source());
shader->set_fragment_shader_source(get_fragment_shader_source());
shader->compile();
ShaderCache::get_singleton()->add_shader(get_material_id(), shader);
}
setup_uniforms();
}
if (current_material && current_material != this) {
current_material->unbind();
setup_state();
}
current_material = this;
shader->bind();
bind_uniforms();
}
void Material::unbind() {
}
void Material::bind_uniforms() {
}
void Material::setup_uniforms() {
}
void Material::setup_state() {
}
GLint Material::get_uniform(const char *name) {
GLint uniform = glGetUniformLocation(shader->program, name);
if (uniform == -1) {
printf("%s is not a valid glsl program variable!\n", name);
}
return uniform;
}
Material::Material() {
shader = nullptr;
}
Material::~Material() {
}

View File

@ -0,0 +1,30 @@
#ifndef MATERIAL_H
#define MATERIAL_H
#include "opengl.h"
#include "shader.h"
class Material {
public:
void bind();
virtual void unbind();
virtual int get_material_id() = 0;
virtual void bind_uniforms();
virtual void setup_uniforms();
virtual void setup_state();
virtual const GLchar** get_vertex_shader_source() = 0;
virtual const GLchar** get_fragment_shader_source() = 0;
GLint get_uniform(const char* name);
Material();
virtual ~Material();
protected:
static Material* current_material;
Shader* shader;
};
#endif

View File

@ -0,0 +1,179 @@
#include "mesh.h"
#include "shader.h"
void Mesh::add_vertex2(GLfloat x, GLfloat y) {
vertices.push_back(x);
vertices.push_back(y);
}
void Mesh::add_vertex3(GLfloat x, GLfloat y, GLfloat z) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
}
void Mesh::add_normal(GLfloat x, GLfloat y, GLfloat z) {
normals.push_back(x);
normals.push_back(y);
normals.push_back(z);
}
void Mesh::add_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
colors.push_back(r);
colors.push_back(g);
colors.push_back(b);
colors.push_back(a);
}
void Mesh::add_uv(GLfloat u, GLfloat v) {
uvs.push_back(u);
uvs.push_back(v);
}
void Mesh::add_index(GLuint index) {
indices.push_back(index);
}
void Mesh::add_triangle(GLuint i1, GLuint i2, GLuint i3) {
indices.push_back(i1);
indices.push_back(i2);
indices.push_back(i3);
}
void Mesh::clear() {
vertices.clear();
normals.clear();
colors.clear();
uvs.clear();
indices.clear();
}
void Mesh::upload() {
if (vertices.size() == 0)
return;
if (!VBO) {
glGenBuffers(1, &VBO);
}
vertices_vbo_size = sizeof(GLfloat) * vertices.size();
normals_vbo_size = sizeof(GLfloat) * normals.size();
colors_vbo_size = sizeof(GLfloat) * colors.size();
uvs_vbo_size = sizeof(GLfloat) * uvs.size();
indices_vbo_size = sizeof(GLfloat) * indices.size();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, &vertices[0]);
if (normals_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, &normals[0]);
}
if (colors_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, &colors[0]);
}
if (uvs_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, &uvs[0]);
}
if (indices_vbo_size > 0) {
if (!IBO) {
glGenBuffers(1, &IBO);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, &indices[0], GL_STATIC_DRAW);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Mesh::destroy() {
if (VBO) {
glDeleteBuffers(1, &VBO);
}
if (IBO) {
glDeleteBuffers(1, &IBO);
}
}
void Mesh::render() {
if (vertices.size() == 0 || !VBO)
return;
if (!Shader::current_shader)
return;
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(Shader::ATTRIBUTE_POSITION, vertex_dimensions, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, (void *)(vertices_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_FALSE, 0, (void *)(vertices_vbo_size + normals_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_UV, 2, GL_FLOAT, GL_FALSE, 0, (void *)(vertices_vbo_size + normals_vbo_size + colors_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
if (indices_vbo_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid*)0);
} else {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
}
glDisableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Mesh::Mesh() {
VBO = 0;
IBO = 0;
vertex_dimensions = 3;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::Mesh(int vert_dim) {
VBO = 0;
IBO = 0;
vertex_dimensions = vert_dim;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::~Mesh() {
destroy();
clear();
}

View File

@ -0,0 +1,50 @@
#ifndef MESH_H
#define MESH_H
#include <vector>
#include "opengl.h"
using namespace std;
class Mesh {
public:
void add_vertex2(GLfloat x, GLfloat y);
void add_vertex3(GLfloat x, GLfloat y, GLfloat z);
void add_normal(GLfloat x, GLfloat y, GLfloat z);
void add_color(GLfloat r = 1, GLfloat g = 1, GLfloat b = 1, GLfloat a = 1);
void add_uv(GLfloat u, GLfloat v);
void add_index(GLuint index);
void add_triangle(GLuint i1, GLuint i2, GLuint i3);
void clear();
void upload();
void destroy();
void render();
Mesh();
Mesh(int vert_dim);
virtual ~Mesh();
GLuint VBO;
GLuint IBO;
int vertex_dimensions;
vector<GLfloat> vertices;
vector<GLfloat> normals;
vector<GLfloat> colors;
vector<GLfloat> uvs;
vector<GLuint> indices;
protected:
size_t vertices_vbo_size;
size_t normals_vbo_size;
size_t colors_vbo_size;
size_t uvs_vbo_size;
size_t indices_vbo_size;
};
#endif

View File

@ -0,0 +1,61 @@
#include "mesh_instance.h"
#include "camera.h"
#include "./glm/vec3.hpp"
#include "./glm/matrix.hpp"
#include "./glm/gtc/matrix_transform.hpp"
void MeshInstance::render() {
if (!mesh)
return;
//glMatrixMode(GL_MODELVIEW);
//glPushMatrix();
//glTranslatef(position.x, position.y, position.z);
//glRotatef(rotation.x, 1, 0, 0);
//glRotatef(rotation.y, 0, 1, 0);
//glRotatef(rotation.z, 0, 0, 1);
//glScalef(scale.x, scale.y, scale.z);
glm::mat4 mat_oring = Camera::current_camera->model_view_matrix;
Camera::current_camera->model_view_matrix = glm::translate(Camera::current_camera->model_view_matrix, position);
Camera::current_camera->model_view_matrix = glm::rotate(Camera::current_camera->model_view_matrix, rotation.x, glm::vec3(1, 0, 0));
Camera::current_camera->model_view_matrix = glm::rotate(Camera::current_camera->model_view_matrix, rotation.y, glm::vec3(0, 1, 0));
Camera::current_camera->model_view_matrix = glm::rotate(Camera::current_camera->model_view_matrix, rotation.z, glm::vec3(0, 0, 1));
Camera::current_camera->model_view_matrix = glm::scale(Camera::current_camera->model_view_matrix, scale);
if (material)
material->bind();
mesh->render();
for (uint32_t i = 0; i < children.size(); ++i) {
MeshInstance *c = children[i];
if (c)
c->render();
}
//glPopMatrix();
Camera::current_camera->model_view_matrix = mat_oring;
}
MeshInstance::MeshInstance() {
material = nullptr;
mesh = nullptr;
position = glm::vec3(0, 0, 0);
rotation = glm::vec3(0, 0, 0);
scale = glm::vec3(1, 1, 1);
}
MeshInstance::~MeshInstance() {
children.clear();
}

View File

@ -0,0 +1,28 @@
#ifndef MESH_INSTANCE_H
#define MESH_INSTANCE_H
#include <vector>
#include "opengl.h"
#include "material.h"
#include "mesh.h"
#include "./glm/vec3.hpp"
class MeshInstance {
public:
void render();
MeshInstance();
virtual ~MeshInstance();
Material *material;
Mesh *mesh;
glm::vec3 position;
glm::vec3 rotation;
glm::vec3 scale;
std::vector<MeshInstance *> children;
};
#endif

View File

@ -0,0 +1,73 @@
#include "mesh_utils.h"
void MeshUtils::create_cone(Mesh *mesh) {
if (!mesh)
return;
uint32_t vc = mesh->vertices.size();
//eleje
mesh->add_color(1, 0, 0);
mesh->add_vertex3(0, 0.5, 0);
mesh->add_color(1,0,0);
mesh->add_vertex3(-0.5, -0.5, 0.5);
mesh->add_color(1, 0, 0);
mesh->add_vertex3(0.5, -0.5, 0.5);
mesh->add_triangle(0 + vc, 1 + vc, 2 + vc);
//bal
mesh->add_color(0, 1, 0);
mesh->add_vertex3(0, 0.5, 0);
mesh->add_color(0, 1, 0);
mesh->add_vertex3(-0.5, -0.5, -0.5);
mesh->add_color(0, 1, 0);
mesh->add_vertex3(-0.5, -0.5, 0.5);
mesh->add_triangle(3 + vc, 4 + vc, 5 + vc);
//jobb
mesh->add_color(0, 0, 1);
mesh->add_vertex3(0, 0.5, 0);
mesh->add_color(0, 0, 1);
mesh->add_vertex3(0.5, -0.5, 0.5);
mesh->add_color(0, 0, 1);
mesh->add_vertex3(0.5, -0.5, -0.5);
mesh->add_triangle(6 + vc, 7 + vc, 8 + vc);
//hátulja
mesh->add_color(1, 1, 0);
mesh->add_vertex3(0, 0.5, 0);
mesh->add_color(1, 1, 0);
mesh->add_vertex3(0.5, -0.5, -0.5);
mesh->add_color(1, 1, 0);
mesh->add_vertex3(-0.5, -0.5, -0.5);
mesh->add_triangle(9 + vc, 10 + vc, 11 + vc);
//alja
mesh->add_color(1, 0, 1);
mesh->add_vertex3(-0.5, -0.5, -0.5);
mesh->add_color(1, 0, 1);
mesh->add_vertex3(0.5, -0.5, 0.5);
mesh->add_color(1, 0, 1);
mesh->add_vertex3(-0.5, -0.5, 0.5);
mesh->add_color(1, 0, 1);
mesh->add_vertex3(0.5, -0.5, -0.5);
mesh->add_triangle(12 + vc, 13 + vc, 14 + vc);
mesh->add_triangle(13 + vc, 12 + vc, 15 + vc);
}

View File

@ -0,0 +1,11 @@
#ifndef MESH_UTILS_H
#define MESH_UTILS_H
#include "mesh.h"
class MeshUtils {
public:
static void create_cone(Mesh *mesh);
};
#endif

View File

@ -0,0 +1,10 @@
#include "object_2d.h"
Object2D::Object2D() {
position = glm::vec2(0, 0);
rotation = 0;
scale = glm::vec2(1, 1);
}
Object2D::~Object2D() {
}

View File

@ -0,0 +1,17 @@
#ifndef OBJECT_2D_H
#define OBJECT_2D_H
#include "./glm/vec2.hpp"
class Object2D {
public:
Object2D();
virtual ~Object2D();
glm::vec2 position;
float rotation;
glm::vec2 scale;
};
#endif

View File

@ -0,0 +1,19 @@
#ifndef OPENGL_H
#define OPENGL_H
#if __unix__ && !__ANDROID__
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#endif
#if __ANDROID__
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#endif
#if _WIN64
#include <glad/glad.h>
#endif
#endif

View File

@ -0,0 +1,9 @@
#include "scene.h"
Scene::Scene() {
}
Scene::~Scene() {
}

View File

@ -0,0 +1,16 @@
#ifndef SCENE_H
#define SCENE_H
#include "sdl.inc.h"
class Scene {
public:
virtual void event(const SDL_Event &ev) = 0;
virtual void update(float delta) = 0;
virtual void render() = 0;
Scene();
virtual ~Scene();
};
#endif

View File

@ -0,0 +1,9 @@
#if __ANDROID__
#include <SDL.h>
#else
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#endif

View File

@ -0,0 +1,153 @@
#include "shader.h"
#include <stdio.h>
#include <vector>
Shader *Shader::current_shader = nullptr;
bool Shader::bind() {
if (current_shader != this) {
glUseProgram(program);
current_shader = this;
return true;
}
return false;
}
void Shader::unbind() {
if (current_shader == this) {
glUseProgram(0);
}
}
void Shader::compile() {
program = glCreateProgram();
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
const GLchar **vertex_shader_source = get_vertex_shader_source();
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);
GLint shader_compiled = GL_FALSE;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &shader_compiled);
if (shader_compiled != GL_TRUE) {
print_shader_errors(vertex_shader, "compiling Vertex Shader");
return;
}
glAttachShader(program, vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar **fragment_shader_source = get_fragment_shader_source();
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
glCompileShader(fragment_shader);
GLint fragment_shader_compiled = GL_FALSE;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &fragment_shader_compiled);
if (fragment_shader_compiled != GL_TRUE) {
print_shader_errors(fragment_shader, "compiling Fragment Shader");
return;
}
glAttachShader(program, fragment_shader);
glBindAttribLocation(program, ATTRIBUTE_POSITION, "a_position");
glBindAttribLocation(program, ATTRIBUTE_NORMAL, "a_normal");
glBindAttribLocation(program, ATTRIBUTE_COLOR, "a_color");
glBindAttribLocation(program, ATTRIBUTE_UV, "a_uv");
glLinkProgram(program);
GLint program_success = GL_TRUE;
glGetProgramiv(program, GL_LINK_STATUS, &program_success);
if (program_success != GL_TRUE) {
print_program_errors(program);
return;
}
}
void Shader::destroy() {
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDeleteProgram(program);
}
const GLchar **Shader::get_vertex_shader_source() {
return vertex_shader_source;
}
void Shader::set_vertex_shader_source(const GLchar **source) {
vertex_shader_source = source;
}
const GLchar **Shader::get_fragment_shader_source() {
return fragment_shader_source;
}
void Shader::set_fragment_shader_source(const GLchar **source) {
fragment_shader_source = source;
}
void Shader::print_shader_errors(const GLuint p_program, const char *name) {
int max_length = 5000;
std::vector<GLchar> error_log(max_length);
glGetShaderInfoLog(p_program, max_length, &max_length, &error_log[0]);
printf("Error %s!\n", name);
printf("%s\n", &error_log[0]);
}
void Shader::print_program_errors(const GLuint p_program) {
if (glIsProgram(p_program)) {
int info_length = 0;
int max_length = 5000;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_length);
char *info_log = new char[max_length];
glGetProgramInfoLog(p_program, max_length, &info_length, info_log);
if (info_length > 0) {
printf("%s\n", info_log);
}
delete[] info_log;
} else {
printf("print_program_errors: Not a program!");
}
}
Shader::Shader() {
}
Shader::~Shader() {
destroy();
}
//Meyers singleton
//Thread safe
ShaderCache *ShaderCache::get_singleton() {
static ShaderCache instance;
return &instance;
}
Shader *ShaderCache::get_shader(const int id) {
return shaders[id];
}
void ShaderCache::add_shader(const int id, Shader *shader) {
shaders[id] = shader;
}
ShaderCache::ShaderCache() {
}
ShaderCache::~ShaderCache() {
for (const std::pair<int, Shader*>& n : shaders) {
delete n.second;
}
shaders.clear();
}

View File

@ -0,0 +1,58 @@
#ifndef SHADER_H
#define SHADER_H
#include "opengl.h"
#include <unordered_map>
class Shader {
public:
enum VertexAttributes {
ATTRIBUTE_POSITION = 0,
ATTRIBUTE_NORMAL,
ATTRIBUTE_COLOR,
ATTRIBUTE_UV,
};
bool bind();
void unbind();
void compile();
void destroy();
const GLchar** get_vertex_shader_source();
void set_vertex_shader_source(const GLchar** source);
const GLchar** get_fragment_shader_source();
void set_fragment_shader_source(const GLchar** source);
void print_shader_errors(const GLuint p_program, const char* name);
void print_program_errors(const GLuint p_program);
Shader();
~Shader();
GLuint vertex_shader = 0;
GLuint fragment_shader = 0;
GLuint program = 0;
static Shader* current_shader;
protected:
const GLchar **vertex_shader_source;
const GLchar **fragment_shader_source;
};
class ShaderCache {
public:
static ShaderCache *get_singleton();
Shader *get_shader(const int id);
void add_shader(const int id, Shader * shader);
ShaderCache(); //lehetene nem publikus
~ShaderCache();
protected:
std::unordered_map<int, Shader*> shaders;
};
#endif

View File

@ -0,0 +1,59 @@
#include "sprite.h"
void Sprite::render() {
mesh_instance->position.x = position.x;
mesh_instance->position.y = position.y;
mesh_instance->rotation.z = rotation;
mesh_instance->scale.x = scale.x;
mesh_instance->scale.y = scale.y;
mesh_instance->render();
}
void Sprite::update_mesh() {
Mesh *mesh = mesh_instance->mesh;
mesh->clear();
float w2 = width / 2.0;
float h2 = height / 2.0;
mesh->add_uv(region_x, region_y);
mesh->add_vertex2(-w2, h2);
mesh->add_uv(region_x + region_width, region_y + region_height);
mesh->add_vertex2(w2, -h2);
mesh->add_uv(region_x, region_y + region_height);
mesh->add_vertex2(-w2, -h2);
mesh->add_uv(region_x + region_width, region_y);
mesh->add_vertex2(w2, h2);
mesh->add_triangle(1, 0, 2);
mesh->add_triangle(0, 1, 3);
mesh->upload();
}
Sprite::Sprite() : Object2D() {
mesh_instance = new MeshInstance();
mesh_instance->mesh = new Mesh(2);
width = 1;
height = 1;
region_x = 0;
region_y = 0;
region_width = 1;
region_height = 1;
}
Sprite::~Sprite() {
delete mesh_instance->mesh;
delete mesh_instance;
}

View File

@ -0,0 +1,27 @@
#ifndef SPRITE_H
#define SPRITE_H
#include "object_2d.h"
#include "mesh_instance.h"
class Sprite : public Object2D {
public:
void render();
void update_mesh();
Sprite();
~Sprite();
MeshInstance *mesh_instance;
float width;
float height;
float region_x;
float region_y;
float region_width;
float region_height;
};
#endif

View File

@ -0,0 +1,44 @@
#include "texture.h"
#include <stdio.h>
void Texture::load_image(const char* file_name, const int format, const int internal_components) {
if (image) {
SDL_FreeSurface(image);
glDeleteTextures(1, &texture);
}
image = SDL_LoadBMP(file_name);
if (!image) {
printf("Couldn't load %s.\n", file_name);
} else {
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, internal_components, image->w, image->h, 0, format, GL_UNSIGNED_BYTE, image->pixels);
apply_filer();
}
}
void Texture::apply_filer() {
GLint param = GL_NEAREST;
if (filter == TEXTURE_FILTER_LINEAR)
param = GL_LINEAR;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
Texture::Texture() {
filter = TEXTURE_FILTER_NEAREST;
texture = 0;
image = nullptr;
}
Texture::~Texture() {
if (image) {
SDL_FreeSurface(image);
glDeleteTextures(1, &texture);
}
}

View File

@ -0,0 +1,25 @@
#ifndef TEXTURE_H
#define TEXTURE_H
#include "opengl.h"
#include "sdl.inc.h"
class Texture {
public:
enum TextureFilter {
TEXTURE_FILTER_NEAREST = 0,
TEXTURE_FILTER_LINEAR,
};
void load_image(const char* file_name, const int format = GL_RGB, const int internal_components = GL_RGB);
void apply_filer();
TextureFilter filter;
GLuint texture;
SDL_Surface *image;
Texture();
virtual ~Texture();
};
#endif

View File

@ -0,0 +1,87 @@
#ifndef TEXTURE_MATERIAL_H
#define TEXTURE_MATERIAL_H
#include "material.h"
#include "glm/vec4.hpp"
#include "texture.h"
#include "camera.h"
#include "./glm/gtc/type_ptr.hpp"
class TextureMaterial : public Material {
public:
int get_material_id() {
return 3;
}
void bind_uniforms() {
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->projection_matrix));
glUniformMatrix4fv(model_view_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->model_view_matrix));
if (texture) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->texture);
glUniform1i(texture_location, 0);
}
}
void setup_uniforms() {
projection_matrix_location = get_uniform("u_proj_matrix");
model_view_matrix_location = get_uniform("u_model_view_matrix");
texture_location = get_uniform("u_texture");
}
void unbind() {
glDisable(GL_TEXTURE_2D);
}
void setup_state() {
glEnable(GL_TEXTURE_2D);
}
const GLchar** get_vertex_shader_source() {
static const GLchar *vertex_shader_source[] = {
"uniform mat4 u_proj_matrix;\n"
"uniform mat4 u_model_view_matrix;\n"
"\n"
"attribute vec4 a_position;\n"
"attribute vec2 a_uv;\n"
"\n"
"varying vec2 v_uv;\n"
"\n"
"void main() { \n"
" v_uv = a_uv;\n"
" gl_Position = u_proj_matrix * u_model_view_matrix * a_position; \n"
"}"
};
return vertex_shader_source;
}
const GLchar** get_fragment_shader_source() {
static const GLchar *fragment_shader_source[] = {
"precision mediump float;\n"
"uniform sampler2D u_texture;\n"
"varying vec2 v_uv;\n"
"\n"
"void main() { gl_FragColor = texture2D(u_texture, v_uv); }\n"
};
return fragment_shader_source;
}
TextureMaterial() {
texture = nullptr;
}
GLint projection_matrix_location;
GLint model_view_matrix_location;
GLint texture_location;
Texture *texture;
};
#endif

View File

@ -0,0 +1,138 @@
#include "tile_map.h"
#include "./glm/gtc/matrix_transform.hpp"
#include "./glm/matrix.hpp"
#include "./glm/vec3.hpp"
#include "camera.h"
void TileMap::build_mesh() {
if (!mesh) {
mesh = new Mesh(2);
} else {
mesh->clear();
}
if (!data) {
//mesh->upload();
return;
}
float asx = 1.0 / atlas_size_x;
float asy = 1.0 / atlas_size_y;
for (int x = 0; x < size_x; ++x) {
int x_offset = x * size_x;
for (int y = 0; y < size_y; ++y) {
uint8_t d = data[x_offset + y];
if (d == 0)
continue;
float px;
float py;
switch (d) {
case 1:
px = 1;
py = 0;
break;
case 2:
px = 0;
py = 1;
break;
}
px /= atlas_size_x;
py /= atlas_size_y;
add_rect(x, y, px, py, asx, asy);
}
}
mesh->upload();
}
void TileMap::allocate_data() {
if (size_x <= 0 || size_y <= 0)
return;
if (data) {
delete[] data;
}
int size = size_x * size_y;
data = new uint8_t[size];
for (int i = 0; i < size; ++i) {
data[i] = 0;
}
}
void TileMap::add_rect(const int x, const int y, const float uv_x, const float uv_y, const float uv_size_x, const float uv_size_y) {
int vc = static_cast<int>(mesh->vertices.size() / mesh->vertex_dimensions);
mesh->add_uv(uv_x, uv_y);
mesh->add_vertex2(x, y + 1);
mesh->add_uv(uv_x + uv_size_x, uv_y + uv_size_y);
mesh->add_vertex2(x + 1, y);
mesh->add_uv(uv_x, uv_y + uv_size_y);
mesh->add_vertex2(x, y);
mesh->add_uv(uv_x + uv_size_x, uv_y);
mesh->add_vertex2(x + 1, y + 1);
mesh->add_triangle(vc + 1, vc + 0, vc + 2);
mesh->add_triangle(vc + 0, vc + 1, vc + 3);
}
uint8_t TileMap::get_data(const int x, const int y) const {
//3d-ben: data[(x * size_x * size_x) + (y * size_y) + size_z] etc
return data[x * size_x + y];
}
void TileMap::set_data(const int x, const int y, const uint8_t value) {
data[x * size_x + y] = value;
}
void TileMap::render() {
if (!mesh)
return;
glm::mat4 mat_orig = Camera::current_camera->model_view_matrix;
Camera::current_camera->model_view_matrix = glm::translate(Camera::current_camera->model_view_matrix, glm::vec3(position.x, position.y, 0));
Camera::current_camera->model_view_matrix = glm::rotate(Camera::current_camera->model_view_matrix, rotation, glm::vec3(0, 0, 1));
Camera::current_camera->model_view_matrix = glm::scale(Camera::current_camera->model_view_matrix, glm::vec3(scale.x, scale.y, 0));
if (material)
material->bind();
mesh->render();
Camera::current_camera->model_view_matrix = mat_orig;
}
TileMap::TileMap() : Object2D() {
data = nullptr;
size_x = 16;
size_y = 16;
atlas_size_x = 1;
atlas_size_y = 1;
mesh = nullptr;
material = nullptr;
}
TileMap::~TileMap() {
if (data)
delete[] data;
}

View File

@ -0,0 +1,36 @@
#ifndef TILE_MAP_H
#define TILE_MAP_H
#include "object_2d.h"
#include "mesh.h"
#include "material.h"
class TileMap : public Object2D {
public:
void build_mesh();
void allocate_data();
void add_rect(const int x, const int y, const float uv_x, const float uv_y, const float uv_size_x, const float uv_size_y);
uint8_t get_data(const int x, const int y) const;
void set_data(const int x, const int y, const uint8_t value);
void render();
TileMap();
~TileMap();
uint8_t *data;
int size_x;
int size_y;
int atlas_size_x;
int atlas_size_y;
Mesh *mesh;
Material *material;
};
#endif

View File

@ -0,0 +1,94 @@
#ifndef TRANSPARENT_TEXTURE_MATERIAL_H
#define TRANSPARENT_TEXTURE_MATERIAL_H
#include "material.h"
#include "glm/vec4.hpp"
#include "texture.h"
#include "camera.h"
#include "./glm/gtc/type_ptr.hpp"
class TransparentTextureMaterial : public Material {
public:
int get_material_id() {
return 4;
}
void bind_uniforms() {
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->projection_matrix));
glUniformMatrix4fv(model_view_matrix_location, 1, GL_FALSE, glm::value_ptr(Camera::current_camera->model_view_matrix));
if (texture) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->texture);
glUniform1i(texture_location, 0);
}
}
void setup_uniforms() {
projection_matrix_location = get_uniform("u_proj_matrix");
model_view_matrix_location = get_uniform("u_model_view_matrix");
texture_location = get_uniform("u_texture");
}
void unbind() {
glDisable(GL_TEXTURE_2D);
}
void setup_state() {
glEnable(GL_TEXTURE_2D);
}
const GLchar** get_vertex_shader_source() {
static const GLchar *vertex_shader_source[] = {
"uniform mat4 u_proj_matrix;\n"
"uniform mat4 u_model_view_matrix;\n"
"\n"
"attribute vec4 a_position;\n"
"attribute vec2 a_uv;\n"
"\n"
"varying vec2 v_uv;\n"
"\n"
"void main() { \n"
" v_uv = a_uv;\n"
" gl_Position = u_proj_matrix * u_model_view_matrix * a_position; \n"
"}"
};
return vertex_shader_source;
}
const GLchar** get_fragment_shader_source() {
static const GLchar *fragment_shader_source[] = {
"precision mediump float;\n"
"uniform sampler2D u_texture;\n"
"varying vec2 v_uv;\n"
"\n"
"void main() {\n"
" vec4 col = texture2D(u_texture, v_uv);\n"
"\n"
" if (col.a < 0.1)\n"
" discard;\n"
"\n"
" gl_FragColor = col;\n"
"}\n"
};
return fragment_shader_source;
}
TransparentTextureMaterial() {
texture = nullptr;
}
GLint projection_matrix_location;
GLint model_view_matrix_location;
GLint texture_location;
Texture *texture;
};
#endif