Compare commits
10 Commits
ce0f93a572
...
7a218edcce
Author | SHA1 | Date | |
---|---|---|---|
7a218edcce | |||
351286d16a | |||
6fdbcc8825 | |||
ced87e0af1 | |||
|
cad444e05d | ||
|
8a99476507 | ||
|
ae2c68bb24 | ||
|
727d3535ba | ||
|
8455ffac2e | ||
|
67aa648299 |
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ build/
|
||||||
*.o
|
*.o
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
.idea/
|
.idea/
|
||||||
|
bin/
|
||||||
|
|
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "06-monogame/Introduction/themes/hugo-bearcub"]
|
||||||
|
path = 06-monogame/Introduction/themes/hugo-bearcub
|
||||||
|
url = https://github.com/clente/hugo-bearcub
|
BIN
.imgs/monogame.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
.imgs/opengl.png
Normal file
After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 105 KiB |
|
@ -1,6 +1,6 @@
|
||||||
<!-- <p align="center"> -->
|
<p align="center">
|
||||||
<!-- <img src=".imgs/showcase.png" width="300" /> -->
|
<img src=".imgs/showcase.png" width="300" />
|
||||||
<!-- </p> -->
|
</p>
|
||||||
|
|
||||||
# Map
|
# Map
|
||||||
|
|
||||||
|
|
29
05-opengl/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
CC=g++
|
||||||
|
CFLAGS=-std=c++20 `pkg-config --cflags glfw3 glew glm`
|
||||||
|
LDFLAGS=`pkg-config --libs glfw3 glew glm`
|
||||||
|
INCLUDE=/usr/include/stb/
|
||||||
|
TARGET=opengl
|
||||||
|
SDIR=src
|
||||||
|
ADIR=assets
|
||||||
|
ODIR=build
|
||||||
|
|
||||||
|
SRC=$(shell find $(SDIR) -type f -name *.cpp)
|
||||||
|
OBJ=$(SRC:.cpp=.o)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
$(TARGET): $(OBJ)
|
||||||
|
mkdir -p build
|
||||||
|
cp -rf $(ADIR) $(ODIR)/$(ADIR)
|
||||||
|
$(CC) -o $(ODIR)/$@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(ODIR)/$(TARGET)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(ODIR)/$(TARGET) $(OBJ)
|
3
05-opengl/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Opengl
|
||||||
|
|
||||||
|
Playing with Opengl because I realized SDL2 is not enough :/
|
BIN
05-opengl/assets/player/idle.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
05-opengl/assets/player/run.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
13
05-opengl/assets/shaders/fragment.glsl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#version 330 core
|
||||||
|
out vec4 color;
|
||||||
|
in vec2 tex_coord;
|
||||||
|
|
||||||
|
uniform sampler2D sampler;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = texture(sampler, tex_coord);
|
||||||
|
// color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (color.a < 0.1)
|
||||||
|
discard;
|
||||||
|
}
|
14
05-opengl/assets/shaders/vertex.glsl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
layout (location = 1) in vec2 texture_coord;
|
||||||
|
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
out vec2 tex_coord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = projection * view * vec4(pos.xyz, 1.0);
|
||||||
|
tex_coord = texture_coord;
|
||||||
|
}
|
22
05-opengl/src/common.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
std::string read_file(const char *path) {
|
||||||
|
std::string content;
|
||||||
|
std::ifstream fs(path, std::ios::in);
|
||||||
|
|
||||||
|
if(!fs.is_open()) {
|
||||||
|
std::cerr << "Error: Could not read file " << path << ". File does not exist." << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line = "";
|
||||||
|
while(!fs.eof()) {
|
||||||
|
std::getline(fs, line);
|
||||||
|
content.append(line + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.close();
|
||||||
|
return content;
|
||||||
|
}
|
5
05-opengl/src/common.hpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string read_file(const char *path);
|
172
05-opengl/src/game.cpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include "game.hpp"
|
||||||
|
#include "texture.hpp"
|
||||||
|
#include "sprite.hpp"
|
||||||
|
#include "other/stb_image.h"
|
||||||
|
|
||||||
|
Game::Game(GLFWwindow *window) {
|
||||||
|
this->window = window;
|
||||||
|
this->program = Program();
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(true);
|
||||||
|
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &this->texture_slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
// code this later lol
|
||||||
|
int Game::setup(int initial_width, int initial_height) {
|
||||||
|
glfwSetKeyCallback(this->window, Game::input_callback);
|
||||||
|
glfwSetFramebufferSizeCallback(this->window, Game::resize_callback);
|
||||||
|
|
||||||
|
Game::resize_callback(this->window, initial_width, initial_height);
|
||||||
|
|
||||||
|
int ret = this->program.add_shader("assets/shaders/vertex.glsl", GL_VERTEX_SHADER);
|
||||||
|
if (ret != 0) {
|
||||||
|
std::cout << "Error: failed adding vertex shader" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = this->program.add_shader("assets/shaders/fragment.glsl", GL_FRAGMENT_SHADER);
|
||||||
|
if (ret != 0) {
|
||||||
|
std::cout << "Error: failed adding fragment shader" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->program.link() != 0) {
|
||||||
|
std::cout << "Error: failed linking program" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(this->program.id);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &this->vao);
|
||||||
|
glGenBuffers(1, &this->vbo);
|
||||||
|
glGenBuffers(1, &this->ebo);
|
||||||
|
|
||||||
|
glBindVertexArray(this->vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ebo);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::run() {
|
||||||
|
this->counter = 0;
|
||||||
|
this->vbo_offset = 0;
|
||||||
|
this->ebo_offset = 0;
|
||||||
|
|
||||||
|
Sprite sprite("assets/player/idle.png", SPLIT_TEXTURE);
|
||||||
|
sprite.bake();
|
||||||
|
this->sprites.push_back(&sprite);
|
||||||
|
|
||||||
|
glBindVertexArray(this->vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ebo);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(struct vertex) * 4 * this->texture_slots, nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 6 * this->texture_slots, nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void *) offsetof(vertex, position));
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void *) offsetof(vertex, texture));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
Game::logic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::input_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
|
||||||
|
if (action != GLFW_PRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case GLFW_KEY_ESCAPE:
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::resize_callback(GLFWwindow *window, int new_width, int new_height) {
|
||||||
|
glViewport(0, 0, new_width, new_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::logic() {
|
||||||
|
while (!glfwWindowShouldClose(this->window)) {
|
||||||
|
glClearColor(0, 0, 0, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
|
||||||
|
for (int sprite = 0; sprite < this->sprites.size(); sprite++, counter++) {
|
||||||
|
Game::load(this->sprites[sprite], this->counter);
|
||||||
|
|
||||||
|
std::cout << "Counter: " << counter << " Texture slots: " << this->texture_slots << std::endl;
|
||||||
|
if (counter > 0 && counter % this->texture_slots == 0) {
|
||||||
|
Game::draw();
|
||||||
|
this->counter = 0;
|
||||||
|
this->vbo_offset = 0;
|
||||||
|
this->ebo_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::draw();
|
||||||
|
this->counter = 0;
|
||||||
|
this->vbo_offset = 0;
|
||||||
|
this->ebo_offset = 0;
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
|
glfwSwapBuffers(this->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::load(Sprite *sprite, int count) {
|
||||||
|
unsigned int program = this->program.id;
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
glUniform1i(glGetUniformLocation(program, "sampler"), count);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vbo_offset, sizeof(struct vertex) * sprite->vertices.size(), sprite->vertices.data());
|
||||||
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ebo_offset, sizeof(int) * sprite->indices.size(), sprite->indices.data());
|
||||||
|
|
||||||
|
vbo_offset += sizeof(struct vertex) * sprite->vertices.size();
|
||||||
|
ebo_offset += sizeof(int) * sprite->indices.size();
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0 + count);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, sprite->texture.texture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::draw() {
|
||||||
|
unsigned int program = this->program.id;
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
glm::mat4 view = glm::mat4(1.0f);
|
||||||
|
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
|
||||||
|
|
||||||
|
glm::mat4 projection = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
float half_width, half_height;
|
||||||
|
glfwGetWindowSize(this->window, &width, &height);
|
||||||
|
|
||||||
|
half_width = (float) width / 2;
|
||||||
|
half_height = (float) height / 2;
|
||||||
|
|
||||||
|
projection = glm::ortho(-half_width/100, half_width/100, -half_height/100, half_height/100, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(program,"view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, this->sprites[0]->indices.size(), GL_UNSIGNED_INT, 0);
|
||||||
|
std::cout << "Error: " << glGetError() << std::endl;
|
||||||
|
|
||||||
|
}
|
34
05-opengl/src/game.hpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "program.hpp"
|
||||||
|
#include "sprite.hpp"
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
public:
|
||||||
|
Game(GLFWwindow *window);
|
||||||
|
int setup(int initial_width, int initial_height);
|
||||||
|
void run();
|
||||||
|
void logic();
|
||||||
|
void load(Sprite *sprite, int counter);
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
// callbacks
|
||||||
|
static void input_callback(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||||
|
static void resize_callback(GLFWwindow *window, int new_width, int new_height);
|
||||||
|
|
||||||
|
GLFWwindow *window;
|
||||||
|
Program program;
|
||||||
|
|
||||||
|
std::vector<Sprite *> sprites;
|
||||||
|
|
||||||
|
int texture_slots;
|
||||||
|
unsigned int vao;
|
||||||
|
unsigned int vbo;
|
||||||
|
unsigned int ebo;
|
||||||
|
unsigned int counter;
|
||||||
|
unsigned int vbo_offset;
|
||||||
|
unsigned int ebo_offset;
|
||||||
|
};
|
40
05-opengl/src/main.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <stb/stb_image.h>
|
||||||
|
#include "game.hpp"
|
||||||
|
|
||||||
|
int initial_width = 1000;
|
||||||
|
int initial_height = 600;
|
||||||
|
std::string vertex_shader_location = "assets/shaders/shader.vert";
|
||||||
|
std::string fragment_shader_location = "assets/shaders/shader.frag";
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
GLFWwindow *window = glfwCreateWindow(initial_width, initial_height, "OpenGL", NULL, NULL);
|
||||||
|
if (window == NULL) {
|
||||||
|
std::cout << "Error: failed creating window" << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
|
GLenum err = glewInit();
|
||||||
|
if (err != GLEW_OK) {
|
||||||
|
std::cout << "Error: failed initializing glew " << glewGetErrorString(err) << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game main_game(window);
|
||||||
|
main_game.setup(initial_width, initial_height);
|
||||||
|
main_game.run();
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
2
05-opengl/src/other/stb_image.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
7987
05-opengl/src/other/stb_image.h
Normal file
38
05-opengl/src/program.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "program.hpp"
|
||||||
|
|
||||||
|
Program::Program() {
|
||||||
|
this->id = glCreateProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Program::add_shader(const char *path, unsigned int type) {
|
||||||
|
Shader new_shader;
|
||||||
|
unsigned int ret = new_shader.load(path, type);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
this->shaders.push_back(new_shader);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Program::link() {
|
||||||
|
for (int shader = 0; shader < this->shaders.size(); shader++)
|
||||||
|
glAttachShader(this->id, this->shaders[shader].id);
|
||||||
|
|
||||||
|
glLinkProgram(this->id);
|
||||||
|
|
||||||
|
int success;
|
||||||
|
char info_log[512];
|
||||||
|
glGetProgramiv(this->id, GL_LINK_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
glGetProgramInfoLog(this->id, 512, NULL, info_log);
|
||||||
|
std::cout << "Error: failed linking program. " << info_log << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
13
05-opengl/src/program.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "shader.hpp"
|
||||||
|
|
||||||
|
struct Program {
|
||||||
|
unsigned int id;
|
||||||
|
std::vector<Shader> shaders;
|
||||||
|
|
||||||
|
Program();
|
||||||
|
int add_shader(const char *path, unsigned int type);
|
||||||
|
int link();
|
||||||
|
};
|
31
05-opengl/src/shader.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
unsigned int Shader::load(const char *path, unsigned int type) {
|
||||||
|
std::string source_s = read_file(path);
|
||||||
|
const char *source = source_s.c_str();
|
||||||
|
|
||||||
|
unsigned int new_shader = glCreateShader(type);
|
||||||
|
if (!new_shader)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
glShaderSource(new_shader, 1, &source, NULL);
|
||||||
|
glCompileShader(new_shader);
|
||||||
|
|
||||||
|
int success;
|
||||||
|
char info_log[512];
|
||||||
|
glGetShaderiv(new_shader, GL_COMPILE_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderInfoLog(new_shader, 512, NULL, info_log);
|
||||||
|
std::cout << "Error: failed compiling new shader " << info_log << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->id = new_shader;
|
||||||
|
this->type = type;
|
||||||
|
|
||||||
|
return new_shader;
|
||||||
|
}
|
8
05-opengl/src/shader.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Shader {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int type;
|
||||||
|
|
||||||
|
unsigned int load(const char *path, unsigned int type);
|
||||||
|
};
|
59
05-opengl/src/sprite.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <stb/stb_image.h>
|
||||||
|
#include "game.hpp"
|
||||||
|
#include "sprite.hpp"
|
||||||
|
|
||||||
|
Sprite::Sprite(const char *path, enum TextureType type) : texture(type) {
|
||||||
|
int image_width;
|
||||||
|
int image_height;
|
||||||
|
int image_resolution;
|
||||||
|
int image_channels;
|
||||||
|
|
||||||
|
unsigned char *image_bytes = stbi_load(path, &image_width, &image_height, &image_channels, 0);
|
||||||
|
if (image_bytes == NULL) {
|
||||||
|
std::cout << "Error: failed loading image data" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->texture.bind_texture();
|
||||||
|
this->texture.load_data(image_bytes, image_width, image_height, image_height);
|
||||||
|
|
||||||
|
stbi_image_free(image_bytes);
|
||||||
|
|
||||||
|
this->pos = glm::vec3(0.0f);
|
||||||
|
this->size = glm::vec3(1.0f);
|
||||||
|
this->rot = glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::bake() {
|
||||||
|
struct vertex v1 = { {0.5f, 0.5f, 0.0f}, {1.0f, 1.0f} };
|
||||||
|
struct vertex v2 = { {0.5f, -0.5f, 0.0f}, {1.0f, 0.0f} };
|
||||||
|
struct vertex v3 = { {-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f} };
|
||||||
|
struct vertex v4 = { {-0.5f, 0.5f, 0.0f}, {0.0f, 1.0f} };
|
||||||
|
|
||||||
|
this->vertices.push_back(v1);
|
||||||
|
this->vertices.push_back(v2);
|
||||||
|
this->vertices.push_back(v3);
|
||||||
|
this->vertices.push_back(v4);
|
||||||
|
|
||||||
|
this->indices = {
|
||||||
|
0, 1, 3,
|
||||||
|
1, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture &tex = this->texture;
|
||||||
|
if (tex.type == SPLIT_TEXTURE) {
|
||||||
|
for (int i = 0; i < this->vertices.size(); i++) {
|
||||||
|
struct vertex *v = &this->vertices[i];
|
||||||
|
|
||||||
|
float tex_x = ((tex.cell_x + v->texture[0]) * tex.cell_res) / tex.texture_width;
|
||||||
|
float tex_y = ((tex.cell_y + v->texture[1]) * tex.cell_res) / tex.texture_height;
|
||||||
|
|
||||||
|
v->texture[0] = tex_x;
|
||||||
|
v->texture[1] = tex_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
05-opengl/src/sprite.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include "texture.hpp"
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
class Texture;
|
||||||
|
|
||||||
|
struct vertex {
|
||||||
|
float position[3];
|
||||||
|
float texture[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sprite {
|
||||||
|
public:
|
||||||
|
Texture texture;
|
||||||
|
|
||||||
|
glm::vec3 pos;
|
||||||
|
glm::vec3 size;
|
||||||
|
glm::vec3 rot;
|
||||||
|
|
||||||
|
std::vector<struct vertex> vertices;
|
||||||
|
std::vector<int> indices;
|
||||||
|
|
||||||
|
Game *game;
|
||||||
|
|
||||||
|
Sprite(const char *path, enum TextureType type);
|
||||||
|
void bake();
|
||||||
|
};
|
29
05-opengl/src/texture.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "texture.hpp"
|
||||||
|
|
||||||
|
Texture::Texture(enum TextureType type) {
|
||||||
|
glGenTextures(1, &this->texture_id);
|
||||||
|
this->type = type;
|
||||||
|
this->cell_x = 0;
|
||||||
|
this->cell_y = 0;
|
||||||
|
this->cell_res = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::bind_texture() {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->texture_id);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::load_data(unsigned char *bytes, int width, int height, int cell_res) {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
this->texture_width = width;
|
||||||
|
this->texture_height = height;
|
||||||
|
this->cell_res = cell_res;
|
||||||
|
}
|
24
05-opengl/src/texture.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum TextureType {
|
||||||
|
FULL_TEXTURE,
|
||||||
|
SPLIT_TEXTURE,
|
||||||
|
DYNAMIC_TEXTURE
|
||||||
|
};
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
public:
|
||||||
|
unsigned int texture_id;
|
||||||
|
|
||||||
|
Texture(enum TextureType type);
|
||||||
|
void bind_texture();
|
||||||
|
void load_data(unsigned char *bytes, int width, int height, int cell_res);
|
||||||
|
|
||||||
|
enum TextureType type;
|
||||||
|
int texture_width;
|
||||||
|
int texture_height;
|
||||||
|
int cell_res;
|
||||||
|
|
||||||
|
int cell_x;
|
||||||
|
int cell_y;
|
||||||
|
};
|
43
06-monogame/.gitignore
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
*.swp
|
||||||
|
*.*~
|
||||||
|
project.lock.json
|
||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
nupkg/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Rider
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Visual Studio
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Fleet
|
||||||
|
.fleet/
|
||||||
|
|
||||||
|
# Code Rush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
msbuild.log
|
||||||
|
msbuild.err
|
||||||
|
msbuild.wrn
|
36
06-monogame/GUI/.config/dotnet-tools.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-mgcb": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-linux": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-windows": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-mac": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-mac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
06-monogame/GUI/Content/Content.mgcb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
#----------------------------- Global Properties ----------------------------#
|
||||||
|
|
||||||
|
/outputDir:bin/$(Platform)
|
||||||
|
/intermediateDir:obj/$(Platform)
|
||||||
|
/platform:DesktopGL
|
||||||
|
/config:
|
||||||
|
/profile:Reach
|
||||||
|
/compress:False
|
||||||
|
|
||||||
|
#-------------------------------- References --------------------------------#
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
||||||
|
#begin button-default-texture.png
|
||||||
|
/importer:TextureImporter
|
||||||
|
/processor:TextureProcessor
|
||||||
|
/processorParam:ColorKeyColor=255,0,255,255
|
||||||
|
/processorParam:ColorKeyEnabled=True
|
||||||
|
/processorParam:GenerateMipmaps=False
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:ResizeToPowerOfTwo=False
|
||||||
|
/processorParam:MakeSquare=False
|
||||||
|
/processorParam:TextureFormat=Color
|
||||||
|
/build:button-default-texture.png
|
||||||
|
|
||||||
|
#begin button.png
|
||||||
|
/importer:TextureImporter
|
||||||
|
/processor:TextureProcessor
|
||||||
|
/processorParam:ColorKeyColor=255,0,255,255
|
||||||
|
/processorParam:ColorKeyEnabled=True
|
||||||
|
/processorParam:GenerateMipmaps=False
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:ResizeToPowerOfTwo=False
|
||||||
|
/processorParam:MakeSquare=False
|
||||||
|
/processorParam:TextureFormat=Color
|
||||||
|
/build:button.png
|
||||||
|
|
||||||
|
#begin Fonts/default.spritefont
|
||||||
|
/importer:FontDescriptionImporter
|
||||||
|
/processor:LocalizedFontProcessor
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:TextureFormat=Compressed
|
||||||
|
/build:Fonts/default.spritefont
|
||||||
|
|
BIN
06-monogame/GUI/Content/Fonts/HackNerdFont.ttf
Normal file
70
06-monogame/GUI/Content/Fonts/default.spritefont
Executable file
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
This file contains an xml description of a font, and will be read by the XNA
|
||||||
|
Framework Content Pipeline. Follow the comments to customize the appearance
|
||||||
|
of the font in your game, and to change the characters which are available to draw
|
||||||
|
with.
|
||||||
|
-->
|
||||||
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
|
<Asset Type="Graphics:LocalizedFontDescription">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Modify this string to change the font that will be imported.
|
||||||
|
-->
|
||||||
|
<FontName>HackNerdFont.ttf</FontName>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Size is a float value, measured in points. Modify this value to change
|
||||||
|
the size of the font.
|
||||||
|
-->
|
||||||
|
<Size>12</Size>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
|
the amount of spacing in between characters.
|
||||||
|
-->
|
||||||
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
|
will be used when placing characters.
|
||||||
|
-->
|
||||||
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
|
and "Bold, Italic", and are case sensitive.
|
||||||
|
-->
|
||||||
|
<Style>Regular</Style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
|
or measure text that contains characters which were not included in the font.
|
||||||
|
-->
|
||||||
|
<DefaultCharacter>A</DefaultCharacter>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CharacterRegions control what letters are available in the font. Every
|
||||||
|
character from Start to End will be built and made available for drawing. The
|
||||||
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
|
See the documentation for more information.
|
||||||
|
For localized fonts you can leave this empty as the character range will be picked up
|
||||||
|
from the Resource Files.
|
||||||
|
-->
|
||||||
|
<CharacterRegions>
|
||||||
|
<CharacterRegion>
|
||||||
|
<Start> </Start>
|
||||||
|
<End>€</End>
|
||||||
|
</CharacterRegion>
|
||||||
|
</CharacterRegions>
|
||||||
|
<!--
|
||||||
|
ResourceFiles control the characters which will be in the font. It does this
|
||||||
|
by scanning the text in each of the resource files and adding those specific
|
||||||
|
characters to the font.
|
||||||
|
-->
|
||||||
|
<ResourceFiles>
|
||||||
|
<!-- <Resx>Strings.resx</Resx> -->
|
||||||
|
</ResourceFiles>
|
||||||
|
</Asset>
|
||||||
|
</XnaContent>
|
BIN
06-monogame/GUI/Content/button-default-texture.png
Normal file
After Width: | Height: | Size: 545 B |
BIN
06-monogame/GUI/Content/button.png
Normal file
After Width: | Height: | Size: 28 KiB |
29
06-monogame/GUI/GUI.csproj
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RollForward>Major</RollForward>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico" />
|
||||||
|
<None Remove="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
|
||||||
|
<Message Text="Restoring dotnet tools" Importance="High" />
|
||||||
|
<Exec Command="dotnet tool restore" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
73
06-monogame/GUI/Game1.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using GUI.UIElements;
|
||||||
|
|
||||||
|
namespace GUI;
|
||||||
|
|
||||||
|
public class Game1 : Game
|
||||||
|
{
|
||||||
|
private GraphicsDeviceManager _graphics;
|
||||||
|
private SpriteBatch _spriteBatch;
|
||||||
|
private Scene mainScene;
|
||||||
|
|
||||||
|
public Game1()
|
||||||
|
{
|
||||||
|
_graphics = new GraphicsDeviceManager(this);
|
||||||
|
Content.RootDirectory = "Content";
|
||||||
|
IsMouseVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
_spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||||
|
|
||||||
|
Scene.graphics = _graphics;
|
||||||
|
Scene.spriteBatch = _spriteBatch;
|
||||||
|
Scene.content = Content;
|
||||||
|
|
||||||
|
mainScene = new Scene();
|
||||||
|
DrawableData drawableData = new DrawableData("button");
|
||||||
|
drawableData.position = new Vector2(100.0f, 100.0f);
|
||||||
|
|
||||||
|
void buttonOnClick(Button obj)
|
||||||
|
{
|
||||||
|
Console.WriteLine("ACTION CALLED SUCCESSFULLY!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonData buttonData = new ButtonData(buttonOnClick);
|
||||||
|
buttonData.text = "Click me!";
|
||||||
|
|
||||||
|
Button mainButton = new Button(drawableData, buttonData);
|
||||||
|
|
||||||
|
mainScene.drawables.Add(mainButton);
|
||||||
|
|
||||||
|
mainScene.Initialize();
|
||||||
|
base.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadContent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||||
|
Exit();
|
||||||
|
|
||||||
|
mainScene.Update(gameTime);
|
||||||
|
|
||||||
|
base.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
GraphicsDevice.Clear(Color.Black);
|
||||||
|
|
||||||
|
mainScene.Draw(gameTime);
|
||||||
|
|
||||||
|
base.Draw(gameTime);
|
||||||
|
}
|
||||||
|
}
|
BIN
06-monogame/GUI/Icon.bmp
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
06-monogame/GUI/Icon.ico
Normal file
After Width: | Height: | Size: 144 KiB |
3
06-monogame/GUI/Program.cs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
using var game = new GUI.Game1();
|
||||||
|
game.Run();
|
176
06-monogame/GUI/UI/Button.cs
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||||
|
|
||||||
|
namespace GUI.UIElements;
|
||||||
|
|
||||||
|
public class ButtonData
|
||||||
|
{
|
||||||
|
public Color bgColor;
|
||||||
|
public Color fgColor;
|
||||||
|
|
||||||
|
public Color? hoverBgColor;
|
||||||
|
public Color? hoverFgColor;
|
||||||
|
|
||||||
|
public Color? pressedBgColor;
|
||||||
|
public Color? pressedFgColor;
|
||||||
|
|
||||||
|
public Color idleBgColor = Color.Black;
|
||||||
|
public Color idleFgColor = Color.White;
|
||||||
|
|
||||||
|
public bool isPressed = false;
|
||||||
|
public bool isReleased = false;
|
||||||
|
public bool isHovered = false;
|
||||||
|
public bool isIdle = false;
|
||||||
|
|
||||||
|
public Action<Button>? onClick;
|
||||||
|
|
||||||
|
public string text = "";
|
||||||
|
public Vector2 textPosition;
|
||||||
|
public Vector2 textResolution;
|
||||||
|
public Vector2 textScale;
|
||||||
|
|
||||||
|
public ButtonData(Action<Button>? onClick)
|
||||||
|
{
|
||||||
|
this.onClick = onClick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Button : Drawable
|
||||||
|
{
|
||||||
|
private DrawableData _drawableData;
|
||||||
|
public ButtonData _buttonData;
|
||||||
|
|
||||||
|
private SpriteFont buttonFont;
|
||||||
|
|
||||||
|
public Button(DrawableData data, ButtonData buttonData)
|
||||||
|
{
|
||||||
|
_drawableData = data;
|
||||||
|
_buttonData = buttonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
buttonFont = Scene.content.Load<SpriteFont>("Fonts/default");
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPressed()
|
||||||
|
{
|
||||||
|
if (_buttonData.isPressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_buttonData.bgColor = _buttonData.pressedBgColor ?? _buttonData.idleBgColor;
|
||||||
|
_buttonData.fgColor = _buttonData.pressedFgColor ?? _buttonData.idleFgColor;
|
||||||
|
|
||||||
|
if (_buttonData.onClick is not null)
|
||||||
|
_buttonData.onClick(this);
|
||||||
|
|
||||||
|
_buttonData.isReleased = false;
|
||||||
|
_buttonData.isPressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onReleased()
|
||||||
|
{
|
||||||
|
if (!_buttonData.isPressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_buttonData.bgColor = _buttonData.hoverBgColor ?? _buttonData.idleBgColor;
|
||||||
|
_buttonData.fgColor = _buttonData.hoverFgColor ?? _buttonData.idleFgColor;
|
||||||
|
|
||||||
|
_buttonData.isPressed = false;
|
||||||
|
_buttonData.isReleased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onHovered()
|
||||||
|
{
|
||||||
|
if (_buttonData.isHovered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_buttonData.bgColor = _buttonData.hoverBgColor ?? _buttonData.idleBgColor;
|
||||||
|
_buttonData.fgColor = _buttonData.hoverFgColor ?? _buttonData.idleFgColor;
|
||||||
|
|
||||||
|
_buttonData.isHovered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onIdle()
|
||||||
|
{
|
||||||
|
_buttonData.bgColor = _buttonData.idleBgColor;
|
||||||
|
_buttonData.fgColor = _buttonData.idleFgColor;
|
||||||
|
|
||||||
|
_buttonData.isPressed = false;
|
||||||
|
_buttonData.isReleased = false;
|
||||||
|
_buttonData.isHovered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buttonLogic()
|
||||||
|
{
|
||||||
|
var mstate = Mouse.GetState();
|
||||||
|
Vector2 mousePosition = mstate.Position.ToVector2();
|
||||||
|
|
||||||
|
bool outsideHorizontalBoundary = (mousePosition.X < _drawableData.position.X) || (mousePosition.X > (_drawableData.position.X + _drawableData.scale.X));
|
||||||
|
bool outsideVerticalBoundary = (mousePosition.Y < _drawableData.position.Y) || (mousePosition.Y > (_drawableData.position.Y + _drawableData.scale.Y));
|
||||||
|
|
||||||
|
if (outsideHorizontalBoundary || outsideVerticalBoundary)
|
||||||
|
{
|
||||||
|
onIdle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mstate.LeftButton == ButtonState.Pressed)
|
||||||
|
{
|
||||||
|
onPressed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mstate.LeftButton == ButtonState.Released)
|
||||||
|
{
|
||||||
|
onReleased();
|
||||||
|
}
|
||||||
|
|
||||||
|
onHovered();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
buttonLogic();
|
||||||
|
|
||||||
|
_buttonData.textResolution = buttonFont.MeasureString(_buttonData.text);
|
||||||
|
|
||||||
|
// we want to center the text so
|
||||||
|
Vector2 buttonCenter = (_drawableData.position + (Vector2.One / 2.0f));
|
||||||
|
Vector2 textHalfResolution = _buttonData.textResolution / 2.0f;
|
||||||
|
|
||||||
|
_buttonData.textPosition = buttonCenter - textHalfResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
Scene.spriteBatch.Draw(
|
||||||
|
_drawableData.texture,
|
||||||
|
_drawableData.position,
|
||||||
|
null,
|
||||||
|
Color.White,
|
||||||
|
_drawableData.rotation,
|
||||||
|
Vector2.Zero,
|
||||||
|
_drawableData.scale,
|
||||||
|
SpriteEffects.None,
|
||||||
|
0f
|
||||||
|
);
|
||||||
|
|
||||||
|
Scene.spriteBatch.DrawString(
|
||||||
|
buttonFont,
|
||||||
|
_buttonData.text,
|
||||||
|
_buttonData.textPosition,
|
||||||
|
_buttonData.fgColor,
|
||||||
|
_drawableData.rotation,
|
||||||
|
Vector2.Zero,
|
||||||
|
_drawableData.scale,
|
||||||
|
SpriteEffects.None,
|
||||||
|
0f,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
49
06-monogame/GUI/UI/Drawable.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace GUI.UIElements;
|
||||||
|
|
||||||
|
public class DrawableData
|
||||||
|
{
|
||||||
|
public Texture2D texture;
|
||||||
|
public Vector2 position = Vector2.Zero;
|
||||||
|
private Vector2 scale_multiplier = Vector2.One;
|
||||||
|
public Vector2 scale
|
||||||
|
{
|
||||||
|
get { return scale_multiplier * new Vector2(texture.Width, texture.Height); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
scale_multiplier = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float rotation = 0.0f;
|
||||||
|
|
||||||
|
public DrawableData(string? texture)
|
||||||
|
{
|
||||||
|
if (texture is not null)
|
||||||
|
{
|
||||||
|
this.texture = Scene.content.Load<Texture2D>(texture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.texture = Scene.content.Load<Texture2D>("button-default-texture");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DrawableType
|
||||||
|
{
|
||||||
|
Container,
|
||||||
|
Text,
|
||||||
|
Button,
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Drawable
|
||||||
|
{
|
||||||
|
public DrawableType drawableType;
|
||||||
|
public abstract void Initialize();
|
||||||
|
public abstract void Update(GameTime gameTime);
|
||||||
|
public abstract void Draw(GameTime gameTime);
|
||||||
|
}
|
79
06-monogame/GUI/UI/Scene.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace GUI.UIElements;
|
||||||
|
|
||||||
|
public class Scene
|
||||||
|
{
|
||||||
|
private static ContentManager? _content;
|
||||||
|
public static ContentManager content
|
||||||
|
{
|
||||||
|
get { return _content; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_content is not null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_content = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsDeviceManager? _graphics;
|
||||||
|
public static GraphicsDeviceManager graphics
|
||||||
|
{
|
||||||
|
get { return _graphics; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_graphics is not null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_graphics = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpriteBatch? _spriteBatch;
|
||||||
|
|
||||||
|
public static SpriteBatch spriteBatch
|
||||||
|
{
|
||||||
|
get { return _spriteBatch; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_spriteBatch is not null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_spriteBatch = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Drawable> drawables;
|
||||||
|
|
||||||
|
public Scene()
|
||||||
|
{
|
||||||
|
drawables = new List<Drawable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
foreach (Drawable drawable in drawables)
|
||||||
|
drawable.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
foreach (Drawable drawable in drawables)
|
||||||
|
drawable.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
|
||||||
|
|
||||||
|
foreach (Drawable drawable in drawables)
|
||||||
|
drawable.Draw(gameTime);
|
||||||
|
|
||||||
|
spriteBatch.End();
|
||||||
|
}
|
||||||
|
}
|
43
06-monogame/GUI/app.manifest
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="GUI"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
36
06-monogame/Introduction/.config/dotnet-tools.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-mgcb": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-linux": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-windows": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-mac": {
|
||||||
|
"version": "3.8.1.303",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-mac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
100
06-monogame/Introduction/Character.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Content;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||||
|
|
||||||
|
namespace Introduction;
|
||||||
|
|
||||||
|
public class Character
|
||||||
|
{
|
||||||
|
public Texture2D texture;
|
||||||
|
public Texture2D noise;
|
||||||
|
public Vector2 pos;
|
||||||
|
public Vector2 scale;
|
||||||
|
public Vector2 rot;
|
||||||
|
public float angles;
|
||||||
|
public float speed;
|
||||||
|
|
||||||
|
private bool glitchEnabled = false;
|
||||||
|
private Effect glitch;
|
||||||
|
private float time;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
speed = 300.0f;
|
||||||
|
pos = Vector2.Zero;
|
||||||
|
scale = new Vector2(1f);
|
||||||
|
rot = Vector2.UnitX;
|
||||||
|
angles = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadContent(ContentManager content)
|
||||||
|
{
|
||||||
|
texture = content.Load<Texture2D>("player_texture");
|
||||||
|
noise = content.Load<Texture2D>("noise");
|
||||||
|
glitch = content.Load<Effect>("glitch");
|
||||||
|
|
||||||
|
if (glitch.Parameters["NoiseTexture"] is not null)
|
||||||
|
glitch.Parameters["NoiseTexture"].SetValue(texture);
|
||||||
|
|
||||||
|
if (glitch.Parameters["textureSize"] is not null)
|
||||||
|
glitch.Parameters["textureSize"].SetValue(new Vector2(texture.Width, texture.Height));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
var kstate = Keyboard.GetState();
|
||||||
|
if (kstate.IsKeyDown(Keys.W))
|
||||||
|
{
|
||||||
|
pos.Y -= speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kstate.IsKeyDown(Keys.S))
|
||||||
|
{
|
||||||
|
pos.Y += speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kstate.IsKeyDown(Keys.A))
|
||||||
|
{
|
||||||
|
pos.X -= speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kstate.IsKeyDown(Keys.D))
|
||||||
|
{
|
||||||
|
pos.X += speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kstate.IsKeyDown(Keys.K))
|
||||||
|
{
|
||||||
|
glitchEnabled = !glitchEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mstate = Mouse.GetState();
|
||||||
|
Vector2 mousePosition = new Vector2(mstate.X, mstate.Y);
|
||||||
|
Vector2 distancePosition = mousePosition - pos;
|
||||||
|
|
||||||
|
angles = (float) (Math.Atan2(distancePosition.Y, distancePosition.X));
|
||||||
|
|
||||||
|
time += (float) gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
|
||||||
|
if (glitch.Parameters["Time"] is not null)
|
||||||
|
glitch.Parameters["Time"].SetValue(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
|
||||||
|
{
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
|
||||||
|
Vector2 origin = new Vector2(texture.Width / 2, texture.Height / 2);
|
||||||
|
|
||||||
|
if (glitchEnabled)
|
||||||
|
glitch.CurrentTechnique.Passes[0].Apply();
|
||||||
|
else
|
||||||
|
time = 0;
|
||||||
|
|
||||||
|
spriteBatch.Draw(texture, pos, null, Color.White, angles, origin, scale, SpriteEffects.None, 0.0f);
|
||||||
|
spriteBatch.End();
|
||||||
|
}
|
||||||
|
}
|
45
06-monogame/Introduction/Content/Content.mgcb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
#----------------------------- Global Properties ----------------------------#
|
||||||
|
|
||||||
|
/outputDir:bin/$(Platform)
|
||||||
|
/intermediateDir:obj/$(Platform)
|
||||||
|
/platform:DesktopGL
|
||||||
|
/config:
|
||||||
|
/profile:Reach
|
||||||
|
/compress:False
|
||||||
|
|
||||||
|
#-------------------------------- References --------------------------------#
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
||||||
|
#begin glitch.fx
|
||||||
|
/importer:EffectImporter
|
||||||
|
/processor:EffectProcessor
|
||||||
|
/processorParam:DebugMode=Auto
|
||||||
|
/build:glitch.fx
|
||||||
|
|
||||||
|
#begin noise.png
|
||||||
|
/importer:TextureImporter
|
||||||
|
/processor:TextureProcessor
|
||||||
|
/processorParam:ColorKeyColor=255,0,255,255
|
||||||
|
/processorParam:ColorKeyEnabled=True
|
||||||
|
/processorParam:GenerateMipmaps=False
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:ResizeToPowerOfTwo=False
|
||||||
|
/processorParam:MakeSquare=False
|
||||||
|
/processorParam:TextureFormat=Color
|
||||||
|
/build:noise.png
|
||||||
|
|
||||||
|
#begin player_texture.png
|
||||||
|
/importer:TextureImporter
|
||||||
|
/processor:TextureProcessor
|
||||||
|
/processorParam:ColorKeyColor=255,0,255,255
|
||||||
|
/processorParam:ColorKeyEnabled=True
|
||||||
|
/processorParam:GenerateMipmaps=False
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:ResizeToPowerOfTwo=False
|
||||||
|
/processorParam:MakeSquare=False
|
||||||
|
/processorParam:TextureFormat=Color
|
||||||
|
/build:player_texture.png
|
||||||
|
|
47
06-monogame/Introduction/Content/glitch.fx
Executable file
|
@ -0,0 +1,47 @@
|
||||||
|
#if OPENGL
|
||||||
|
#define SV_POSITION POSITION
|
||||||
|
#define VS_SHADERMODEL vs_3_0
|
||||||
|
#define PS_SHADERMODEL ps_3_0
|
||||||
|
#else
|
||||||
|
#define VS_SHADERMODEL vs_4_0_level_9_1
|
||||||
|
#define PS_SHADERMODEL ps_4_0_level_9_1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
matrix WorldViewProjection;
|
||||||
|
|
||||||
|
sampler s0 : register (s0);
|
||||||
|
float Time;
|
||||||
|
float2 textureSize;
|
||||||
|
|
||||||
|
Texture2D NoiseTexture;
|
||||||
|
sampler2D NoiseSampler = sampler_state
|
||||||
|
{
|
||||||
|
Texture = <NoiseTexture>;
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 MainPS(float2 coords: TEXCOORD0) : COLOR0
|
||||||
|
{
|
||||||
|
float2 up_limit = float2(0.0, 0.0) + float2(Time, Time);
|
||||||
|
float2 down_limit = textureSize - float2(Time, Time);
|
||||||
|
|
||||||
|
float4 output_col;
|
||||||
|
if (coords.x < up_limit.x || coords.y < up_limit.y) {
|
||||||
|
output_col = float4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
return output_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coords.x > down_limit.x || coords.y > down_limit.y) {
|
||||||
|
output_col = float4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
return output_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tex2D(s0, coords);
|
||||||
|
}
|
||||||
|
|
||||||
|
technique BasicColorDrawing
|
||||||
|
{
|
||||||
|
pass P0
|
||||||
|
{
|
||||||
|
PixelShader = compile PS_SHADERMODEL MainPS();
|
||||||
|
}
|
||||||
|
};
|
BIN
06-monogame/Introduction/Content/noise.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
06-monogame/Introduction/Content/player_texture.png
Normal file
After Width: | Height: | Size: 39 KiB |
53
06-monogame/Introduction/Game1.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace Introduction;
|
||||||
|
|
||||||
|
public class Game1 : Game
|
||||||
|
{
|
||||||
|
private GraphicsDeviceManager _graphics;
|
||||||
|
private SpriteBatch _spriteBatch;
|
||||||
|
private Character player;
|
||||||
|
|
||||||
|
public Game1()
|
||||||
|
{
|
||||||
|
_graphics = new GraphicsDeviceManager(this);
|
||||||
|
Content.RootDirectory = "Content";
|
||||||
|
IsMouseVisible = true;
|
||||||
|
player = new Character();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
player.Initialize();
|
||||||
|
|
||||||
|
base.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadContent()
|
||||||
|
{
|
||||||
|
_spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||||
|
player.LoadContent(Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||||
|
Exit();
|
||||||
|
|
||||||
|
player.Update(gameTime);
|
||||||
|
|
||||||
|
base.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
|
|
||||||
|
player.Draw(gameTime, _spriteBatch);
|
||||||
|
|
||||||
|
base.Draw(gameTime);
|
||||||
|
}
|
||||||
|
}
|
BIN
06-monogame/Introduction/Icon.bmp
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
06-monogame/Introduction/Icon.ico
Normal file
After Width: | Height: | Size: 144 KiB |
29
06-monogame/Introduction/Introduction.csproj
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RollForward>Major</RollForward>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico" />
|
||||||
|
<None Remove="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
|
||||||
|
<Message Text="Restoring dotnet tools" Importance="High" />
|
||||||
|
<Exec Command="dotnet tool restore" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
3
06-monogame/Introduction/Program.cs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
using var game = new Introduction.Game1();
|
||||||
|
game.Run();
|
43
06-monogame/Introduction/app.manifest
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="Introduction"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
BIN
07-boilerplate/.imgs/showcase.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
28
07-boilerplate/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
CC=g++
|
||||||
|
CFLAGS=-std=c++20 `pkg-config --cflags glfw3 glew glm`
|
||||||
|
LDFLAGS=`pkg-config --libs glfw3 glew glm`
|
||||||
|
TARGET=boilerplate
|
||||||
|
SDIR=src
|
||||||
|
ADIR=assets
|
||||||
|
ODIR=build
|
||||||
|
|
||||||
|
SRC=$(shell find $(SDIR) -type f -name *.cpp)
|
||||||
|
OBJ=$(SRC:.cpp=.o)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
$(TARGET): $(OBJ)
|
||||||
|
mkdir -p build
|
||||||
|
cp -rf $(ADIR) $(ODIR)/$(ADIR)
|
||||||
|
$(CC) -o $(ODIR)/$@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(ODIR)/$(TARGET)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(ODIR)/$(TARGET) $(OBJ)
|
8
07-boilerplate/README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<p align="center">
|
||||||
|
<img src=".imgs/showcase.png" width="300" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
|
||||||
|
Creating a boilerplate API to abstract away OpenGL.
|
||||||
|
- Also added my first ever batch renderer
|
BIN
07-boilerplate/assets/player/idle.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
07-boilerplate/assets/player/run.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
12
07-boilerplate/assets/shaders/default_fragment.glsl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 330 core
|
||||||
|
in vec4 _color;
|
||||||
|
in vec2 _texture_position;
|
||||||
|
in float _ctt;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// color = texture(sampler, _texture_position);
|
||||||
|
//color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
color = _color;
|
||||||
|
}
|
23
07-boilerplate/assets/shaders/default_vertex.glsl
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec4 position;
|
||||||
|
layout (location = 1) in vec4 origin;
|
||||||
|
layout (location = 2) in vec4 color;
|
||||||
|
layout (location = 3) in vec2 texture_position;
|
||||||
|
layout (location = 4) in float ctt;
|
||||||
|
|
||||||
|
uniform mat4 view_matrix;
|
||||||
|
uniform mat4 projection_matrix;
|
||||||
|
|
||||||
|
out vec4 _color;
|
||||||
|
out vec2 _texture_position;
|
||||||
|
out float _ctt;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 origined_position = origin.xyz + position.xyz;
|
||||||
|
|
||||||
|
gl_Position = projection_matrix * view_matrix * vec4(origined_position, 1.0);
|
||||||
|
_color = color;
|
||||||
|
_texture_position = texture_position;
|
||||||
|
_ctt = ctt;
|
||||||
|
}
|
13
07-boilerplate/assets/shaders/fragment.glsl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#version 330 core
|
||||||
|
out vec4 color;
|
||||||
|
in vec2 tex_coord;
|
||||||
|
|
||||||
|
uniform sampler2D sampler;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = texture(sampler, tex_coord);
|
||||||
|
// color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (color.a < 0.1)
|
||||||
|
discard;
|
||||||
|
}
|
14
07-boilerplate/assets/shaders/vertex.glsl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
layout (location = 1) in vec2 texture_coord;
|
||||||
|
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
out vec2 tex_coord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = projection * view * vec4(pos.xyz, 1.0);
|
||||||
|
tex_coord = texture_coord;
|
||||||
|
}
|
22
07-boilerplate/src/base/common.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
std::string read_file(const char *path) {
|
||||||
|
std::string content;
|
||||||
|
std::ifstream fs(path, std::ios::in);
|
||||||
|
|
||||||
|
if(!fs.is_open()) {
|
||||||
|
std::cerr << "Error: Could not read file " << path << ". File does not exist." << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line = "";
|
||||||
|
while(!fs.eof()) {
|
||||||
|
std::getline(fs, line);
|
||||||
|
content.append(line + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.close();
|
||||||
|
return content;
|
||||||
|
}
|
5
07-boilerplate/src/base/common.hpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string read_file(const char *path);
|
10
07-boilerplate/src/base/graphics/graphics.hpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define DEFAULT_POSITION_ATTRIBUTE 0
|
||||||
|
#define DEFAULT_ORIGIN_ATTRIBUTE 1
|
||||||
|
#define DEFAULT_COLOR_ATTRIBUTE 2
|
||||||
|
#define DEFAULT_TEXTURE_ATTRIBUTE 3
|
||||||
|
#define DEFAULT_CTT_ATTRIBUTE 4
|
||||||
|
|
||||||
|
#define QUAD 6
|
||||||
|
#define DEFAULT_VBO_SIZE QUAD * 1000000 // unit: rows of RenderData
|
38
07-boilerplate/src/base/graphics/program.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "program.hpp"
|
||||||
|
#include "../macros.hpp"
|
||||||
|
|
||||||
|
Program::Program() {
|
||||||
|
this->id = glCreateProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Program::add_shader(const char *path, unsigned int type) {
|
||||||
|
Shader new_shader;
|
||||||
|
unsigned int ret = new_shader.load(path, type);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return RET_ERR;
|
||||||
|
|
||||||
|
this->shaders.push_back(new_shader);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Program::link() {
|
||||||
|
for (int shader = 0; shader < this->shaders.size(); shader++)
|
||||||
|
glAttachShader(this->id, this->shaders[shader].id);
|
||||||
|
|
||||||
|
glLinkProgram(this->id);
|
||||||
|
|
||||||
|
int success;
|
||||||
|
char info_log[512];
|
||||||
|
glGetProgramiv(this->id, GL_LINK_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
glGetProgramInfoLog(this->id, 512, NULL, info_log);
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
14
07-boilerplate/src/base/graphics/program.hpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "shader.hpp"
|
||||||
|
|
||||||
|
struct Program {
|
||||||
|
GLuint id;
|
||||||
|
std::vector<Shader> shaders;
|
||||||
|
|
||||||
|
Program();
|
||||||
|
int add_shader(const char *path, unsigned int type);
|
||||||
|
int link();
|
||||||
|
};
|
155
07-boilerplate/src/base/graphics/renderer.cpp
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include "renderer.hpp"
|
||||||
|
#include "../macros.hpp"
|
||||||
|
#include "graphics.hpp"
|
||||||
|
|
||||||
|
Renderer::Renderer(Window &window) : window(window) {
|
||||||
|
pack = RendererPack();
|
||||||
|
this->window = window;
|
||||||
|
|
||||||
|
glGenBuffers(1, &this->vertex_buffer_id);
|
||||||
|
glGenVertexArrays(1, &this->array_buffer_id);
|
||||||
|
|
||||||
|
this->view_matrix = glm::mat4(1.0f);
|
||||||
|
this->projection_matrix = glm::mat4(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Renderer::setup(std::optional<Program> program) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (program != std::nullopt)
|
||||||
|
this->program = program.value();
|
||||||
|
else {
|
||||||
|
Program new_program = Program();
|
||||||
|
|
||||||
|
ret = new_program.add_shader("assets/shaders/default_vertex.glsl", GL_VERTEX_SHADER);
|
||||||
|
if (ret != RET_OK) {
|
||||||
|
LOG(LOG_ERR, "Failed adding vertex shader to program");
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = new_program.add_shader("assets/shaders/default_fragment.glsl", GL_FRAGMENT_SHADER);
|
||||||
|
if (ret != RET_OK) {
|
||||||
|
LOG(LOG_ERR, "Failed adding fragment shader to program");
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = new_program.link();
|
||||||
|
if (ret != RET_OK) {
|
||||||
|
LOG(LOG_ERR, "Failed linking program");
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->program = new_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(this->array_buffer_id);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertex_buffer_id);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(struct RendererData) * DEFAULT_VBO_SIZE, nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
DEFAULT_POSITION_ATTRIBUTE,
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(struct RendererData),
|
||||||
|
(void *) offsetof(RendererData, vertex)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(DEFAULT_POSITION_ATTRIBUTE);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
DEFAULT_ORIGIN_ATTRIBUTE,
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(struct RendererData),
|
||||||
|
(void *) offsetof(RendererData, origin)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(DEFAULT_ORIGIN_ATTRIBUTE);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
DEFAULT_COLOR_ATTRIBUTE,
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(struct RendererData),
|
||||||
|
(void *) offsetof(RendererData, color)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(DEFAULT_COLOR_ATTRIBUTE);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
DEFAULT_TEXTURE_ATTRIBUTE,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(struct RendererData),
|
||||||
|
(void *) offsetof(RendererData, tex)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(DEFAULT_TEXTURE_ATTRIBUTE);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
DEFAULT_CTT_ATTRIBUTE,
|
||||||
|
1,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
sizeof(struct RendererData),
|
||||||
|
(void *) offsetof(RendererData, ctt_ratio)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(DEFAULT_CTT_ATTRIBUTE);
|
||||||
|
|
||||||
|
// setup matrices
|
||||||
|
this->view_matrix = glm::translate(this->view_matrix, glm::vec3(0.0f, 0.0f, -3.0f));
|
||||||
|
|
||||||
|
return RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::draw(struct RendererData data) {
|
||||||
|
if (batch_buffer.size() >= DEFAULT_VBO_SIZE) {
|
||||||
|
LOG(LOG_WARN, "Batch buffer limit reached!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
batch_buffer.push_back(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::batch() {
|
||||||
|
glBindVertexArray(this->array_buffer_id);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, this->vertex_buffer_id);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, batch_buffer.size() * sizeof(struct RendererData), batch_buffer.data());
|
||||||
|
|
||||||
|
glUseProgram(this->program.id);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(this->program.id, "view_matrix"), 1, GL_FALSE, &this->view_matrix[0][0]);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(this->program.id, "projection_matrix"), 1, GL_FALSE, &this->projection_matrix[0][0]);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, DEFAULT_VBO_SIZE);
|
||||||
|
|
||||||
|
batch_buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::logic() {
|
||||||
|
int window_width;
|
||||||
|
int window_height;
|
||||||
|
float half_width;
|
||||||
|
float half_height;
|
||||||
|
|
||||||
|
this->window.get_size(&window_width, &window_height);
|
||||||
|
|
||||||
|
half_width = window_width / 2.0f;
|
||||||
|
half_height = window_height / 2.0f;
|
||||||
|
|
||||||
|
this->projection_matrix = glm::ortho(-half_width/100, half_width/100, -half_height/100, half_height/100, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::~Renderer() {
|
||||||
|
glDisableVertexAttribArray(DEFAULT_POSITION_ATTRIBUTE);
|
||||||
|
glDisableVertexAttribArray(DEFAULT_COLOR_ATTRIBUTE);
|
||||||
|
glDisableVertexAttribArray(DEFAULT_TEXTURE_ATTRIBUTE);
|
||||||
|
glDisableVertexAttribArray(DEFAULT_CTT_ATTRIBUTE);
|
||||||
|
}
|
32
07-boilerplate/src/base/graphics/renderer.hpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <optional>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include "renderer_pack.hpp"
|
||||||
|
#include "program.hpp"
|
||||||
|
#include "../window/window.hpp"
|
||||||
|
|
||||||
|
class Renderer {
|
||||||
|
public:
|
||||||
|
GLuint array_buffer_id;
|
||||||
|
GLuint vertex_buffer_id;
|
||||||
|
Program program;
|
||||||
|
RendererPack pack;
|
||||||
|
|
||||||
|
glm::mat4 view_matrix;
|
||||||
|
glm::mat4 projection_matrix;
|
||||||
|
|
||||||
|
Window &window;
|
||||||
|
|
||||||
|
Renderer(Window &window);
|
||||||
|
~Renderer();
|
||||||
|
|
||||||
|
int setup(std::optional<Program> program = std::nullopt);
|
||||||
|
void logic();
|
||||||
|
|
||||||
|
std::vector<struct RendererData> batch_buffer;
|
||||||
|
|
||||||
|
void draw(struct RendererData data);
|
||||||
|
void batch();
|
||||||
|
};
|
9
07-boilerplate/src/base/graphics/renderer_pack.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "renderer_pack.hpp"
|
||||||
|
|
||||||
|
RendererPack::RendererPack() {
|
||||||
|
this->data = std::vector<struct RendererData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
RendererPack::~RendererPack(){
|
||||||
|
|
||||||
|
}
|
22
07-boilerplate/src/base/graphics/renderer_pack.hpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
|
||||||
|
struct RendererData {
|
||||||
|
glm::vec4 vertex;
|
||||||
|
glm::vec4 origin;
|
||||||
|
glm::vec4 color;
|
||||||
|
glm::vec2 tex;
|
||||||
|
float ctt_ratio; // color to texture ratio (i.e. how much does the color affect the texture)
|
||||||
|
};
|
||||||
|
|
||||||
|
class RendererPack {
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<struct RendererData> data;
|
||||||
|
RendererPack();
|
||||||
|
~RendererPack();
|
||||||
|
};
|
33
07-boilerplate/src/base/graphics/shader.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include "../common.hpp"
|
||||||
|
#include "../macros.hpp"
|
||||||
|
|
||||||
|
unsigned int Shader::load(const char *path, unsigned int type) {
|
||||||
|
std::string source_s = read_file(path);
|
||||||
|
const char *source = source_s.c_str();
|
||||||
|
|
||||||
|
unsigned int new_shader = glCreateShader(type);
|
||||||
|
if (!new_shader)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
glShaderSource(new_shader, 1, &source, NULL);
|
||||||
|
glCompileShader(new_shader);
|
||||||
|
|
||||||
|
int success;
|
||||||
|
char info_log[512];
|
||||||
|
glGetShaderiv(new_shader, GL_COMPILE_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
glGetShaderInfoLog(new_shader, 512, NULL, info_log);
|
||||||
|
std::cout << "Error: failed compiling new shader " << info_log << std::endl;
|
||||||
|
LOG(LOG_ERR, "Failed compiling new shader");
|
||||||
|
return RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->id = new_shader;
|
||||||
|
this->type = type;
|
||||||
|
|
||||||
|
return new_shader;
|
||||||
|
}
|
8
07-boilerplate/src/base/graphics/shader.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Shader {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int type;
|
||||||
|
|
||||||
|
unsigned int load(const char *path, unsigned int type);
|
||||||
|
};
|
12
07-boilerplate/src/base/macros.hpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define LOG_DEBUG "debug"
|
||||||
|
#define LOG_WARN "warning"
|
||||||
|
#define LOG_ERR "error"
|
||||||
|
|
||||||
|
#define LOG(level, ...) std::cout << "[" << __TIME__ << " " << level << "]: " << __VA_ARGS__ << std::endl;
|
||||||
|
|
||||||
|
#define RET_OK 0
|
||||||
|
#define RET_ERR -1
|
39
07-boilerplate/src/base/window/window.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "window.hpp"
|
||||||
|
#include "../macros.hpp"
|
||||||
|
|
||||||
|
int Window::init(int width, int height, std::string title) {
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
this->window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
|
||||||
|
if (this->window == NULL) {
|
||||||
|
LOG(LOG_ERR, "Failed creating window");
|
||||||
|
glfwTerminate();
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(this->window);
|
||||||
|
|
||||||
|
GLenum err = glewInit();
|
||||||
|
if (err != GLEW_OK) {
|
||||||
|
LOG(LOG_ERR, "FAiled initializing Glew");
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwSetFramebufferSizeCallback(this->window, this->resize_callback);
|
||||||
|
|
||||||
|
return RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::resize_callback(GLFWwindow *window, int new_width, int new_height) {
|
||||||
|
glViewport(0, 0, new_width, new_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::get_size(int *width, int *height) {
|
||||||
|
glfwGetWindowSize(this->window, width, height);
|
||||||
|
}
|
13
07-boilerplate/src/base/window/window.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
class Window {
|
||||||
|
public:
|
||||||
|
int init(int width, int height, std::string title);
|
||||||
|
|
||||||
|
static void resize_callback(GLFWwindow *window, int new_width, int new_height);
|
||||||
|
void get_size(int *width, int *height);
|
||||||
|
|
||||||
|
GLFWwindow *window;
|
||||||
|
};
|
48
07-boilerplate/src/main.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <stb/stb_image.h>
|
||||||
|
#include "base/window/window.hpp"
|
||||||
|
#include "base/graphics/renderer.hpp"
|
||||||
|
#include "base/macros.hpp"
|
||||||
|
#include "sprites/sprite.hpp"
|
||||||
|
|
||||||
|
const int initial_width = 1000;
|
||||||
|
const int initial_height = 600;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
Window window;
|
||||||
|
window.init(initial_width, initial_height, "OpenGL");
|
||||||
|
|
||||||
|
Renderer main_renderer(window);
|
||||||
|
int ret = main_renderer.setup();
|
||||||
|
if (ret != RET_OK) {
|
||||||
|
LOG(LOG_ERR, "Failed setting up a new renderer");
|
||||||
|
return RET_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Sprite> sprites;
|
||||||
|
|
||||||
|
Sprite sprite(main_renderer);
|
||||||
|
sprite.bake();
|
||||||
|
|
||||||
|
sprite.origin = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(window.window)) {
|
||||||
|
glClearColor(0, 0, 0, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
sprite.update();
|
||||||
|
main_renderer.logic();
|
||||||
|
main_renderer.batch();
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
|
glfwSwapBuffers(window.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
return RET_OK;
|
||||||
|
}
|
2
07-boilerplate/src/other/stb_image.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
7987
07-boilerplate/src/other/stb_image.h
Normal file
44
07-boilerplate/src/sprites/sprite.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "../base/graphics/renderer.hpp"
|
||||||
|
#include "sprite.hpp"
|
||||||
|
|
||||||
|
Sprite::Sprite(Renderer &renderer) : renderer(renderer) {
|
||||||
|
this->vertices = std::vector<glm::vec4>();
|
||||||
|
this->origin = glm::vec4(1.0f);
|
||||||
|
this->color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
this->texture_position = glm::vec2(0.0f);
|
||||||
|
this->ctt = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare data
|
||||||
|
void Sprite::bake() {
|
||||||
|
this->vertices.push_back(glm::vec4(0.5f, 0.5f, 0.0f, 0.0f));
|
||||||
|
this->vertices.push_back(glm::vec4(0.5f, -0.5f, 0.0f, 0.0f));
|
||||||
|
this->vertices.push_back(glm::vec4(-0.5f, -0.5f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
this->vertices.push_back(glm::vec4(-0.5f, 0.5f, 0.0f, 0.0f));
|
||||||
|
this->vertices.push_back(glm::vec4(0.5f, 0.5f, 0.0f, 0.0f));
|
||||||
|
this->vertices.push_back(glm::vec4(-0.5f, -0.5f, 0.0f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::update() {
|
||||||
|
for (int i = 0; i < this->vertices.size(); i++) {
|
||||||
|
struct RendererData data = {
|
||||||
|
.vertex = this->vertices[i],
|
||||||
|
.origin = this->origin,
|
||||||
|
.color = this->color,
|
||||||
|
.tex = this->texture_position,
|
||||||
|
.ctt_ratio = this->ctt
|
||||||
|
};
|
||||||
|
|
||||||
|
this->renderer.draw(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite::~Sprite() {
|
||||||
|
|
||||||
|
}
|
26
07-boilerplate/src/sprites/sprite.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include "../base/graphics/renderer.hpp"
|
||||||
|
|
||||||
|
class Sprite {
|
||||||
|
public:
|
||||||
|
std::vector<glm::vec4> vertices;
|
||||||
|
glm::vec4 origin;
|
||||||
|
glm::vec4 color;
|
||||||
|
glm::vec2 texture_position;
|
||||||
|
float ctt;
|
||||||
|
|
||||||
|
// GLuint vertex_buffer_id;
|
||||||
|
Renderer &renderer;
|
||||||
|
|
||||||
|
Sprite(Renderer &renderer);
|
||||||
|
~Sprite();
|
||||||
|
|
||||||
|
void bake();
|
||||||
|
void update();
|
||||||
|
};
|
BIN
08-particle-system/.imgs/showcase.png
Normal file
After Width: | Height: | Size: 89 KiB |
28
08-particle-system/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
CC=g++
|
||||||
|
CFLAGS=-std=c++20 `pkg-config --cflags glfw3 glew glm`
|
||||||
|
LDFLAGS=`pkg-config --libs glfw3 glew glm`
|
||||||
|
TARGET=boilerplate
|
||||||
|
SDIR=src
|
||||||
|
ADIR=assets
|
||||||
|
ODIR=build
|
||||||
|
|
||||||
|
SRC=$(shell find $(SDIR) -type f -name *.cpp)
|
||||||
|
OBJ=$(SRC:.cpp=.o)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: default
|
||||||
|
$(TARGET): $(OBJ)
|
||||||
|
mkdir -p build
|
||||||
|
cp -rf $(ADIR) $(ODIR)/
|
||||||
|
$(CC) -o $(ODIR)/$@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(ODIR)/$(TARGET)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(ODIR)/$(TARGET) $(OBJ)
|
10
08-particle-system/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<p align="center">
|
||||||
|
<img src=".imgs/showcase.png" width="300" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Particle System OpenGL
|
||||||
|
|
||||||
|
Contains a particle system abstraction on top of the previous OpenGL boilerplate code (`07-boilerplate`).
|
||||||
|
|
||||||
|
Each particle system is supposed (although not necessary) to have 1 renderer fully for itself.
|
||||||
|
Meaning that all the particles will be batched into 1 draw call.
|
BIN
08-particle-system/assets/brick.jpg
Normal file
After Width: | Height: | Size: 3.8 MiB |
BIN
08-particle-system/assets/particle.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
08-particle-system/assets/player/idle.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
08-particle-system/assets/player/run.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
12
08-particle-system/assets/shaders/default_fragment.glsl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 330 core
|
||||||
|
in vec4 _color;
|
||||||
|
in vec2 _texture_position;
|
||||||
|
in float _ctt;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform sampler2D sampler;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = texture(sampler, _texture_position) * (_color * _ctt);
|
||||||
|
}
|
26
08-particle-system/assets/shaders/default_vertex.glsl
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec4 position;
|
||||||
|
layout (location = 1) in vec4 origin;
|
||||||
|
layout (location = 2) in vec4 size;
|
||||||
|
layout (location = 3) in vec4 color;
|
||||||
|
layout (location = 4) in vec2 texture_position;
|
||||||
|
layout (location = 5) in float ctt;
|
||||||
|
|
||||||
|
uniform mat4 view_matrix;
|
||||||
|
uniform mat4 projection_matrix;
|
||||||
|
|
||||||
|
out vec4 _color;
|
||||||
|
out vec2 _texture_position;
|
||||||
|
out float _ctt;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 origined_position = origin.xyz + position.xyz;
|
||||||
|
|
||||||
|
origined_position *= size.xyz;
|
||||||
|
|
||||||
|
gl_Position = projection_matrix * view_matrix * vec4(origined_position, 1.0);
|
||||||
|
_color = color;
|
||||||
|
_texture_position = texture_position;
|
||||||
|
_ctt = ctt;
|
||||||
|
}
|
13
08-particle-system/assets/shaders/fragment.glsl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#version 330 core
|
||||||
|
out vec4 color;
|
||||||
|
in vec2 tex_coord;
|
||||||
|
|
||||||
|
uniform sampler2D sampler;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = texture(sampler, tex_coord);
|
||||||
|
// color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (color.a < 0.1)
|
||||||
|
discard;
|
||||||
|
}
|
14
08-particle-system/assets/shaders/vertex.glsl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 pos;
|
||||||
|
layout (location = 1) in vec2 texture_coord;
|
||||||
|
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
out vec2 tex_coord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = projection * view * vec4(pos.xyz, 1.0);
|
||||||
|
tex_coord = texture_coord;
|
||||||
|
}
|
BIN
08-particle-system/assets/smoke.png
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
08-particle-system/boilerplate.trace
Normal file
22
08-particle-system/src/base/common.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
std::string read_file(const char *path) {
|
||||||
|
std::string content;
|
||||||
|
std::ifstream fs(path, std::ios::in);
|
||||||
|
|
||||||
|
if(!fs.is_open()) {
|
||||||
|
std::cerr << "Error: Could not read file " << path << ". File does not exist." << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line = "";
|
||||||
|
while(!fs.eof()) {
|
||||||
|
std::getline(fs, line);
|
||||||
|
content.append(line + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.close();
|
||||||
|
return content;
|
||||||
|
}
|
5
08-particle-system/src/base/common.hpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::string read_file(const char *path);
|