diff --git a/core/renderer/opengl/application.cpp b/core/renderer/opengl/application.cpp new file mode 100644 index 0000000..e084aad --- /dev/null +++ b/core/renderer/opengl/application.cpp @@ -0,0 +1,117 @@ +#include "application.h" + +#include + +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(¤t_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 elapsed_seconds = end - start; + + double t = elapsed_seconds.count(); + double tfps = 1.0 / static_cast(target_fps); + double remaining = tfps - t; + + if (remaining > 0) { + Uint32 fms = static_cast(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(); +} diff --git a/core/renderer/opengl/application.h b/core/renderer/opengl/application.h new file mode 100644 index 0000000..795403d --- /dev/null +++ b/core/renderer/opengl/application.h @@ -0,0 +1,38 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include "sdl.inc.h" +#include "opengl.h" + +#include + +#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 diff --git a/core/renderer/opengl/camera.cpp b/core/renderer/opengl/camera.cpp new file mode 100644 index 0000000..43fe119 --- /dev/null +++ b/core/renderer/opengl/camera.cpp @@ -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(-(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(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() { +} \ No newline at end of file diff --git a/core/renderer/opengl/camera.h b/core/renderer/opengl/camera.h new file mode 100644 index 0000000..b4b935a --- /dev/null +++ b/core/renderer/opengl/camera.h @@ -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 diff --git a/core/renderer/opengl/color_material.h b/core/renderer/opengl/color_material.h new file mode 100644 index 0000000..1ee7888 --- /dev/null +++ b/core/renderer/opengl/color_material.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/colored_material.h b/core/renderer/opengl/colored_material.h new file mode 100644 index 0000000..e8a2830 --- /dev/null +++ b/core/renderer/opengl/colored_material.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/game_application.h b/core/renderer/opengl/game_application.h new file mode 100644 index 0000000..d761038 --- /dev/null +++ b/core/renderer/opengl/game_application.h @@ -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 diff --git a/core/renderer/opengl/game_scene.cpp b/core/renderer/opengl/game_scene.cpp new file mode 100644 index 0000000..03c429c --- /dev/null +++ b/core/renderer/opengl/game_scene.cpp @@ -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(width) / static_cast(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(w) / static_cast(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; +} diff --git a/core/renderer/opengl/game_scene.h b/core/renderer/opengl/game_scene.h new file mode 100644 index 0000000..556d4bb --- /dev/null +++ b/core/renderer/opengl/game_scene.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/main.cpp b/core/renderer/opengl/main.cpp new file mode 100644 index 0000000..6eec4c7 --- /dev/null +++ b/core/renderer/opengl/main.cpp @@ -0,0 +1,31 @@ +#ifdef __EMSCRIPTEN__ +#include +#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; +} \ No newline at end of file diff --git a/core/renderer/opengl/main_orig.cpp b/core/renderer/opengl/main_orig.cpp new file mode 100644 index 0000000..7aa173e --- /dev/null +++ b/core/renderer/opengl/main_orig.cpp @@ -0,0 +1,1218 @@ +#include +#include + +#define SDL_MAIN_HANDLED + +#include + +#include "opengl.h" + +#ifdef __EMSCRIPTEN__ +#include +#endif + +SDL_Window *window; +SDL_GLContext context; + +bool running = true; + +bool shader_init = false; + +GLuint vertex_shader; +GLuint fragment_shader; +GLuint shader_program; + + +#include "shader.h" +Shader *s; + +void first_2d_triangle() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { gl_Position = gl_Vertex; }" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = vec4(1, 1, 0, 1); }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + glUseProgram(shader_program); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //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); +} + +GLint tri_color_uniform_location; +float color_count = 0; +void first_2d_triangle_uniforms() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { gl_Position = gl_Vertex; }" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform vec4 fragment_color = vec4(1, 1, 1, 1);" + "" + "void main() { gl_FragColor = fragment_color; }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + //ha -1 akkor nem sikerült + tri_color_uniform_location = glGetUniformLocation(shader_program, "fragment_color"); + } + + color_count += 0.01; + + if (color_count > 1) + color_count = 0; + + glUseProgram(shader_program); + glUniform4f(tri_color_uniform_location, color_count, 1, 1, 1 ); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //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); +} + +GLint tri_position_uniform_location; +void first_2d_triangle_uniforms_moving() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "#version 120\n" + "uniform float positions_offset = 0;" + "void main() { " + " vec4 p = gl_Vertex;" + " p.x += sin(positions_offset) * 0.5 * p.x;" + " p.y += cos(positions_offset) * 0.5 * p.y;" + " gl_Position = p;" + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = vec4(1, 1, 1, 1); }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + //ha -1 akkor nem sikerült + tri_position_uniform_location = glGetUniformLocation(shader_program, "positions_offset"); + } + + color_count += 0.01; + + glUseProgram(shader_program); + glUniform1f(tri_position_uniform_location, color_count); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //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); +} + + +void first_2d_triangle_shader_errors() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "#version 120\n" + "uniform float positions_offset = 0;\n" + "void main() { \n" + " gl_Position = gl_Verte;\n" + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + int max_length = 5000; + std::vector error_log(max_length); + glGetShaderInfoLog(vertex_shader, max_length, &max_length, &error_log[0]); + printf("%s\n", &error_log[0]); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = vec4(1, 0, 0, 1); }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + //ha -1 akkor nem sikerült + tri_position_uniform_location = glGetUniformLocation(shader_program, "positions_offset"); + } + + color_count += 0.01; + + glUseProgram(shader_program); + glUniform1f(tri_position_uniform_location, color_count); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //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); +} + +void print_shader_error(GLuint shader) { + int max_length = 5000; + std::vector error_log(max_length); + glGetShaderInfoLog(shader, max_length, &max_length, &error_log[0]); + printf("%s\n", &error_log[0]); +} + +void first_2d_triangle_error_checks() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { gl_Position = gl_Verte; }" + }; + + 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) { + printf("Unable to compile vertex shader!\n"); + print_shader_error(vertex_shader); + return; + } + + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = vec4(1, 1, 0, 1); }" + }; + + 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) { + printf("Unable to compile vertex shader!\n"); + print_shader_error(fragment_shader); + return; + } + + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + GLint program_success = GL_TRUE; + glGetProgramiv(shader_program, GL_LINK_STATUS, &program_success); + if (program_success != GL_TRUE) { + printf("Unable to link prigram!\n"); + print_shader_error(shader_program); + return; + } + } + + glUseProgram(shader_program); + + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + printf("glUseProgram error!\n"); + return; + } + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //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); +} + +void first_2d_triangle_colors() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { " + " gl_FrontColor = gl_Color;" + " gl_Position = gl_Vertex; " + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = gl_Color; }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + glUseProgram(shader_program); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //immediate mode + glBegin(GL_TRIANGLES); + glColor3f(1, 0, 0); + glVertex2f(0.0, 0.5); + + glColor3f(0, 1, 0); + glVertex2f(0.5, -0.5); + + glColor3f(0, 0, 1); + glVertex2f(-0.5, -0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + +float c3dc_rot = 0; +void first_3d_cone_perspective() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { " + " gl_FrontColor = gl_Color;" + //" gl_Position = gl_Vertex; " + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; " + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { gl_FragColor = gl_Color; }" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + glUseProgram(shader_program); + + + c3dc_rot += 1; + + //Ebben a példában a +z jön a kamera fele (alapbeállítás) + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + //glFrustum(-1, 1, -1, 1, 1, 10); + + glFrustum(-1, 1, -0.75, 0.75, 1, 10); + + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glTranslatef(0, 0, -2); + glRotatef(c3dc_rot, 0, 1, 0); + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + + glBegin(GL_TRIANGLES); + + //eleje + glColor3f(1, 0, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(1,0,0); + glVertex3f(-0.5, -0.5, 0.5); + + glColor3f(1, 0, 0); + glVertex3f(0.5, -0.5, 0.5); + + //bal + glColor3f(0, 1, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(0, 1, 0); + glVertex3f(-0.5, -0.5, -0.5); + + glColor3f(0, 1, 0); + glVertex3f(-0.5, -0.5, 0.5); + + //jobb + glColor3f(0, 0, 1); + glVertex3f(0, 0.5, 0); + + glColor3f(0, 0, 1); + glVertex3f(0.5, -0.5, 0.5); + + glColor3f(0, 0, 1); + glVertex3f(0.5, -0.5, -0.5); + + //hátulja + glColor3f(1, 1, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(1, 1, 0); + glVertex3f(0.5, -0.5, -0.5); + + glColor3f(1, 1, 0); + glVertex3f(-0.5, -0.5, -0.5); + + glEnd(); + + SDL_GL_SwapWindow(window); +} + +bool texture_loaded = false; +GLuint texture; +void loadGLTextures(const char *file_name) { + if (texture_loaded) + return; + + texture_loaded = true; + + SDL_Surface *texture_image; + texture_image = SDL_LoadBMP(file_name); + + if (!texture_image) { + printf("Couldn't load %s.\n", file_name); + } else { + + glGenTextures(1, &texture); + + glBindTexture(GL_TEXTURE_2D, texture); + + glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_image->w, texture_image->h, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image->pixels); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + //(bi)linear filtering + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + SDL_FreeSurface(texture_image); + } +} + +void first_2d_triangle_uv() { + loadGLTextures("img_forest.bmp"); + + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { " + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; " + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform sampler2D image;" + "void main() {" + " gl_FragColor = texture(image, gl_MultiTexCoord0); " + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + glUseProgram(shader_program); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + //glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + //glUniform1i(glGetUniformLocation(fragment_shader, "image"), 0); + + //immediate mode + glBegin(GL_TRIANGLES); + glTexCoord2f(0.5, 0); + glVertex2f(0.0, 0.5); + + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glTexCoord2f(0, 1); + glVertex2f(-0.5, -0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + +void first_2d_triangle_uv_varying() { + loadGLTextures("img_forest.bmp"); + + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "varying vec4 v_uv;" + "void main() { " + " v_uv = gl_MultiTexCoord0;" + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; " + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform sampler2D image;" + "varying vec4 v_uv;" + "void main() {" + " gl_FragColor = texture(image, v_uv); " + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + glUseProgram(shader_program); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + //glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + //glUniform1i(glGetUniformLocation(fragment_shader, "image"), 0); + + //immediate mode + glBegin(GL_TRIANGLES); + glTexCoord2f(0.5, 0); + glVertex2f(0.0, 0.5); + + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glTexCoord2f(0, 1); + glVertex2f(-0.5, -0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + +GLint uniform_water_uv_offset; +float uv_offset = 0; +void first_2d_triangle_uv_varying_water() { + loadGLTextures("img_forest.bmp"); + + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "#version 120\n" + "uniform float position_offset = 0;\n" + "varying vec4 v_uv;\n" + "void main() { \n" + " vec4 uvcoords = gl_MultiTexCoord0;\n" + " uvcoords.y -= position_offset;\n" + " v_uv = uvcoords;\n" + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + + print_shader_error(vertex_shader); + + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform sampler2D image;" + "varying vec4 v_uv;" + "void main() {" + " gl_FragColor = texture(image, v_uv); " + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + uniform_water_uv_offset = glGetUniformLocation(shader_program, "position_offset"); + } + + uv_offset += 0.01; + + if (uv_offset > 1) + uv_offset = 0; + + glUseProgram(shader_program); + glUniform1f(uniform_water_uv_offset, uv_offset); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + //glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + //glUniform1i(glGetUniformLocation(fragment_shader, "image"), 0); + + //immediate mode + glBegin(GL_TRIANGLES); + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glTexCoord2f(0, 1); + glVertex2f(-0.5, -0.5); + + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glTexCoord2f(1, 0); + glVertex2f(0.5, 0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + +GLint uniform_grass_offset; +float grass_displace = 0.5; +float grass_displace_val = 0.03; +void grass() { + loadGLTextures("grass.bmp"); + + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + //cv.rgba + //cv.ra + //cv.rga + //cv.yz + //... + //vec3 * cv.rgb + //stpq + + const GLchar *vertex_shader_source[] = { + "#version 120\n" + "uniform float position_offset = 0;\n" + "varying vec4 v_uv;\n" + "void main() { \n" + " vec4 cv = gl_Color;" + " cv.xyz *= position_offset;" + " vec4 v = cv + gl_Vertex;" + " v_uv = gl_MultiTexCoord0;" + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * v;\n" + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + + print_shader_error(vertex_shader); + + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform sampler2D image;" + "varying vec4 v_uv;" + "void main() {" + " gl_FragColor = texture(image, v_uv); " + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + uniform_grass_offset = glGetUniformLocation(shader_program, "position_offset"); + } + + grass_displace += grass_displace_val; + + if (grass_displace > 0.5) + grass_displace_val = -grass_displace_val; + + if (grass_displace < -0.5) + grass_displace_val = -grass_displace_val; + + glUseProgram(shader_program); + glUniform1f(uniform_grass_offset, grass_displace); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + //glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + //glUniform1i(glGetUniformLocation(fragment_shader, "image"), 0); + + //immediate mode + glBegin(GL_TRIANGLES); + glColor3f(0.3, 0.01, 0); + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(0, 1); + glVertex2f(-0.5, -0.5); + + glColor3f(0.3, 0.01, 0); + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glColor3f(0.3, 0.01, 0); + glTexCoord2f(1, 0); + glVertex2f(0.5, 0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + + +void grass_transparent() { + loadGLTextures("grass.bmp"); + + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + //cv.rgba + //cv.ra + //cv.rga + //cv.yz + //... + //vec3 * cv.rgb + //stpq + + const GLchar *vertex_shader_source[] = { + "#version 120\n" + "uniform float position_offset = 0;\n" + "varying vec4 v_uv;\n" + "void main() { \n" + " vec4 cv = gl_Color;" + " cv.xyz *= position_offset;" + " vec4 v = cv + gl_Vertex;" + " v_uv = gl_MultiTexCoord0;" + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * v;\n" + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + + print_shader_error(vertex_shader); + + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "uniform sampler2D image;" + "varying vec4 v_uv;" + "void main() {" + " vec4 color = texture(image, v_uv); " + " if (color.r >= 0.5 && color.g >= 0.5 && color.b >= 0.5) {" + " discard; " + " } else {" + " gl_FragColor = color; " + " }" + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + + uniform_grass_offset = glGetUniformLocation(shader_program, "position_offset"); + } + + grass_displace += grass_displace_val; + + if (grass_displace > 0.5) + grass_displace_val = -grass_displace_val; + + if (grass_displace < -0.5) + grass_displace_val = -grass_displace_val; + + glUseProgram(shader_program); + glUniform1f(uniform_grass_offset, grass_displace); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + + //glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture); + //glUniform1i(glGetUniformLocation(fragment_shader, "image"), 0); + + //immediate mode + glBegin(GL_TRIANGLES); + glColor3f(0.3, 0.01, 0); + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(0, 1); + glVertex2f(-0.5, -0.5); + + glColor3f(0.3, 0.01, 0); + glTexCoord2f(0, 0); + glVertex2f(-0.5, 0.5); + + glColor3f(0, 0, 0); + glTexCoord2f(1, 1); + glVertex2f(0.5, -0.5); + + glColor3f(0.3, 0.01, 0); + glTexCoord2f(1, 0); + glVertex2f(0.5, 0.5); + glEnd(); + + SDL_GL_SwapWindow(window); +} + +void first_3d_cone_perspective_transparent() { + if (!shader_init) { + shader_init = true; + + shader_program = glCreateProgram(); + + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + + const GLchar *vertex_shader_source[] = { + "void main() { " + " gl_FrontColor = gl_Color;" + //" gl_Position = gl_Vertex; " + " gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; " + "}" + }; + + glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); + glCompileShader(vertex_shader); + glAttachShader(shader_program, vertex_shader); + + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + const GLchar *fragment_shader_source[] = { + "void main() { " + " vec4 col = gl_Color;" + " col.a = 0.5;" + " gl_FragColor = col; " + "}" + }; + + glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); + glCompileShader(fragment_shader); + glAttachShader(shader_program, fragment_shader); + + glLinkProgram(shader_program); + } + + + c3dc_rot += 1; + + //Ebben a példában a +z jön a kamera fele (alapbeállítás) + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + //glFrustum(-1, 1, -1, 1, 1, 10); + + glFrustum(-1, 1, -0.75, 0.75, 1, 10); + + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glTranslatef(0, 0, -2); + + glUseProgram(0); + + glBegin(GL_TRIANGLES); + + glColor3f(0.8, 0.8, 0.8); + glVertex3f(0, 1, -1); + + glColor3f(0.8, 0.8, 0.8); + glVertex3f(-1, -1, -1); + + glColor3f(0.8, 0.8, 0.8); + glVertex3f(1, -1, -1); + + glEnd(); + + + glRotatef(c3dc_rot, 0, 1, 0); + + glUseProgram(shader_program); + + glDisable(GL_CULL_FACE); + glDepthMask(false); + + glBegin(GL_TRIANGLES); + + //eleje + glColor3f(1, 0, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(1,0,0); + glVertex3f(-0.5, -0.5, 0.5); + + glColor3f(1, 0, 0); + glVertex3f(0.5, -0.5, 0.5); + + //bal + glColor3f(0, 1, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(0, 1, 0); + glVertex3f(-0.5, -0.5, -0.5); + + glColor3f(0, 1, 0); + glVertex3f(-0.5, -0.5, 0.5); + + //jobb + glColor3f(0, 0, 1); + glVertex3f(0, 0.5, 0); + + glColor3f(0, 0, 1); + glVertex3f(0.5, -0.5, 0.5); + + glColor3f(0, 0, 1); + glVertex3f(0.5, -0.5, -0.5); + + //hátulja + glColor3f(1, 1, 0); + glVertex3f(0, 0.5, 0); + + glColor3f(1, 1, 0); + glVertex3f(0.5, -0.5, -0.5); + + glColor3f(1, 1, 0); + glVertex3f(-0.5, -0.5, -0.5); + + glEnd(); + + glDepthMask(true); + + SDL_GL_SwapWindow(window); +} + + +int current_demo = 12; + +//gameloop +void handle_frame() { + //handle input + SDL_Event current_evevnt; + + while(SDL_PollEvent(¤t_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_moving(); + break; + case 3: + first_2d_triangle_shader_errors(); + break; + case 4: + first_2d_triangle_error_checks(); + break; + case 5: + first_2d_triangle_colors(); + break; + case 6: + first_3d_cone_perspective(); + break; + case 7: + first_2d_triangle_uv(); + break; + case 8: + first_2d_triangle_uv_varying(); + break; + case 9: + first_2d_triangle_uv_varying_water(); + break; + case 10: + grass(); + break; + case 11: + grass_transparent(); + break; + case 12: + first_3d_cone_perspective_transparent(); + 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; + } + + //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); + + 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 (shader_init) { + printf("memleak\n"); + } + + SDL_DestroyWindow(window); + + window = nullptr; + + SDL_Quit(); + + return 0; +} \ No newline at end of file diff --git a/core/renderer/opengl/main_orig_2.cpp b/core/renderer/opengl/main_orig_2.cpp new file mode 100644 index 0000000..5470cc9 --- /dev/null +++ b/core/renderer/opengl/main_orig_2.cpp @@ -0,0 +1,422 @@ +#include +#include + +#define SDL_MAIN_HANDLED + +#include "sdl.inc.h" + +#include "opengl.h" + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include + +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(¤t_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; +} \ No newline at end of file diff --git a/core/renderer/opengl/material.cpp b/core/renderer/opengl/material.cpp new file mode 100644 index 0000000..9f86f72 --- /dev/null +++ b/core/renderer/opengl/material.cpp @@ -0,0 +1,62 @@ +#include "material.h" + +#include + +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() { +} diff --git a/core/renderer/opengl/material.h b/core/renderer/opengl/material.h new file mode 100644 index 0000000..679d32f --- /dev/null +++ b/core/renderer/opengl/material.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/mesh.cpp b/core/renderer/opengl/mesh.cpp new file mode 100644 index 0000000..7f2982f --- /dev/null +++ b/core/renderer/opengl/mesh.cpp @@ -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(); +} \ No newline at end of file diff --git a/core/renderer/opengl/mesh.h b/core/renderer/opengl/mesh.h new file mode 100644 index 0000000..979d7c9 --- /dev/null +++ b/core/renderer/opengl/mesh.h @@ -0,0 +1,50 @@ +#ifndef MESH_H +#define MESH_H + +#include +#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 vertices; + vector normals; + vector colors; + vector uvs; + vector 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 \ No newline at end of file diff --git a/core/renderer/opengl/mesh_instance.cpp b/core/renderer/opengl/mesh_instance.cpp new file mode 100644 index 0000000..327f656 --- /dev/null +++ b/core/renderer/opengl/mesh_instance.cpp @@ -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(); +} \ No newline at end of file diff --git a/core/renderer/opengl/mesh_instance.h b/core/renderer/opengl/mesh_instance.h new file mode 100644 index 0000000..72cd044 --- /dev/null +++ b/core/renderer/opengl/mesh_instance.h @@ -0,0 +1,28 @@ +#ifndef MESH_INSTANCE_H +#define MESH_INSTANCE_H + +#include +#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 children; +}; + +#endif diff --git a/core/renderer/opengl/mesh_utils.cpp b/core/renderer/opengl/mesh_utils.cpp new file mode 100644 index 0000000..2533df7 --- /dev/null +++ b/core/renderer/opengl/mesh_utils.cpp @@ -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); +} \ No newline at end of file diff --git a/core/renderer/opengl/mesh_utils.h b/core/renderer/opengl/mesh_utils.h new file mode 100644 index 0000000..5516e72 --- /dev/null +++ b/core/renderer/opengl/mesh_utils.h @@ -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 diff --git a/core/renderer/opengl/object_2d.cpp b/core/renderer/opengl/object_2d.cpp new file mode 100644 index 0000000..fd8f99a --- /dev/null +++ b/core/renderer/opengl/object_2d.cpp @@ -0,0 +1,10 @@ +#include "object_2d.h" + +Object2D::Object2D() { + position = glm::vec2(0, 0); + rotation = 0; + scale = glm::vec2(1, 1); +} + +Object2D::~Object2D() { +} diff --git a/core/renderer/opengl/object_2d.h b/core/renderer/opengl/object_2d.h new file mode 100644 index 0000000..e11e04f --- /dev/null +++ b/core/renderer/opengl/object_2d.h @@ -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 diff --git a/core/renderer/opengl/opengl.h b/core/renderer/opengl/opengl.h new file mode 100644 index 0000000..36659d7 --- /dev/null +++ b/core/renderer/opengl/opengl.h @@ -0,0 +1,19 @@ +#ifndef OPENGL_H +#define OPENGL_H + +#if __unix__ && !__ANDROID__ +#define GL_GLEXT_PROTOTYPES +#include +#endif + +#if __ANDROID__ +#define GL_GLEXT_PROTOTYPES +#include +#endif + +#if _WIN64 +#include +#endif + + +#endif diff --git a/core/renderer/opengl/scene.cpp b/core/renderer/opengl/scene.cpp new file mode 100644 index 0000000..0e5026f --- /dev/null +++ b/core/renderer/opengl/scene.cpp @@ -0,0 +1,9 @@ +#include "scene.h" + +Scene::Scene() { + +} + +Scene::~Scene() { + +} \ No newline at end of file diff --git a/core/renderer/opengl/scene.h b/core/renderer/opengl/scene.h new file mode 100644 index 0000000..9263378 --- /dev/null +++ b/core/renderer/opengl/scene.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/sdl.inc.h b/core/renderer/opengl/sdl.inc.h new file mode 100644 index 0000000..d073928 --- /dev/null +++ b/core/renderer/opengl/sdl.inc.h @@ -0,0 +1,9 @@ + +#if __ANDROID__ +#include +#else +#define SDL_MAIN_HANDLED +#include +#endif + + diff --git a/core/renderer/opengl/shader.cpp b/core/renderer/opengl/shader.cpp new file mode 100644 index 0000000..a8b85e2 --- /dev/null +++ b/core/renderer/opengl/shader.cpp @@ -0,0 +1,153 @@ +#include "shader.h" + +#include +#include + +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 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& n : shaders) { + delete n.second; + } + + shaders.clear(); +} diff --git a/core/renderer/opengl/shader.h b/core/renderer/opengl/shader.h new file mode 100644 index 0000000..493da15 --- /dev/null +++ b/core/renderer/opengl/shader.h @@ -0,0 +1,58 @@ +#ifndef SHADER_H +#define SHADER_H + +#include "opengl.h" +#include + +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 shaders; +}; + +#endif \ No newline at end of file diff --git a/core/renderer/opengl/sprite.cpp b/core/renderer/opengl/sprite.cpp new file mode 100644 index 0000000..7832d74 --- /dev/null +++ b/core/renderer/opengl/sprite.cpp @@ -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; +} + + diff --git a/core/renderer/opengl/sprite.h b/core/renderer/opengl/sprite.h new file mode 100644 index 0000000..d05842d --- /dev/null +++ b/core/renderer/opengl/sprite.h @@ -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 + diff --git a/core/renderer/opengl/texture.cpp b/core/renderer/opengl/texture.cpp new file mode 100644 index 0000000..04b1181 --- /dev/null +++ b/core/renderer/opengl/texture.cpp @@ -0,0 +1,44 @@ +#include "texture.h" + +#include + +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); + } +} \ No newline at end of file diff --git a/core/renderer/opengl/texture.h b/core/renderer/opengl/texture.h new file mode 100644 index 0000000..10c9d03 --- /dev/null +++ b/core/renderer/opengl/texture.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/texture_material.h b/core/renderer/opengl/texture_material.h new file mode 100644 index 0000000..01b48cb --- /dev/null +++ b/core/renderer/opengl/texture_material.h @@ -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 \ No newline at end of file diff --git a/core/renderer/opengl/tile_map.cpp b/core/renderer/opengl/tile_map.cpp new file mode 100644 index 0000000..f02d147 --- /dev/null +++ b/core/renderer/opengl/tile_map.cpp @@ -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(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; +} diff --git a/core/renderer/opengl/tile_map.h b/core/renderer/opengl/tile_map.h new file mode 100644 index 0000000..cb67ce9 --- /dev/null +++ b/core/renderer/opengl/tile_map.h @@ -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 diff --git a/core/renderer/opengl/transparent_texture_material.h b/core/renderer/opengl/transparent_texture_material.h new file mode 100644 index 0000000..c9db9af --- /dev/null +++ b/core/renderer/opengl/transparent_texture_material.h @@ -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 \ No newline at end of file