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