06: add introduction to monogame

This commit is contained in:
0xdeadbeer 2023-12-05 17:18:36 +01:00
parent 8455ffac2e
commit 727d3535ba
25 changed files with 483 additions and 55 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ build/
*.o *.o
compile_commands.json compile_commands.json
.idea/ .idea/
bin/

3
.gitmodules vendored Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
.imgs/opengl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -2,10 +2,10 @@
out vec4 color; out vec4 color;
in vec2 tex_coord; in vec2 tex_coord;
uniform sampler2D texture1; uniform sampler2D sampler;
void main() { void main() {
color = texture(texture1, tex_coord); color = texture(sampler, tex_coord);
// color = vec4(1.0, 0.0, 0.0, 1.0); // color = vec4(1.0, 0.0, 0.0, 1.0);
if (color.a < 0.1) if (color.a < 0.1)

View File

@ -3,18 +3,12 @@
layout (location = 0) in vec3 pos; layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texture_coord; layout (location = 1) in vec2 texture_coord;
uniform vec3 size;
uniform ivec3 offset;
uniform mat4 model;
uniform mat4 view; uniform mat4 view;
uniform mat4 projection; uniform mat4 projection;
out vec2 tex_coord; out vec2 tex_coord;
void main() { void main() {
vec3 new_pos = pos.xyz + offset.xyz; gl_Position = projection * view * vec4(pos.xyz, 1.0);
new_pos = new_pos.xyz * size.xyz;
gl_Position = projection * view * model * vec4(new_pos.xyz, 1.0);
tex_coord = texture_coord; tex_coord = texture_coord;
} }

View File

@ -13,7 +13,10 @@
Game::Game(GLFWwindow *window) { Game::Game(GLFWwindow *window) {
this->window = window; this->window = window;
this->program = Program(); this->program = Program();
stbi_set_flip_vertically_on_load(true); stbi_set_flip_vertically_on_load(true);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &this->texture_slots);
} }
// code this later lol // code this later lol
@ -41,14 +44,40 @@ int Game::setup(int initial_width, int initial_height) {
} }
glUseProgram(this->program.id); 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; return 0;
} }
void Game::run() { void Game::run() {
this->counter = 0;
this->vbo_offset = 0;
this->ebo_offset = 0;
Sprite sprite("assets/player/idle.png", SPLIT_TEXTURE); Sprite sprite("assets/player/idle.png", SPLIT_TEXTURE);
sprite.bake(); sprite.bake();
this->sprites.push_back(&sprite); 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(); Game::logic();
} }
@ -74,8 +103,24 @@ void Game::logic() {
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < this->sprites.size(); i++)
Game::draw(this->sprites[i]); 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(); glfwPollEvents();
glfwSwapBuffers(this->window); glfwSwapBuffers(this->window);
@ -84,16 +129,25 @@ void Game::logic() {
glBindVertexArray(0); glBindVertexArray(0);
} }
void Game::draw(Sprite *sprite) { void Game::load(Sprite *sprite, int count) {
unsigned int program = this->program.id; unsigned int program = this->program.id;
glUseProgram(program); glUseProgram(program);
glUniform3i(glGetUniformLocation(program, "offset"), sprite->pos.x, sprite->pos.y, sprite->pos.z); glUniform1i(glGetUniformLocation(program, "sampler"), count);
glUniform3f(glGetUniformLocation(program, "size"), sprite->size.x, sprite->size.y, sprite->size.z);
glUniform1i(glGetUniformLocation(program, "texture1"), 0);
glm::mat4 model = glm::mat4(1.0f); glBufferSubData(GL_ARRAY_BUFFER, vbo_offset, sizeof(struct vertex) * sprite->vertices.size(), sprite->vertices.data());
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); 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); glm::mat4 view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f)); view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
@ -109,19 +163,10 @@ void Game::draw(Sprite *sprite) {
projection = glm::ortho(-half_width/100, half_width/100, -half_height/100, half_height/100, 0.1f, 100.0f); projection = glm::ortho(-half_width/100, half_width/100, -half_height/100, half_height/100, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(program,"view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(program,"view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(sprite->vao); glDrawElements(GL_TRIANGLES, this->sprites[0]->indices.size(), GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ARRAY_BUFFER, sprite->vbo); std::cout << "Error: " << glGetError() << std::endl;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sprite->ebo);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(struct vertex) * sprite->vertices.size(), sprite->vertices.data());
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * sprite->indices.size(), sprite->indices.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sprite->texture.texture_id);
glDrawElements(GL_TRIANGLES, sprite->indices.size(), GL_UNSIGNED_INT, 0);
} }

View File

@ -12,15 +12,23 @@ public:
int setup(int initial_width, int initial_height); int setup(int initial_width, int initial_height);
void run(); void run();
void logic(); void logic();
void draw(Sprite *sprite); void load(Sprite *sprite, int counter);
void draw();
// callbacks // callbacks
static void input_callback(GLFWwindow *window, int key, int scancode, int action, int mods); 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); static void resize_callback(GLFWwindow *window, int new_width, int new_height);
GLFWwindow *window; GLFWwindow *window;
Program program;
std::vector<Sprite *> sprites; std::vector<Sprite *> sprites;
Program program; int texture_slots;
unsigned int vao;
unsigned int vbo;
unsigned int ebo;
unsigned int counter;
unsigned int vbo_offset;
unsigned int ebo_offset;
}; };

View File

@ -23,10 +23,6 @@ Sprite::Sprite(const char *path, enum TextureType type) : texture(type) {
stbi_image_free(image_bytes); stbi_image_free(image_bytes);
glGenVertexArrays(1, &this->vao);
glGenBuffers(1, &this->vbo);
glGenBuffers(1, &this->ebo);
this->pos = glm::vec3(0.0f); this->pos = glm::vec3(0.0f);
this->size = glm::vec3(1.0f); this->size = glm::vec3(1.0f);
this->rot = glm::vec3(0.0f); this->rot = glm::vec3(0.0f);
@ -60,20 +56,4 @@ void Sprite::bake() {
v->texture[1] = tex_y; v->texture[1] = tex_y;
} }
} }
glBindVertexArray(this->vao);
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(struct vertex), nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(int), 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);
glBindVertexArray(0);
} }

View File

@ -22,10 +22,6 @@ public:
std::vector<struct vertex> vertices; std::vector<struct vertex> vertices;
std::vector<int> indices; std::vector<int> indices;
unsigned int vao;
unsigned int vbo;
unsigned int ebo;
Game *game; Game *game;
Sprite(const char *path, enum TextureType type); Sprite(const char *path, enum TextureType type);

43
06-monogame/.gitignore vendored Normal file
View 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

View 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"
]
}
}
}

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

View 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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View 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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View 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>

View File

@ -0,0 +1,3 @@

using var game = new Introduction.Game1();
game.Run();

View 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>

View File

@ -1,5 +1,7 @@
<p align="center"> <p align="center">
<img src=".imgs/icon.png" width="200"/> <img src=".imgs/sdl.png" width="200"/>
<img src=".imgs/opengl.png" width="200"/>
<img src=".imgs/monogame.png" width="200"/>
</p> </p>
# Graphics # Graphics