Skip to content

Instantly share code, notes, and snippets.

@chromedays
Last active June 19, 2019 03:27
Show Gist options
  • Save chromedays/93b310087bdb67a298940f213cf03675 to your computer and use it in GitHub Desktop.
Save chromedays/93b310087bdb67a298940f213cf03675 to your computer and use it in GitHub Desktop.
뭔가 directx (5시간 걸림)
struct VertexIn
{
float3 pos : POSITION;
float4 color : COLOR;
float3 normal : TEXCOORD;
};
struct VertexOut
{
float4 pos : SV_POSITION;
float4 color : COLOR;
float3 normal : TEXCOORD0;
float3 world_pos : TEXCOORD1;
};
#include "default.hlsli"
float4 main(VertexOut i) : SV_Target
{
return i.color;
}
#include "default.hlsli"
VertexOut main(VertexIn i)
{
VertexOut o;
#if 0
o.pos = mul(float4(i.pos, 1.f), g_mvp);
o.color = i.color;
o.normal = normalize(mul(float4(i.normal, 0.f), g_invt_model).xyz);
o.world_pos = mul(float4(i.pos, 1.f), g_model).xyz;
#endif
o.pos = float4(i.pos, 1.f);
o.color = i.color;
o.normal = float3(0.f, 0.f, 0.f);
o.world_pos = float3(0.f, 0.f, 0.f);
return o;
}
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <SDL.h>
#include <SDL_syswm.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <algorithm>
#include <type_traits>
#include <assert.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#ifdef _WIN32
#define PLATFORM_WINDOWS
#endif
#define ASSERT(expression) \
do \
{ \
assert((expression)); \
} while (0)
using uint = unsigned int;
template<typename Fn>
struct ScopeGuard
{
Fn func;
bool active;
ScopeGuard(const Fn& func) : func(func), active(true)
{
}
ScopeGuard(Fn&& func) : func(std::move(func)), active(true)
{
}
ScopeGuard(ScopeGuard&& other)
: func(std::move(other.func)), active(other.active)
{
other.active = false;
}
~ScopeGuard()
{
if (active)
func();
}
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
};
#define DO_STRING_JOIN(a, b) a##b
#define STRING_JOIN(a, b) DO_STRING_JOIN(a, b)
#define SCOPE_EXIT(code) \
ScopeGuard STRING_JOIN(scope_guard_, __LINE__)([&]() { code; })
using Size = ptrdiff_t;
struct StringView
{
using Char = char;
const Char* buf;
Size len;
};
StringView string_view(const StringView::Char* c_str)
{
StringView result = {.buf = c_str, .len = (Size)strlen(c_str)};
return result;
}
struct String
{
using Char = char;
const Char* buf;
Size len;
};
String string_create(const String::Char* c_str)
{
Size len = (Size)strlen(c_str);
Size buf_size = (len + 1) * sizeof(String::Char);
String::Char* buf = (String::Char*)malloc(buf_size);
memcpy_s(buf, buf_size, c_str, buf_size);
String result = {.buf = buf, .len = len};
return result;
}
String string_create(const String::Char* a, const String::Char* b)
{
Size new_len = (Size)strlen(a) + (Size)strlen(b);
Size new_buf_size = (new_len + 1) * sizeof(String::Char);
String::Char* new_buf = (String::Char*)malloc(new_buf_size);
strcpy_s(new_buf, new_buf_size, a);
strcpy_s(new_buf + strlen(a),
new_buf_size - strlen(a) * sizeof(String::Char), b);
new_buf[new_buf_size - 1] = '\0';
String result = {.buf = new_buf, .len = new_len};
return result;
}
void string_destroy(String* str)
{
if (str->buf)
free(const_cast<String::Char*>(str->buf));
}
String operator+(String str, const String::Char* buf)
{
Size new_len = str.len + (Size)strlen(buf);
Size new_buf_size = (new_len + 1) * sizeof(String::Char);
String::Char* new_buf = (String::Char*)malloc(new_buf_size);
strcpy_s(new_buf, new_buf_size, str.buf);
strcpy_s(new_buf + str.len, new_buf_size - (str.len * sizeof(String::Char)),
buf);
new_buf[new_buf_size - 1] = '\0';
String result = {.buf = new_buf, .len = new_len};
return result;
}
String& operator+=(String& str, const String::Char* buf)
{
String temp = str;
str = str + buf;
string_destroy(&temp);
return str;
}
template<typename T>
bool is_in_range_inclusive(T value, T min, T max)
{
static_assert(std::is_arithmetic_v<T>, "T is not arithmetic type!");
bool result = (value >= min) && (value <= max);
return result;
}
template<typename T>
bool is_in_range_exclusive(T value, T min, T max)
{
static_assert(std::is_arithmetic_v<T>, "T is not arithmetic type!");
bool result = (value >= min) && (value < max);
return result;
}
template<typename T>
inline constexpr bool is_pod_v =
std::is_trivial_v<T>&& std::is_standard_layout_v<T>;
template<typename T>
struct Span
{
T* buf;
Size size;
T& operator[](Size index)
{
ASSERT(is_in_range_exclusive<Size>(index, 0, size));
return buf[index];
}
const T& operator[](Size index) const
{
ASSERT(is_in_range_exclusive<Size>(index, 0, size));
return buf[index];
}
T* begin()
{
return buf;
}
T* end()
{
return buf + size;
}
const T* begin() const
{
return buf;
}
const T* end() const
{
return buf + size;
}
};
static_assert(is_pod_v<Span<int>>);
template<typename T, Size N>
Span<T> span(T (&arr)[N])
{
Span result = {.buf = arr, .size = (Size)std::size(arr)};
return result;
}
template<typename T>
struct Array
{
static_assert(is_pod_v<T>);
T* buf;
Size cap;
Size size;
operator Span<T>()
{
Span<T> result = {.buf = buf, .size = size};
return result;
}
T& operator[](Size index)
{
ASSERT(is_in_range_exclusive<Size>(index, 0, size));
return buf[index];
}
const T& operator[](Size index) const
{
ASSERT(is_in_range_exclusive<Size>(index, 0, size));
return buf[index];
}
T* begin()
{
return buf;
}
T* end()
{
return buf + size;
}
const T* begin() const
{
return buf;
}
const T* end() const
{
return buf + size;
}
};
static_assert(is_pod_v<Array<int>>);
template<typename T>
Array<T> array_create(Size size = 0)
{
Array<T> result = {};
if (size > 0)
{
result.buf = (T*)malloc(size * sizeof(T));
result.cap = size;
result.size = size;
}
return result;
}
template<typename T>
Size array_size_bytes(const Array<T>* arr);
template<typename T>
Array<T> array_create(std::initializer_list<T> init_list)
{
Array<T> result = array_create<T>((Size)init_list.size());
errno_t err = memcpy_s(result.buf, array_size_bytes(&result),
init_list.begin(), init_list.size() * sizeof(T));
ASSERT(err == 0);
return result;
}
template<typename T>
void array_destroy(Array<T>* arr)
{
if (arr->buf)
free(arr->buf);
}
template<typename T>
Size array_size_bytes(const Array<T>* arr)
{
Size result = arr->size * sizeof(T);
return result;
}
struct IntVector2
{
int x;
int y;
};
struct Vector3
{
float x;
float y;
float z;
};
Vector3 operator+(Vector3 a, Vector3 b)
{
Vector3 result = {.x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z};
return result;
}
Vector3 operator-(Vector3 a, Vector3 b)
{
Vector3 result = {.x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z};
return result;
}
Vector3 operator*(Vector3 a, Vector3 b)
{
Vector3 result = {.x = a.x * b.x, .y = a.y * b.y, .z = a.z * b.z};
return result;
}
Vector3 operator/(Vector3 a, Vector3 b)
{
Vector3 result = {.x = a.x / b.x, .y = a.y / b.y, .z = a.z / b.z};
return result;
}
Vector3 operator/(Vector3 v, float s)
{
Vector3 result = {.x = v.x / s, .y = v.y / s, .z = v.z / s};
return result;
}
Vector3& operator+=(Vector3& a, Vector3 b)
{
a = a + b;
return a;
}
Vector3& operator-=(Vector3& a, Vector3 b)
{
a = a - b;
return a;
}
Vector3& operator*=(Vector3& a, Vector3 b)
{
a = a * b;
return a;
}
Vector3& operator/=(Vector3& a, Vector3 b)
{
a = a / b;
return a;
}
Vector3& operator/=(Vector3& v, float s)
{
v = v / s;
return v;
}
Vector3 cross(Vector3 a, Vector3 b)
{
Vector3 result = {.x = a.y * b.z - a.z * b.y,
.y = a.z * b.x - a.x * b.z,
.z = a.x * b.y - a.y * b.x};
return result;
}
float dot(Vector3 a, Vector3 b)
{
float result = a.x * b.x + a.y * b.y + a.z * b.z;
return result;
}
float length_squared(Vector3 v)
{
float result = dot(v, v);
return result;
}
float length(Vector3 v)
{
float result = sqrtf(length_squared(v));
return result;
}
Vector3 normalize(Vector3 v)
{
Vector3 result = v / length(v);
return result;
}
struct Vector4
{
float x;
float y;
float z;
float w;
};
struct Matrix
{
float e[4][4];
};
struct Vertex
{
Vector3 pos;
Vector4 color;
Vector3 normal;
};
namespace color
{
constexpr Vector4 white{1.f, 1.f, 1.f, 1.f};
constexpr Vector4 black{0.f, 0.f, 0.f, 1.f};
constexpr Vector4 red{1.f, 0.f, 0.f, 1.f};
constexpr Vector4 green{0.f, 1.f, 0.f, 1.f};
constexpr Vector4 blue{0.f, 0.f, 1.f, 1.f};
constexpr Vector4 yellow{1.f, 1.f, 0.f, 1.f};
constexpr Vector4 cyan{0.f, 1.f, 1.f, 1.f};
constexpr Vector4 magenta{1.f, 0.f, 1.f, 1.f};
}
struct Mesh
{
Array<Vertex> vertices;
Array<uint> indices;
};
void mesh_destroy(Mesh* mesh)
{
array_destroy(&mesh->vertices);
array_destroy(&mesh->indices);
}
void set_average_interpolated_normals(Span<Vertex> vertices, Span<uint> indices)
{
for (Vertex& v : vertices)
v.normal = {};
for (int i = 0; i < indices.size / 3; ++i)
{
uint i0 = indices[i * 3 + 0];
uint i1 = indices[i * 3 + 1];
uint i2 = indices[i * 3 + 2];
Vector3 v0 = vertices[i0].pos;
Vector3 v1 = vertices[i1].pos;
Vector3 v2 = vertices[i2].pos;
Vector3 e0 = v1 - v0;
Vector3 e1 = v2 - v0;
Vector3 n = cross(e0, e1);
vertices[i0].normal += n;
vertices[i0].normal += n;
vertices[i0].normal += n;
}
for (Vertex& v : vertices)
v.normal = normalize(v.normal);
}
Mesh create_triangle_mesh()
{
Mesh result = {.vertices =
array_create<Vertex>({{{-0.5f, -0.5f, 0.f}, color::red},
{{0.5f, -0.5f, 0.f}, color::red},
{{0.f, 0.5f, 0.f}, color::red}}),
.indices = array_create<uint>({0, 1, 2})};
set_average_interpolated_normals(result.vertices, result.indices);
return result;
}
struct Camera
{
Vector3 eye;
float yaw;
float pitch;
};
struct NativeHandle
{
uint64_t value;
};
Array<uint8_t> read_binary_file(const char* filename);
namespace d3d
{
struct Context
{
ID3D11Device* device;
ID3D11DeviceContext* device_context;
IDXGISwapChain* swap_chain;
ID3D11RenderTargetView* render_target_view;
ID3D11Texture2D* depth_stencil_buffer;
ID3D11DepthStencilView* depth_stencil_view;
D3D_FEATURE_LEVEL feature_level;
uint msaa4x_quality;
ID3D11InputLayout* input_layout;
};
template<typename T, typename U>
long query_interface(T* ptr, U** out)
{
return ptr->QueryInterface(__uuidof(U), (void**)out);
}
Context context_create(NativeHandle window, IntVector2 window_size)
{
ASSERT(window_size.x > 0 && window_size.y > 0);
HWND hwnd = *(HWND*)&window;
Context result = {};
// Create device and device context
{
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
D3D11_CREATE_DEVICE_DEBUG, nullptr, 0,
D3D11_SDK_VERSION, &result.device,
&result.feature_level, &result.device_context);
// TODO: handle the case when msaa4x_quality receives zero
result.device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM,
5, &result.msaa4x_quality);
}
// Create swap chain
{
DXGI_SWAP_CHAIN_DESC desc = {
.BufferDesc =
{
.Width = (UINT)window_size.x,
.Height = (UINT)window_size.y,
.RefreshRate = {.Numerator = 60, .Denominator = 1},
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
.Scaling = DXGI_MODE_SCALING_UNSPECIFIED,
},
.SampleDesc =
{
.Count = 4,
.Quality = result.msaa4x_quality - 1,
},
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
.BufferCount = 1,
.OutputWindow = hwnd,
.Windowed = true,
.SwapEffect = DXGI_SWAP_EFFECT_DISCARD,
.Flags = 0};
IDXGIDevice* dxgi_device;
IDXGIAdapter* dxgi_adapter;
IDXGIFactory* dxgi_factory;
query_interface(result.device, &dxgi_device);
dxgi_device->GetAdapter(&dxgi_adapter);
dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory));
dxgi_factory->CreateSwapChain(result.device, &desc, &result.swap_chain);
dxgi_factory->Release();
dxgi_adapter->Release();
dxgi_device->Release();
}
// Create render target view
{
ID3D11Texture2D* back_buffer;
result.swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer));
result.device->CreateRenderTargetView(back_buffer, nullptr,
&result.render_target_view);
back_buffer->Release();
}
// Create depth/stencil buffer
{
D3D11_TEXTURE2D_DESC desc = {
.Width = (UINT)window_size.x,
.Height = (UINT)window_size.y,
.MipLevels = 1,
.ArraySize = 1,
.Format = DXGI_FORMAT_D24_UNORM_S8_UINT,
.SampleDesc = {.Count = 4, .Quality = result.msaa4x_quality - 1},
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_DEPTH_STENCIL,
.CPUAccessFlags = 0,
.MiscFlags = 0,
};
result.device->CreateTexture2D(&desc, nullptr,
&result.depth_stencil_buffer);
result.device->CreateDepthStencilView(
result.depth_stencil_buffer, nullptr, &result.depth_stencil_view);
}
// Bind views to output merger
result.device_context->OMSetRenderTargets(1, &result.render_target_view,
result.depth_stencil_view);
// Create input layout
{
constexpr D3D11_INPUT_ELEMENT_DESC vertex_layout[3] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,
offsetof(Vertex, pos), D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
offsetof(Vertex, color), D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,
offsetof(Vertex, normal), D3D11_INPUT_PER_VERTEX_DATA, 0}};
StringView dummy_hlsl_source = string_view(R"(
struct VertexIn
{
float3 pos : POSITION;
float4 color : COLOR;
float3 normal : TEXCOORD;
};
float4 main(VertexIn i) : SV_POSITION
{
return float4(0.f, 0.f, 0.f, 0.f);
}
)");
D3D_SHADER_MACRO macros[] = {{}};
ID3DBlob* bytecode;
D3DCompile(dummy_hlsl_source.buf, dummy_hlsl_source.len, nullptr,
macros, nullptr, "main", "vs_5_0", 0, 0, &bytecode, nullptr);
result.device->CreateInputLayout(
vertex_layout, (UINT)std::size(vertex_layout),
bytecode->GetBufferPointer(), bytecode->GetBufferSize(),
&result.input_layout);
bytecode->Release();
}
return result;
}
void context_destroy(Context* context)
{
context->device->Release();
context->device_context->Release();
context->swap_chain->Release();
context->render_target_view->Release();
context->depth_stencil_buffer->Release();
context->depth_stencil_view->Release();
context->input_layout->Release();
}
struct Renderable
{
const Mesh* mesh;
ID3D11Buffer* vb;
ID3D11Buffer* ib;
};
Renderable renderable_create(const Mesh* mesh, const Context* d3d)
{
ASSERT(mesh->vertices.size > 0 && mesh->indices.size > 0);
ID3D11Buffer* vb;
D3D11_BUFFER_DESC vb_desc = {.ByteWidth =
(UINT)array_size_bytes(&mesh->vertices),
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_VERTEX_BUFFER,
.CPUAccessFlags = 0,
.MiscFlags = 0,
.StructureByteStride = 0};
D3D11_SUBRESOURCE_DATA vb_init_data = {.pSysMem = mesh->vertices.buf};
d3d->device->CreateBuffer(&vb_desc, &vb_init_data, &vb);
ID3D11Buffer* ib;
D3D11_BUFFER_DESC ib_desc = {.ByteWidth =
(UINT)array_size_bytes(&mesh->indices),
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = D3D11_BIND_INDEX_BUFFER,
.CPUAccessFlags = 0,
.MiscFlags = 0,
.StructureByteStride = 0};
D3D11_SUBRESOURCE_DATA ib_init_data = {.pSysMem = mesh->indices.buf};
d3d->device->CreateBuffer(&ib_desc, &ib_init_data, &ib);
Renderable result = {.mesh = mesh, .vb = vb, .ib = ib};
return result;
}
void renderable_destroy(Renderable* renderable)
{
renderable->vb->Release();
renderable->ib->Release();
}
struct Shader
{
ID3D11VertexShader* vs;
ID3D11PixelShader* ps;
};
Shader shader_create(const char* base_dir_path,
const char* shader_name,
Context* d3d)
{
String shader_path_without_suffix =
string_create(base_dir_path, shader_name);
String vs_path = shader_path_without_suffix + "_v.cso";
String ps_path = shader_path_without_suffix + "_p.cso";
Array<uint8_t> vs_source = read_binary_file(vs_path.buf);
Array<uint8_t> ps_source = read_binary_file(ps_path.buf);
SCOPE_EXIT({
array_destroy(&ps_source);
array_destroy(&vs_source);
string_destroy(&ps_path);
string_destroy(&vs_path);
string_destroy(&shader_path_without_suffix);
});
ID3D11VertexShader* vs;
d3d->device->CreateVertexShader(vs_source.buf, vs_source.size, nullptr,
&vs);
ID3D11PixelShader* ps;
d3d->device->CreatePixelShader(ps_source.buf, ps_source.size, nullptr, &ps);
Shader result = {.vs = vs, .ps = ps};
return result;
}
void shader_destroy(Shader* shader)
{
shader->vs->Release();
shader->ps->Release();
}
}
struct App
{
IntVector2 window_size;
SDL_Window* window_handle;
};
App app_create(const char* window_title, IntVector2 window_size)
{
SDL_Init(SDL_INIT_VIDEO);
App result = {.window_size = window_size,
.window_handle = SDL_CreateWindow(
window_title, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, 0)};
return result;
}
void app_destroy(App* app)
{
SDL_DestroyWindow(app->window_handle);
SDL_Quit();
}
NativeHandle get_native_window_handle(const App* app)
{
NativeHandle result{};
#if defined(PLATFORM_WINDOWS)
static_assert((sizeof(decltype(SDL_SysWMinfo::info.win.window)) <=
sizeof(NativeHandle)));
SDL_SysWMinfo wminfo{};
SDL_VERSION(&wminfo.version);
SDL_GetWindowWMInfo(app->window_handle, &wminfo);
memcpy(&result, &wminfo.info.win.window, sizeof(wminfo.info.win.window));
#else
#error This platform is not supported
#endif
return result;
}
StringView get_exe_dir_path()
{
return string_view(SDL_GetBasePath());
}
struct Timer
{
int64_t frequency;
int64_t counter;
};
int64_t get_current_perf_counter()
{
LARGE_INTEGER curr_counter{};
QueryPerformanceCounter(&curr_counter);
return curr_counter.QuadPart;
}
int64_t get_perf_frequency()
{
LARGE_INTEGER freq{};
QueryPerformanceFrequency(&freq);
return freq.QuadPart;
}
Timer timer()
{
Timer result = {.frequency = get_perf_frequency(),
.counter = get_current_perf_counter()};
return result;
}
void reset(Timer* timer)
{
timer->counter = get_current_perf_counter();
}
float get_elapsed_seconds(const Timer* timer)
{
int64_t curr_counter = get_current_perf_counter();
float result =
(float)(curr_counter - timer->counter) / (float)timer->frequency;
return result;
}
Array<uint8_t> read_binary_file(const char* filename)
{
HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, 0, nullptr);
ASSERT(file != INVALID_HANDLE_VALUE);
LARGE_INTEGER file_size = {};
GetFileSizeEx(file, &file_size);
Array<uint8_t> result = array_create<uint8_t>((Size)file_size.QuadPart);
DWORD bytes_read = 0;
ReadFile(file, result.buf, (DWORD)file_size.QuadPart, &bytes_read, nullptr);
ASSERT(file_size.QuadPart == bytes_read);
return result;
}
void process_os_event(bool* running)
{
SDL_Event e = {};
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
*running = false;
else
{
}
}
}
void run()
{
using namespace d3d;
App app = app_create("DemoEngine", {1280, 720});
SCOPE_EXIT(app_destroy(&app));
Context d3d =
context_create(get_native_window_handle(&app), app.window_size);
SCOPE_EXIT(d3d::context_destroy(&d3d));
Mesh triangle_mesh = create_triangle_mesh();
SCOPE_EXIT(mesh_destroy(&triangle_mesh));
Renderable triangle = renderable_create(&triangle_mesh, &d3d);
SCOPE_EXIT(renderable_destroy(&triangle));
StringView base_path = get_exe_dir_path();
Shader default_shader = shader_create(base_path.buf, "default", &d3d);
SCOPE_EXIT(shader_destroy(&default_shader));
ID3D11RasterizerState* rs;
{
D3D11_RASTERIZER_DESC desc = {.FillMode = D3D11_FILL_SOLID,
.CullMode = D3D11_CULL_BACK,
.FrontCounterClockwise = true,
.DepthBias = 0,
.DepthBiasClamp = 0.f,
.SlopeScaledDepthBias = 0.f,
.DepthClipEnable = true,
.ScissorEnable = false,
.MultisampleEnable = true,
.AntialiasedLineEnable = true};
d3d.device->CreateRasterizerState(&desc, &rs);
}
SCOPE_EXIT(rs->Release());
Timer tm = timer();
bool running = true;
while (running)
{
float dt = get_elapsed_seconds(&tm);
reset(&tm);
process_os_event(&running);
// Begin render
{
D3D11_VIEWPORT vp = {.TopLeftX = 0.f,
.TopLeftY = 0.f,
.Width = (float)app.window_size.x,
.Height = (float)app.window_size.y,
.MinDepth = 0.f,
.MaxDepth = 1.f};
d3d.device_context->RSSetViewports(1, &vp);
FLOAT clear_color[] = {1.f, 0.7f, 1.f, 1.f};
d3d.device_context->ClearRenderTargetView(d3d.render_target_view,
clear_color);
d3d.device_context->ClearDepthStencilView(
d3d.depth_stencil_view, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,
1.f, 0);
d3d.device_context->IASetInputLayout(d3d.input_layout);
}
d3d.device_context->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3d.device_context->RSSetState(rs);
d3d.device_context->VSSetShader(default_shader.vs, nullptr, 0);
d3d.device_context->PSSetShader(default_shader.ps, nullptr, 0);
UINT stride = sizeof(Vertex);
UINT offset = 0;
d3d.device_context->IASetVertexBuffers(0, 1, &triangle.vb, &stride,
&offset);
d3d.device_context->IASetIndexBuffer(triangle.ib, DXGI_FORMAT_R32_UINT,
0);
d3d.device_context->DrawIndexed((UINT)triangle.mesh->indices.size, 0,
0);
d3d.swap_chain->Present(1, 0);
}
}
int main(int, char**)
{
run();
_CrtDumpMemoryLeaks();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment