diff --git a/assets/shader/basic_pixel_shader.hlsl b/assets/shader/basic_pixel_shader.hlsl
new file mode 100644
index 0000000..3d29910
--- /dev/null
+++ b/assets/shader/basic_pixel_shader.hlsl
@@ -0,0 +1,18 @@
+struct PixelShaderInput {
+ float4 pos : SV_POSITION;
+ float4 color : COLOR;
+};
+
+struct PixelShaderOutput {
+ float4 color : SV_TARGET;
+};
+
+PixelShaderOutput main(PixelShaderInput input) {
+ PixelShaderOutput output;
+#if 1
+ output.color = input.color;
+#else
+ output.color = float4(1, 0, 1, 1);
+#endif
+ return output;
+}
\ No newline at end of file
diff --git a/assets/shader/basic_vertex_shader.hlsl b/assets/shader/basic_vertex_shader.hlsl
new file mode 100644
index 0000000..bd1db96
--- /dev/null
+++ b/assets/shader/basic_vertex_shader.hlsl
@@ -0,0 +1,53 @@
+struct VertexShaderInput {
+ // Per Vertex
+ float4 pos : VERTEX_POSITION;
+ uint vid : SV_VertexID;
+
+ // Per Instance
+ float4 pos_size : INSTANCE_POSITION_SIZE;
+ float4 left_color : LEFT_COLOR;
+
+};
+
+struct VertexShaderOutput {
+ float4 pos : SV_POSITION;
+ float4 color : COLOR;
+};
+
+
+
+VertexShaderOutput main(VertexShaderInput input) {
+ VertexShaderOutput output;
+
+ float2 rect_pos = input.pos_size.xy;
+ float2 rect_size = input.pos_size.zw;
+
+ float3x3 coord_sys = {
+ 2, 0, -1,
+ 0, -2, 1,
+ 0, 0, 1
+ };
+
+ input.pos_size.xy = mul(coord_sys, float3(input.pos_size.xy, 1)).xy;
+
+ float3x3 pos = {
+ 1, 0, input.pos_size.x,
+ 0, 1, input.pos_size.y,
+ 0, 0, 1
+ };
+
+ float3x3 size = {
+ rect_size.x, 0, 0,
+ 0, rect_size.y, 0,
+ 0, 0, 1
+ };
+
+ output.pos.xy = mul(pos, mul(size, input.pos.xyz)).xy;
+ //output.pos.xy = mul(pos, input.pos.xyz).xy;
+ output.pos.zw = float2(0, 1);
+
+ output.color = input.left_color;
+
+
+ return output;
+}
\ No newline at end of file
diff --git a/bin/pokemon.exe b/bin/pokemon.exe
index 78e1e75..7df4d36 100644
Binary files a/bin/pokemon.exe and b/bin/pokemon.exe differ
diff --git a/bin/pokemon.pdb b/bin/pokemon.pdb
index 0eb70aa..f378662 100644
Binary files a/bin/pokemon.pdb and b/bin/pokemon.pdb differ
diff --git a/pokemon.vcxproj b/pokemon.vcxproj
index 7914699..e01035f 100644
--- a/pokemon.vcxproj
+++ b/pokemon.vcxproj
@@ -70,8 +70,8 @@
true
- $(SolutionDir)bin
- $(SolutionDir)vs_trash
+ $(SolutionDir)bin\
+ $(SolutionDir)vs_trash\
$(SolutionDir)bin
@@ -106,9 +106,26 @@
true
+
+
+ -Wno-missing-braces -Wno-parentheses -Wno-reorder-init-list -Wno-unused-variable -Wno-format %(AdditionalOptions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pokemon.vcxproj.filters b/pokemon.vcxproj.filters
index 58beaf5..5d3cdf8 100644
--- a/pokemon.vcxproj.filters
+++ b/pokemon.vcxproj.filters
@@ -18,5 +18,37 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/pokemon.vcxproj.user b/pokemon.vcxproj.user
index 429333d..7ea7983 100644
--- a/pokemon.vcxproj.user
+++ b/pokemon.vcxproj.user
@@ -3,4 +3,8 @@
true
+
+ $(ProjectDir)bin
+ WindowsLocalDebugger
+
\ No newline at end of file
diff --git a/src/create_window.cpp b/src/create_window.cpp
new file mode 100644
index 0000000..7a0bef6
--- /dev/null
+++ b/src/create_window.cpp
@@ -0,0 +1,25 @@
+#include "create_window.h"
+
+
+//create Window
+void* create_window(LRESULT (*WindowProc)(HWND, UINT, WPARAM, LPARAM)) {
+ WNDCLASSEXA window_class_struct = {};
+ window_class_struct.cbSize = sizeof(WNDCLASSEXW);
+ window_class_struct.style = CS_CLASSDC | CS_HREDRAW | CS_VREDRAW;
+ window_class_struct.lpfnWndProc = WindowProc;
+ window_class_struct.cbClsExtra = 0;
+ window_class_struct.cbWndExtra = 0;
+ window_class_struct.hInstance = GetModuleHandle(NULL);
+ window_class_struct.hIcon = 0;
+ window_class_struct.hCursor = LoadCursor(NULL, IDC_ARROW);
+ window_class_struct.hbrBackground = 0;
+ window_class_struct.lpszMenuName = 0;
+ window_class_struct.lpszClassName = "DX_WINDOW_CLASS";
+ window_class_struct.hIconSm = 0;
+
+ ATOM window_class = RegisterClassExA(&window_class_struct);
+ if (!window_class)
+ return 0;
+
+ return CreateWindowExA(0, "DX_WINDOW_CLASS", "Pokemon", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(NULL), 0);
+}
\ No newline at end of file
diff --git a/src/create_window.h b/src/create_window.h
new file mode 100644
index 0000000..24c559a
--- /dev/null
+++ b/src/create_window.h
@@ -0,0 +1,3 @@
+#pragma once
+#include
+void* create_window(LRESULT(*WindowProc)(HWND, UINT, WPARAM, LPARAM));
\ No newline at end of file
diff --git a/src/load_entire_file.cpp b/src/load_entire_file.cpp
new file mode 100644
index 0000000..94f74da
--- /dev/null
+++ b/src/load_entire_file.cpp
@@ -0,0 +1,32 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include "load_entire_file.h"
+
+#include
+#include
+
+String load_entire_file(const char* filename) {
+ auto file = fopen(filename, "rb");
+ if (!file)
+ return {};
+
+ if (fseek(file, 0, SEEK_END))
+ return {};
+
+ auto file_length = ftell(file);
+ if (file_length == -1)
+ return {};
+
+ if (fseek(file, 0, SEEK_SET))
+ return {};
+
+ auto file_mem = malloc(file_length);
+ if (!file_mem)
+ return {};
+
+ if (fread(file_mem, file_length, 1, file) != 1) {
+ free(file_mem);
+ return {};
+ }
+
+ return { (size_t)file_length, (char*)file_mem };
+}
\ No newline at end of file
diff --git a/src/load_entire_file.h b/src/load_entire_file.h
new file mode 100644
index 0000000..1b82158
--- /dev/null
+++ b/src/load_entire_file.h
@@ -0,0 +1,4 @@
+#pragma once
+#include "m_string.h"
+
+String load_entire_file(const char* filename);
\ No newline at end of file
diff --git a/src/load_tga_file.cpp b/src/load_tga_file.cpp
new file mode 100644
index 0000000..a345525
--- /dev/null
+++ b/src/load_tga_file.cpp
@@ -0,0 +1,153 @@
+#include
+#include
+#include
+
+#include "load_tga_file.h"
+#include "m_string.h"
+#include "log.h"
+#include "load_entire_file.h"
+
+
+#define print_value(v) _Generic((v), \
+ int8_t: printf("%hhd", v), \
+ int16_t: printf("%hd", v), \
+ int32_t: printf("%d", v), \
+ int64_t: printf("%lld", v), \
+ long: printf("%lld", v), \
+ \
+ uint8_t: printf("%hhu", v), \
+ uint16_t: printf("%hu", v), \
+ uint32_t: printf("%u", v), \
+ uint64_t: printf("%llu", v), \
+ unsigned long: printf("%llu", v) \
+)
+
+bool _expect_read(String& file, String expected_value, const char* path, const char* error_msg) {
+ if (file.length < expected_value.length)
+ return false;
+ if (!(String{ expected_value.length, file.data } == expected_value)) {
+ log_error("'%s' %s expected '%.*s' got '%.*s'\n", path, error_msg, expected_value.length, expected_value.data, expected_value.length, file.data);
+ return false;
+ }
+ advance(file, expected_value.length);
+ return true;
+}
+
+template
+bool _expect_read(String& file, T expected_value, const char* path, const char* error_msg) {
+ if (file.length < sizeof(T))
+ return false;
+ if (*(T*)file.data != expected_value) {
+ printf("'%s' %s expected '", path, error_msg);
+ print_value(expected_value);
+ printf("' got '");
+ print_value(*(T*)file.data);
+ printf("'\n");
+ return false;
+ }
+
+ advance(file, sizeof(T));
+ return true;
+}
+
+template
+bool _expect(T value, S expected_value, const char* path, const char* error_msg) {
+ if (value != expected_value) {
+ printf("'%s' %s expected '", path, error_msg);
+ print_value(expected_value);
+ printf("' got '");
+ print_value(value);
+ printf("'\n");
+ return false;
+ }
+
+ return true;
+}
+
+#define expect_read(expected_value, error_msg) if(!_expect_read(file, expected_value, path, error_msg)) return{0, 0};
+#define expect(value, expected_value, error_msg) if(!_expect(value, expected_value, path, error_msg)) return{0, 0};
+
+
+#pragma pack(1)
+struct TGA_Color_Map_Info {
+ uint16_t index;
+ uint16_t length;
+ uint8_t size;
+};
+
+#pragma pack(1)
+struct TGA_Image_Specification {
+ uint16_t x_origin;
+ uint16_t y_origin;
+ uint16_t width;
+ uint16_t height;
+ uint8_t bits_per_pixel;
+ uint8_t image_descriptor;
+};
+
+BMP_Texture load_tga_file(const char* path) {
+ auto file = load_entire_file(path);
+ auto start_file = file;
+
+ if (!file.length) {
+ log_error("'%s' failed to load", path);
+ return{ 0, 0, 0 };
+ }
+
+ auto id_length = read(file);
+
+ auto color_map_type = read(file);
+ expect(color_map_type, 0, "wrong color map type");
+
+ auto image_type = read(file);
+ expect(image_type, 10, "wrong image type");
+
+ auto color_map_info = read(file);
+ expect(color_map_info.size, 0, "no existing color map");
+
+ auto image_specification = read(file);
+ expect(image_specification.bits_per_pixel, 32, "not 32 bitsperpixel");
+
+ auto descriptor_mask = 0x30;
+ auto image_origin = image_specification.image_descriptor & descriptor_mask;
+ expect(image_origin, 32, "wrong image origin");
+
+ advance(file, id_length);
+
+ uint32_t* start_pixel = (uint32_t*)malloc(image_specification.width * image_specification.height * 4);
+
+ uint32_t* pixel = start_pixel;
+
+
+ if (!start_pixel) {
+ log_error("'%s' malloc failed", path);
+ return { 0, 0 };
+ }
+
+ auto needed_pixel = image_specification.height * image_specification.width;
+
+ for (; needed_pixel;) {
+ auto type_and_repetition_count = read(file);
+ auto repetition_count = type_and_repetition_count & 0x7F;
+
+ if ((type_and_repetition_count & 0x80)) {
+ auto pixel_value = read(file);
+ for (; repetition_count + 1; repetition_count--) {
+ *pixel = pixel_value;
+ pixel++;
+ needed_pixel--;
+ }
+ }
+ else {
+ for (; repetition_count + 1; repetition_count--) {
+ auto pixel_value = read(file);
+ *pixel = pixel_value;
+ pixel++;
+ needed_pixel--;
+ }
+ }
+ }
+
+ return { image_specification.width, image_specification.height, start_pixel };
+}
+
diff --git a/src/load_tga_file.h b/src/load_tga_file.h
new file mode 100644
index 0000000..24db431
--- /dev/null
+++ b/src/load_tga_file.h
@@ -0,0 +1,11 @@
+#pragma once
+#include
+
+struct BMP_Texture {
+ int64_t bmp_width;
+ int64_t bmp_height;
+ uint32_t* pixel;
+};
+
+
+BMP_Texture load_tga_file(const char* path);
\ No newline at end of file
diff --git a/src/log.cpp b/src/log.cpp
new file mode 100644
index 0000000..ecfdcaf
--- /dev/null
+++ b/src/log.cpp
@@ -0,0 +1,25 @@
+#include "log.h"
+#include
+#include
+
+void _log(const char* function_name, const char* format, ...) {
+ printf("[%s] ", function_name);
+
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ printf("\n");
+}
+
+void _log_error(const char* function_name, const char* format, ...) {
+ printf("[%s]ERROR: ", function_name);
+
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ printf("\n");
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..7f37baf
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,6 @@
+#pragma once
+#define log(format, ...) _log(__FUNCTION__, format, __VA_ARGS__)
+#define log_error(format, ...) _log_error(__FUNCTION__, format, __VA_ARGS__)
+
+void _log(const char* function_name, const char* format, ...);
+void _log_error(const char* function_name, const char* format, ...);
\ No newline at end of file
diff --git a/src/m_string.h b/src/m_string.h
new file mode 100644
index 0000000..8e50a7f
--- /dev/null
+++ b/src/m_string.h
@@ -0,0 +1,67 @@
+#pragma once
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+struct String {
+
+ size_t length;
+ char* data;
+
+ constexpr String() : length(0), data(0) {};
+ constexpr String(size_t length, char* data) : length(length), data(data) {};
+ template constexpr String(const char(&data)[_len]) : length(_len - 1), data((char*)data) {};
+
+ char operator[](int index) {
+ if (index < 0) {
+ return 0;
+ }
+ if (index < length) {
+ return data[index];
+ }
+ return 0;
+ }
+};
+
+inline String operator""_str(const char* str, size_t length) {
+ return { length, (char*)str };
+}
+
+inline bool operator==(String a, String b) {
+ if (a.length != b.length)
+ return false;
+
+ if (a.data == b.data)
+ return true;
+
+ for (int i = 0; i < a.length; i++)
+ if (a[i] != b[i])
+ return false;
+
+ return true;
+}
+
+inline void advance(String& s, int num = 1) {
+ int to_advance = min(s.length, num);
+ s.data = s.data + to_advance;
+ s.length = s.length - to_advance;
+}
+
+inline bool starts_with(String s, String start) {
+ if (s.length < start.length) {
+ return false;
+ }
+ for (int i = 0; i < start.length; i++) {
+ if (s[i] != start[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+template
+inline T read(String& file) {
+ if (file.length < sizeof(T))
+ return {};
+ T value = *(T*)file.data;
+ advance(file, sizeof(T));
+ return value;
+}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 115d3cc..f25b161 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,3 +1,373 @@
-int main() {
+#define NOMINMAX
+#pragma comment(lib, "d3dcompiler.lib")
+#pragma comment(lib, "d3d11.lib")
+#pragma comment(lib, "dxguid.lib")
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "create_window.h"
+#include "log.h"
+#include "m_string.h"
+#include "math_graphics.h"
+#include "load_tga_file.h"
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+IDXGISwapChain* swap_chain;
+ID3D11Device* device;
+ID3D11DeviceContext* devicecontext;
+ID3D11DepthStencilState* depth_stencil_state;
+
+ID3D11RenderTargetView* render_target_view;
+
+ID3D11InputLayout* input_layout;
+ID3D11Buffer* vertex_buffer;
+ID3D11Buffer* index_buffer;
+ID3D11Buffer* instance_buffer;
+
+ID3DBlob* vertex_shader_code;
+ID3D11VertexShader* vertex_shader;
+
+ID3DBlob* pixel_shader_code;
+ID3D11PixelShader* pixel_shader;
+
+bool Running = true;
+
+BMP_Texture tex1 = load_tga_file("../assets/strawberry.tga");
+
+struct Vertex {
+ V4 pos;
+};
+
+Vertex vertices[] = {
+ {{ -1, 1, 1, 1 } },
+ {{ 1, -1, 1, 1 } },
+ {{ -1, -1, 1, 1 } },
+ {{ 1, 1, 1, 1 } },
+};
+
+uint16 indices[] = {
+ 0, 1, 2,
+ 0, 3, 1,
+};
+
+struct Instance {
+ V4 pos_size;
+ V4 left_color;
+ V4 right_color;
+};
+
+Instance instances[1] = {
+ {{0.1, 0.1, 0.2, 0.2}, {0, 1, 1, 1}, {1, 0, 1, 1}},
+};
+
+bool LoadShaders() {
+
+ ID3DBlob* error_msgs = 0;
+ HRESULT error_code = 0;
+
+ if (error_code = D3DCompileFromFile(L"../Assets/Shader/basic_vertex_shader.hlsl", 0, 0, "main", "vs_5_0", D3DCOMPILE_DEBUG | D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &vertex_shader_code, &error_msgs)) {
+ log("CompileFromFile has failed");
+ if (error_msgs)
+ log_error("%.*s", error_msgs->GetBufferSize(), error_msgs->GetBufferPointer());
+ return false;
+ }
+
+ if (device->CreateVertexShader(vertex_shader_code->GetBufferPointer(), vertex_shader_code->GetBufferSize(), 0, &vertex_shader)) {
+ log_error("CreateVertexShader has failed");
+ return false;
+ }
+
+ if (error_code = D3DCompileFromFile(L"../Assets/Shader/basic_pixel_shader.hlsl", 0, 0, "main", "ps_5_0", D3DCOMPILE_DEBUG | D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE_OPTIMIZATION_LEVEL0, 0, &pixel_shader_code, &error_msgs)) {
+ log("CompileFromFile has failed");
+ if (error_msgs)
+ log_error("%.*s", error_msgs->GetBufferSize(), error_msgs->GetBufferPointer());
+ return false;
+ }
+
+ if (device->CreatePixelShader(pixel_shader_code->GetBufferPointer(), pixel_shader_code->GetBufferSize(), 0, &pixel_shader)) {
+ log_error("CreatePixelShader has failed");
+ return false;
+ }
+
+ return true;
+}
+
+LRESULT WindowMsgs(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam) {
+ LRESULT Result = 0;
+
+ switch (Message) {
+ case WM_SIZE: {
+ if(swap_chain)
+ swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
+ printf("size\n");
+ } break;
+
+ case WM_DESTROY: {
+ PostQuitMessage(0);
+ printf("destroy\n");
+ } break;
+
+ case WM_CLOSE: {
+ Running = false;
+ printf("close\n");
+ } break;
+
+ case WM_ACTIVATEAPP: {
+ printf("app\n");
+ } break;
+
+
+ case WM_KEYDOWN: {
+ if (!(lParam & (1 << 30))) {
+ //key_down[wParam] = true;
+ }
+
+ if (wParam == VK_F5) {
+ //LoadShaders();
+ }
+ } break;
+
+ case WM_KEYUP: {
+ //key_down[wParam] = false;
+ } break;
+
+ default: {
+ Result = DefWindowProc(Window, Message, wParam, lParam);
+ } break;
+
+ }
+ return Result;
+}
+
+void DX11SetDebugName(ID3D11DeviceChild* child, String name) {
+#ifdef _DEBUG
+ if (child && name.data)
+ child->SetPrivateData(WKPDID_D3DDebugObjectName, name.length, name.data);
+#endif
+}
+
+ID3D11Buffer* CreateBuffer(String name, uint32 num_bytes, void* data = 0, uint32 BindFlags = D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE Usage = D3D11_USAGE_DEFAULT, uint32 CPUAccessFlags = 0, uint32 MiscFlags = 0, uint32 StructureByteStride = 0, uint32 SysMemPitch = 0, uint32 SysMemSlicePitch = 0) {
+ D3D11_BUFFER_DESC buffer_desc = {
+ .ByteWidth = num_bytes,
+ .Usage = Usage,
+ .BindFlags = BindFlags,
+ .CPUAccessFlags = CPUAccessFlags,
+ .MiscFlags = MiscFlags,
+ .StructureByteStride = StructureByteStride,
+ };
+
+ D3D11_SUBRESOURCE_DATA subresource_data = {
+ .pSysMem = data,
+ .SysMemPitch = SysMemPitch,
+ .SysMemSlicePitch = SysMemSlicePitch,
+ };
+
+ ID3D11Buffer* buffer;
+ if (device->CreateBuffer(&buffer_desc, &subresource_data, &buffer)) {
+ return 0;
+ }
+ DX11SetDebugName(buffer, name);
+
+ return buffer;
+}
+
+
+bool init_directx11(HWND Window) {
+ D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_0 };
+
+ DXGI_RATIONAL refresh_rate = {
+ .Numerator = 60,
+ .Denominator = 1,
+ };
+
+ DXGI_MODE_DESC buffer_desc = {
+ .Width = 0,
+ .Height = 0,
+ .RefreshRate = refresh_rate,
+ .Format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
+ .Scaling = DXGI_MODE_SCALING_UNSPECIFIED,
+ };
+
+ DXGI_SAMPLE_DESC sample_desc = {
+ .Count = 1,
+ .Quality = 0,
+ };
+
+ DXGI_SWAP_CHAIN_DESC swap_chain_desc = {
+ .BufferDesc = buffer_desc,
+ .SampleDesc = sample_desc,
+ .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
+ .BufferCount = 2,
+ .OutputWindow = Window,
+ .Windowed = TRUE,
+ .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
+ .Flags = 0,
+ };
+
+ if (D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_DEBUG, feature_levels, 1, D3D11_SDK_VERSION, &swap_chain_desc, &swap_chain, &device, 0, &devicecontext)) {
+ log_error("D3D11CreateDeviceAndSwapChain has failed.");
+ return 1;
+ }
+
+ ID3D11Texture2D* present_buffer;
+ if (swap_chain->GetBuffer(0, IID_PPV_ARGS(&present_buffer))) {
+ log_error("PresentBuffer getting failed");
+ return 1;
+ }
+
+
+ if (device->CreateRenderTargetView(present_buffer, 0, &render_target_view)) {
+ log_error("CreateRenderTargetView has failed");
+ return 1;
+ }
+
+ present_buffer->Release();
+
+ D3D11_DEPTH_STENCIL_DESC depth_stencil_desc = {
+ .DepthEnable = FALSE,
+ .DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL,
+ .DepthFunc = D3D11_COMPARISON_LESS,
+ .StencilEnable = FALSE,
+ .StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK,
+ .StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK,
+ .FrontFace = {
+ .StencilFunc = D3D11_COMPARISON_ALWAYS,
+ .StencilDepthFailOp = D3D11_STENCIL_OP_KEEP,
+ .StencilFailOp = D3D11_STENCIL_OP_KEEP,
+ .StencilPassOp = D3D11_STENCIL_OP_KEEP,
+ },
+ .BackFace = {
+ .StencilFunc = D3D11_COMPARISON_ALWAYS,
+ .StencilDepthFailOp = D3D11_STENCIL_OP_KEEP,
+ .StencilFailOp = D3D11_STENCIL_OP_KEEP,
+ .StencilPassOp = D3D11_STENCIL_OP_KEEP,
+ },
+ };
+
+
+ if (device->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state)) {
+ log_error("CreateDepthStencilState has failed.");
+ return 1;
+ }
+
+ if (!LoadShaders()) {
+ log_error("LoadShaders has failed");
+ return 1;
+ }
+ //device->CreateVertexShader()
+
+ D3D11_INPUT_ELEMENT_DESC input_element_desc[] = {
+ { "VERTEX_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "INSTANCE_POSITION_SIZE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "LEFT_COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ { "RIGHT_COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
+ };
+
+ if (device->CreateInputLayout(input_element_desc, sizeof(input_element_desc) / sizeof(*input_element_desc), vertex_shader_code->GetBufferPointer(), vertex_shader_code->GetBufferSize(), &input_layout)) {
+ log_error("CreateInputLayout has failed");
+ return 1;
+ }
+
+ RECT rect;
+ if (!GetClientRect(Window, &rect)) {
+ log_error("GetClientRect has failed.");
+ return 1;
+ }
+
+ D3D11_VIEWPORT viewport = {
+ .TopLeftX = 0,
+ .TopLeftY = 0,
+ .Width = (float)(rect.right),
+ .Height = (float)(rect.bottom),
+ .MinDepth = 0,
+ .MaxDepth = 1,
+ };
+ devicecontext->RSSetViewports(1, &viewport);
+
+ vertex_buffer = CreateBuffer("vertex_buffer", sizeof(vertices), vertices, D3D11_BIND_VERTEX_BUFFER);
+ index_buffer = CreateBuffer("index_buffer", sizeof(indices), indices, D3D11_BIND_INDEX_BUFFER);
+ instance_buffer = CreateBuffer("instance_buffer", sizeof(instances), instances, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
+
+ return 0;
+}
+
+int main() {
+ CoInitializeEx(0, COINIT_MULTITHREADED);
+
+ auto Window = (HWND)create_window(WindowMsgs);
+ if (!Window) {
+
+ printf("CreateWindow failed!\n");
+ return 1;
+ }
+
+ if (init_directx11(Window))
+ return 1;
+
+ MSG Message;
+ while (Running) {
+ while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
+
+ if (Message.message == WM_QUIT) {
+ Running = false;
+ }
+ TranslateMessage(&Message);
+ DispatchMessage(&Message);
+ }
+ devicecontext->OMSetRenderTargets(1, &render_target_view, 0);
+ V4 clear_color = { 0, 0, 0, 1 };
+ devicecontext->ClearRenderTargetView(render_target_view, clear_color.E);
+
+ //Quad rendern
+ D3D11_MAPPED_SUBRESOURCE mapped_subresource;
+ devicecontext->Map(instance_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_subresource);
+ memcpy(mapped_subresource.pData, instances, sizeof(instances));
+ devicecontext->Unmap(instance_buffer, 0);
+
+ devicecontext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ devicecontext->IASetInputLayout(input_layout);
+
+ ID3D11Buffer* input_buffers[] = {
+ vertex_buffer,
+ instance_buffer,
+ };
+
+ UINT input_strides[] = {
+ sizeof(Vertex),
+ sizeof(Instance),
+ };
+
+ UINT input_offsets[] = {
+ 0,
+ 0,
+ };
+
+ devicecontext->IASetVertexBuffers(0, sizeof(input_buffers) / sizeof(*input_buffers), input_buffers, input_strides, input_offsets);
+ devicecontext->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R16_UINT, 0);
+
+ devicecontext->IASetInputLayout(input_layout);
+ devicecontext->VSSetShader(vertex_shader, 0, 0);
+ devicecontext->PSSetShader(pixel_shader, 0, 0);
+ devicecontext->DrawIndexedInstanced(6, 1, 0, 0, 0);
+
+ //
+ swap_chain->Present(0, 0);
+ }
+ return 0;
}
\ No newline at end of file
diff --git a/src/math_graphics.h b/src/math_graphics.h
new file mode 100644
index 0000000..6c67dcf
--- /dev/null
+++ b/src/math_graphics.h
@@ -0,0 +1,704 @@
+#pragma once
+#define _CRT_SECURE_NO_WARNINGS
+
+
+#include
+#include
+#include
+#include
+#include
+
+#undef min
+#undef max
+
+//clamp
+constexpr inline float clamp(float min, float a, float max) {
+ float result = a;
+ if (a < min)
+ result = min;
+ if (a > max)
+ result = max;
+ return result;
+}
+
+//clamp für 0-1 Bereich (Grafik)
+constexpr inline float clamp01(float a) {
+ return clamp(0, a, 1);
+}
+
+
+//wurzelberechnung
+inline float square_root(float a) {
+ return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(a)));
+}
+
+inline float reciprocal_square_root(float a) {
+ return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(a)));
+}
+
+constexpr inline float min(float a, float b) {
+ return a < b ? a : b;
+}
+
+constexpr inline float max(float a, float b) {
+ return a > b ? a : b;
+}
+
+constexpr inline double min(double a, double b) {
+ return a < b ? a : b;
+}
+
+constexpr inline double max(double a, double b) {
+ return a > b ? a : b;
+}
+
+constexpr inline int64_t min(int64_t a, int64_t b) {
+ return a < b ? a : b;
+}
+
+template
+constexpr inline T min(T a, T b) {
+ return a < b ? a : b;
+}
+
+constexpr float lerp(float a, float t, float b) {
+ return (1.0f - t) * a + t * b;
+}
+
+
+//-----------------------------------------------
+//Vektorberechnung 2-dim
+union V2 {
+ struct {
+ float x;
+ float y;
+ };
+
+ struct {
+ float u;
+ float v;
+ };
+
+ struct {
+ float width;
+ float height;
+ };
+
+ struct {
+ float E[2];
+ };
+
+ float operator [](size_t index) {
+ assert(index < 2);
+ return E[index];
+ }
+};
+
+
+//Negation von 2-dim Vektor
+inline V2 operator -(V2 a) {
+ return {
+ -a.x,
+ -a.y
+ };
+}
+
+//Addition 2er 2-dim Vektoren
+inline V2 operator +(V2 a, V2 b) {
+ return {
+ a.x + b.x,
+ a.y + b.y
+ };
+}
+
+//Subtraktion 2er 2-dim Vektoren
+inline V2 operator -(V2 a, V2 b) {
+ return {
+ a.x - b.x,
+ a.y - b.y
+ };
+}
+
+//Skalarmultiplikation -> erst Skalar, dann Vektor
+inline V2 operator *(float a, V2 b) {
+ return {
+ a * b.x,
+ a * b.y
+ };
+
+}
+
+//Skalarmultiplikation -> erst Vektor, dann Skalar
+inline V2 operator *(V2 a, float b) {
+ return {
+ a.x * b,
+ a.y * b
+ };
+
+}
+
+//Division mit nem Skalar Oo -> Skalar geteilt durch Vektor
+inline V2 operator /(float a, V2 b) {
+ return {
+ a / b.x,
+ a / b.y
+ };
+}
+
+//Division mit nem Skalar Oo -> Vektor geteilt durch Skalar
+inline V2 operator /(V2 a, float b) {
+ return {
+ a.x / b,
+ a.y / b
+ };
+}
+
+//Skalarprodukt
+inline float dot(V2 a, V2 b) {
+ return a.x * b.x + a.y * b.y;
+}
+
+//Hadamard-Produkt
+inline V2 hadamard(V2 a, V2 b) {
+ return {
+ a.x * b.x,
+ a.y * b.y
+ };
+}
+
+//Betrag des Vektors quadrieren
+inline float length_squared(V2 a) {
+ return dot(a, a);
+}
+
+//Betrag eines Vektors
+inline float length(V2 a) {
+ return square_root(length_squared(a));
+}
+
+//Reziproke der Länge
+inline float reciprocal_length(V2 a) {
+ return reciprocal_square_root(length_squared(a));
+}
+
+//Einheitsvektor
+inline V2 normalize(V2 a) {
+ return a * reciprocal_length(a);
+}
+
+//Vektor der 90°
+inline V2 perp(V2 a) {
+ return {
+ -a.y,
+ a.x
+ };
+}
+
+//clamp für 2-dim Vektor
+inline V2 clamp01(V2 a) {
+ return {
+ clamp01(a.x),
+ clamp01(a.y)
+ };
+}
+
+inline V2 min(V2 a, V2 b) {
+ return {
+ min(a.x, b.x),
+ min(a.y, b.y),
+ };
+}
+
+inline V2 max(V2 a, V2 b) {
+ return {
+ max(a.x, b.x),
+ max(a.y, b.y),
+ };
+}
+
+inline float min(V2 a) {
+ return min(a.x, a.y);
+}
+
+inline float max(V2 a) {
+ return max(a.x, a.y);
+}
+
+
+//-----------------------------------------------
+//Vektorberechnung 3-dim
+union V3 {
+ struct {
+ float x;
+ float y;
+ float z;
+ };
+
+ //farbvektor
+ struct {
+ float r;
+ float g;
+ float b;
+ };
+
+ //texturvektor
+ struct {
+ float u;
+ float v;
+ float s;
+ };
+
+ //von V3 zu V2 ohne z
+ struct {
+ V2 xy;
+ float _z;
+ };
+
+ //von V3 zu V2 ohne x
+ struct {
+ float _x;
+ V2 yz;
+ };
+
+ struct {
+ float E[3];
+ };
+
+ float operator [](size_t index) {
+ assert(index < 3);
+ return E[index];
+ }
+};
+
+//Negation von 2-dim Vektor
+inline V3 operator -(V3 a) {
+ return {
+ -a.x,
+ -a.y,
+ -a.z
+ };
+}
+
+
+//Addition 2er 2-dim Vektoren
+inline V3 operator +(V3 a, V3 b) {
+ return {
+ a.x + b.x,
+ a.y + b.y,
+ a.z + b.z
+ };
+}
+
+//Subtraktion 2er 2-dim Vektoren
+inline V3 operator -(V3 a, V3 b) {
+ return {
+ a.x - b.x,
+ a.y - b.y,
+ a.z - b.z
+ };
+}
+
+//Skalarmultiplikation -> erst Skalar, dann Vektor
+inline V3 operator *(float a, V3 b) {
+ return {
+ a * b.x,
+ a * b.y,
+ a * b.z
+ };
+
+}
+
+//Skalarmultiplikation -> erst Vektor, dann Skalar
+inline V3 operator *(V3 a, float b) {
+ return {
+ a.x * b,
+ a.y * b,
+ a.z * b
+ };
+
+}
+
+//Division mit nem Skalar Oo -> Skalar geteilt durch Vektor
+inline V3 operator /(float a, V3 b) {
+ return {
+ a / b.x,
+ a / b.y,
+ a / b.z
+ };
+}
+
+//Division mit nem Skalar Oo -> Vektor geteilt durch Skalar
+inline V3 operator /(V3 a, float b) {
+ return {
+ a.x / b,
+ a.y / b,
+ a.z / b
+ };
+}
+
+//Skalarprodukt
+inline float dot(V3 a, V3 b) {
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+//Hadamard-Produkt
+inline V3 hadamard(V3 a, V3 b) {
+ return {
+ a.x * b.x,
+ a.y * b.y,
+ a.z * b.z
+ };
+}
+
+//Kreuzprodukt
+inline V3 cross(V3 a, V3 b) {
+ return {
+ a.y * b.z - a.z * b.y,
+ a.z * b.x - a.x * b.z,
+ a.x * b.y - a.y * b.x
+ };
+}
+
+//Betrag des Vektors quadrieren
+inline float length_squared(V3 a) {
+ return dot(a, a);
+}
+
+//Betrag eines Vektors
+inline float length(V3 a) {
+ return square_root(length_squared(a));
+}
+
+//Reziproke der Länge
+inline float reciprocal_length(V3 a) {
+ return reciprocal_square_root(length_squared(a));
+}
+
+//Einheitsvektor
+inline V3 normalize(V3 a) {
+ return a * reciprocal_length(a);
+}
+
+union V4 {
+ struct {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ //farbvektor
+ struct {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+
+ //texturvektor
+ struct {
+ float u;
+ float v;
+ float s;
+ float t;
+ };
+
+ //von V3 zu V2 ohne z
+ struct {
+ V2 xy;
+ V2 zw;
+ };
+
+ //von V3 zu V2 ohne x
+ struct {
+ float _x;
+ V2 yz;
+ float _w;
+ };
+
+ struct {
+ float E[4];
+ };
+
+ V4(V2 a, V2 b) { xy = a; zw = b; }
+ V4(float a, float b, float c, float d) { x = a; y = b; z = c; w = d; }
+ V4(float a, float b, float c) { x = a; y = b; z = c; w = 1; }
+ V4() {}
+
+ float operator [](size_t index) {
+ assert(index < 4);
+ return E[index];
+ }
+};
+
+
+//-----------------------------------------------
+//2x2 Matrix
+
+//M2x2 m;
+//m.E[0][1]
+//m.V[1]
+
+//m[1][0]
+union M2x2 {
+ struct {
+ float x1; float x2;
+ float y1; float y2;
+ };
+
+ struct {
+ float E[2][2];
+ };
+
+ struct {
+ V2 V[2];
+ };
+
+ V2 &operator [](size_t index) {
+ assert(index < 2);
+ return V[index];
+ }
+};
+
+//Matrix negieren
+inline M2x2 operator -(M2x2 a){
+ return {
+ -a[0][0], -a[0][1],
+ -a[1][0], -a[1][1]
+ };
+}
+
+//Matrix Addition
+inline M2x2 operator +(M2x2 a, M2x2 b) {
+ return {
+ a[0][0] + b[0][0], a[0][1] + b[0][1],
+ a[1][0] + b[1][0], a[1][1] + b[1][1]
+ };
+}
+
+//Matrix Subtraktion
+inline M2x2 operator -(M2x2 a, M2x2 b) {
+ return {
+ a[0][0] - b[0][0], a[0][1] - b[0][1],
+ a[1][0] - b[1][0], a[1][1] - b[1][1]
+ };
+}
+
+//Matrix Skalarmultiplikation
+inline M2x2 operator *(M2x2 a, float b) {
+ return {
+ a[0][0] * b, a[0][1] * b,
+ a[1][0] * b, a[1][1] * b
+ };
+}
+
+//Matrix Skalarmultiplikation
+inline M2x2 operator *(float a, M2x2 b) {
+ return {
+ a * b[0][0], a * b[0][1],
+ a * b[1][0], a * b[1][1]
+ };
+}
+
+//Matrix Multiplikation
+inline M2x2 operator *(M2x2 a, M2x2 b) {
+ return {
+ a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1],
+ a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]
+ };
+}
+
+//Matrix * Vektor
+inline V2 operator *(M2x2 a, V2 b) {
+ return {
+ a[0][0] * b[0] + a[0][1] * b[1],
+ a[1][0] * b[0] + a[1][1] * b[1],
+ };
+}
+
+//Matrix Transponieren
+inline M2x2 transpose(M2x2 a) {
+ return {
+ a[0][0], a[1][0],
+ a[0][1], a[1][1]
+ };
+}
+
+//Einheitsmatrix (oder Identitätsmatrix)
+constexpr inline M2x2 identityM2x2() {
+ return {
+ 1.0f, 0.0f,
+ 0.0f, 1.0f
+ };
+}
+
+
+//-----------------------------------------------
+//3x3 Matrix
+union M3x3 {
+ struct {
+ float x1; float x2; float x3;
+ float y1; float y2; float y3;
+ float z1; float z2; float z3;
+ };
+
+ struct {
+ float E[3][3];
+ };
+
+ struct {
+ V3 V[3];
+ };
+
+
+ V3& operator [](size_t index) {
+ assert(index < 3);
+ return V[index];
+ }
+
+};
+
+//Matrix negieren
+inline M3x3 operator -(M3x3 a) {
+ return {
+ -a[0][0], -a[0][1], -a[0][1],
+ -a[1][0], -a[1][1], -a[1][2],
+ -a[2][0], -a[2][1], -a[2][2]
+ };
+}
+
+//Matrix Addition
+inline M3x3 operator +(M3x3 a, M3x3 b) {
+ return {
+ a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2],
+ a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2],
+ a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2]
+ };
+}
+
+//Matrix Subtraktion
+inline M3x3 operator -(M3x3 a, M3x3 b) {
+ return {
+ a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2],
+ a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2],
+ a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2]
+ };
+}
+
+//Matrix Skalarmultiplikation
+inline M3x3 operator *(M3x3 a, float b) {
+ return {
+ a[0][0] * b, a[0][1] * b, a[0][2] * b,
+ a[1][0] * b, a[1][1] * b, a[1][2] * b,
+ a[2][0] * b, a[2][1] * b, a[2][2] * b
+ };
+}
+
+//Matrix Skalarmultiplikation
+inline M3x3 operator *(float a, M3x3 b) {
+ return {
+ a * b[0][0], a * b[0][1], a * b[0][2],
+ a * b[1][0], a * b[1][1], a * b[1][2],
+ a * b[2][0], a * b[2][1], a * b[2][2]
+ };
+}
+
+//Matrix Multiplikation
+inline M3x3 operator *(M3x3 a, M3x3 b) {
+ return {
+ a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0], a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1], a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2],
+ a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1], a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[0][2] * b[2][2],
+ a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0], a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1], a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[0][2] * b[2][2]
+ };
+}
+
+//Matrix * V2
+inline V2 operator *(M3x3 a, V2 b) {
+ return {
+ b.x * a[0][0] + b.y * a[0][1] + 1.0f * a[0][2],
+ b.x * a[1][0] + b.y * a[1][1] + 1.0f * a[1][2],
+ };
+}
+
+//Matrix * V3
+inline V3 operator *(M3x3 a, V3 b) {
+ return {
+ b.x * a[0][0] + b.y * a[0][1] + b.z * a[0][2],
+ b.x * a[1][0] + b.y * a[1][1] + b.z * a[1][2],
+ b.x * a[2][0] + b.y * a[2][1] + b.z * a[2][2]
+ };
+}
+
+
+//Matrix transponieren
+inline M3x3 transpose(M3x3 a) {
+ return {
+ a[0][0], a[1][0], a[2][0],
+ a[0][1], a[1][1], a[2][1],
+ a[0][2], a[1][2], a[2][2]
+ };
+}
+
+//Einheitsmatrix (oder Identitätsmatrix)
+inline M3x3 identityM3x3() {
+ return {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ };
+}
+
+
+
+//-----------------------------------------------
+//m128i
+struct m128i {
+ __m128i val;
+};
+
+inline __m128i operator &(m128i a, m128i b) {
+ return _mm_and_si128(a.val, b.val);
+}
+
+inline __m128i operator |(m128i a, m128i b) {
+ return _mm_or_si128(a.val, b.val);
+}
+
+inline __m128i operator >>(m128i a, int b) {
+ return _mm_srli_epi32(a.val, b);
+}
+
+inline __m128i operator <<(m128i a, int b) {
+ return _mm_slli_epi32(a.val, b);
+}
+
+
+//-----------------------------------------------
+//m128
+struct m128 {
+ __m128 val;
+};
+
+inline __m128 operator +(m128 a, m128 b) {
+ return _mm_mul_ps(a.val, b.val);
+}
+
+inline __m128 operator *(m128 a, m128 b) {
+ return _mm_mul_ps(a.val, b.val);
+}
+
+inline __m128 operator *(float a, m128 b) {
+ return _mm_mul_ps(_mm_set1_ps(a), b.val);
+}
+
+inline __m128 square_root(__m128 a) {
+ return _mm_sqrt_ps(a);
+}
+
+inline __m128 operator /(m128 a, m128 b) {
+ return _mm_div_ps(a.val, b.val);
+}
+
+inline __m128 lerp(__m128 a, float t, float b) {
+ return (1.0f - t) * a + (t * b);
+}
\ No newline at end of file