Skip to content

Instantly share code, notes, and snippets.

@Gargaj
Last active January 24, 2025 20:22
Show Gist options
  • Save Gargaj/7d06bf237deb768cb8929faa97c8761c to your computer and use it in GitHub Desktop.
Save Gargaj/7d06bf237deb768cb8929faa97c8761c to your computer and use it in GitHub Desktop.
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")
#define CGLTF_IMPLEMENTATION
#include "cgltf.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include "ccVector.h"
bool gWindowWantsToQuit = false;
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
case WM_KEYDOWN:
{
switch ( wParam )
{
case VK_ESCAPE:
{
gWindowWantsToQuit = true;
} break;
}
} break;
case WM_SYSCOMMAND:
{
switch ( wParam )
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
{
return 0;
}
}
} break;
case WM_CLOSE:
{
gWindowWantsToQuit = true;
} break;
}
return DefWindowProcA( hWnd, uMsg, wParam, lParam );
}
int main()
{
const char * windowClassName = "DemosForDummiesWindowClass";
WNDCLASSA windowClass;
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
windowClass.lpfnWndProc = &WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = GetModuleHandle( nullptr );
windowClass.hIcon = nullptr;
windowClass.hCursor = LoadCursor( nullptr, IDC_ARROW );
windowClass.hbrBackground = nullptr;
windowClass.lpszMenuName = nullptr;
windowClass.lpszClassName = windowClassName;
if ( !RegisterClassA( &windowClass ) )
{
return 1;
}
const int width = 1280;
const int height = 720;
DWORD exStyle = WS_EX_APPWINDOW;
DWORD style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
RECT windowRect = { 0, 0, width, height };
AdjustWindowRectEx( &windowRect, style, FALSE, exStyle );
HWND hWnd = CreateWindowExA( exStyle, windowClassName, "Demos For Dummies", style,
0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
nullptr, nullptr, windowClass.hInstance, nullptr );
if ( !hWnd )
{
return 1;
}
//////////////////////////////////////////////////////////////////////////
DXGI_SWAP_CHAIN_DESC desc = { 0 };
desc.BufferCount = 2;
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.OutputWindow = hWnd;
desc.SampleDesc.Count = 1;
desc.Windowed = true;
ID3D11Device * device = nullptr;
ID3D11DeviceContext * context = nullptr;
IDXGISwapChain * swapChain = nullptr;
if ( D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &desc, &swapChain, &device, nullptr, &context ) != S_OK )
{
return 1;
}
ID3D11Texture2D * backBuffer = nullptr;
ID3D11RenderTargetView * backBufferView = nullptr;
swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void **)&backBuffer );
device->CreateRenderTargetView( backBuffer, nullptr, &backBufferView );
D3D11_TEXTURE2D_DESC depthDesc = CD3D11_TEXTURE2D_DESC( DXGI_FORMAT_R24G8_TYPELESS, width, height, 1, 1, D3D11_BIND_DEPTH_STENCIL );
ID3D11Texture2D * depthStencil = nullptr;
if ( device->CreateTexture2D( &depthDesc, nullptr, &depthStencil ) != S_OK )
{
return 1;
}
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV = CD3D11_DEPTH_STENCIL_VIEW_DESC( D3D11_DSV_DIMENSION_TEXTURE2D, DXGI_FORMAT_D24_UNORM_S8_UINT );
ID3D11DepthStencilView * depthStencilView = nullptr;
if ( device->CreateDepthStencilView( depthStencil, &descDSV, &depthStencilView ) != S_OK )
{
return false;
}
CD3D11_RASTERIZER_DESC rasterizerDesc = CD3D11_RASTERIZER_DESC( CD3D11_DEFAULT() );
rasterizerDesc.FrontCounterClockwise = true;
ID3D11RasterizerState * rasterizerState = nullptr;
device->CreateRasterizerState( &rasterizerDesc, &rasterizerState );
//////////////////////////////////////////////////////////////////////////
cgltf_options gltfOptions = { 0 };
cgltf_data * meshData = nullptr;
const char * meshFilename = "mesh.glb";
if ( cgltf_parse_file( &gltfOptions, meshFilename, &meshData ) != cgltf_result_success )
{
return 1;
}
if ( cgltf_load_buffers( &gltfOptions, meshData, meshFilename ) != cgltf_result_success )
{
return 1;
}
cgltf_primitive & primitive = meshData->meshes[ 0 ].primitives[ 0 ];
D3D11_BUFFER_DESC bufferDesc = CD3D11_BUFFER_DESC( (UINT)primitive.attributes[ 0 ].data->buffer_view->size, D3D11_BIND_VERTEX_BUFFER );
D3D11_SUBRESOURCE_DATA subData = { 0 };
subData.pSysMem = (char *)primitive.attributes[ 0 ].data->buffer_view->buffer->data + primitive.attributes[ 0 ].data->buffer_view->offset;
ID3D11Buffer * vertexBuffer = nullptr;
if ( device->CreateBuffer( &bufferDesc, &subData, &vertexBuffer ) != S_OK )
{
return 1;
}
D3D11_BUFFER_DESC ibBufferDesc = CD3D11_BUFFER_DESC( (UINT)primitive.indices->buffer_view->size, D3D11_BIND_INDEX_BUFFER );
D3D11_SUBRESOURCE_DATA ibSubData = { 0 };
ibSubData.pSysMem = (char *)primitive.indices->buffer_view->buffer->data + primitive.indices->buffer_view->offset;
ID3D11Buffer * indexBuffer = nullptr;
if ( device->CreateBuffer( &ibBufferDesc, &ibSubData, &indexBuffer ) != S_OK )
{
return 1;
}
//////////////////////////////////////////////////////////////////////////
int x = 0, y = 0, n = 0;
unsigned char * textureData = stbi_load( "texture.png", &x, &y, &n, 4 );
if ( !textureData )
{
return 1;
}
D3D11_TEXTURE2D_DESC tex2DDesc = CD3D11_TEXTURE2D_DESC( DXGI_FORMAT_R8G8B8A8_UNORM, x, y, 1, 1, D3D11_BIND_SHADER_RESOURCE );
D3D11_SUBRESOURCE_DATA texSubData = { 0 };
texSubData.pSysMem = textureData;
texSubData.SysMemPitch = x * 4 * sizeof( char );
ID3D11Texture2D * texture = nullptr;
if ( device->CreateTexture2D( &tex2DDesc, &texSubData, &texture ) != S_OK )
{
return 1;
}
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC( D3D11_SRV_DIMENSION_TEXTURE2D, tex2DDesc.Format, 0, 1 );
ID3D11ShaderResourceView * textureSRV = nullptr;
if ( device->CreateShaderResourceView( texture, &srvDesc, &textureSRV ) != S_OK )
{
return 1;
}
stbi_image_free( textureData );
//////////////////////////////////////////////////////////////////////////
char shaderSource[] =
"cbuffer c { float4x4 projectionMatrix; float4x4 worldMatrix; };\n"
"struct VS_INPUT { float3 Pos : POSITION; };\n"
"struct VS_OUTPUT { float4 Pos : SV_POSITION; float2 TexCoord : TEXCOORD0; };\n"
"\n"
"VS_OUTPUT vs_main( VS_INPUT In )\n"
"{\n"
" VS_OUTPUT Out;\n"
" Out.Pos = float4( In.Pos, 1.0 );\n"
" Out.Pos = mul(worldMatrix, Out.Pos);\n"
" Out.Pos = mul(projectionMatrix, Out.Pos);\n"
" Out.TexCoord = In.Pos.xy + In.Pos.z;\n"
" return Out;\n"
"}\n"
"\n"
"Texture2D tex;\n"
"SamplerState smp;\n"
"float4 ps_main( VS_OUTPUT In ) : SV_TARGET\n"
"{\n"
" return tex.Sample( smp, In.TexCoord );\n"
"}\n";
ID3DBlob * vertexShaderBlob = nullptr;
if ( D3DCompile( shaderSource, strlen( shaderSource ), nullptr, nullptr, nullptr, "vs_main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr ) != S_OK )
{
return 1;
}
ID3D11VertexShader * vertexShader = nullptr;
if ( device->CreateVertexShader( vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &vertexShader ) != S_OK )
{
return 1;
}
ID3DBlob * pixelShaderBlob = nullptr;
if ( D3DCompile( shaderSource, strlen( shaderSource ), nullptr, nullptr, nullptr, "ps_main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr ) != S_OK )
{
return 1;
}
ID3D11PixelShader * pixelShader = nullptr;
if ( device->CreatePixelShader( pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &pixelShader ) != S_OK )
{
return 1;
}
D3D11_INPUT_ELEMENT_DESC inputDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
ID3D11InputLayout * inputLayout = nullptr;
if ( device->CreateInputLayout( inputDesc, 1, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &inputLayout ) != S_OK )
{
return 1;
}
float constantBufferData[ 16 + 16 ] = { 0 };
D3D11_BUFFER_DESC constantBufferDesc = CD3D11_BUFFER_DESC( sizeof( constantBufferData ), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE );
D3D11_SUBRESOURCE_DATA constantSubData = { 0 };
constantSubData.pSysMem = constantBufferData;
ID3D11Buffer * constantBuffer = nullptr;
if ( device->CreateBuffer( &constantBufferDesc, &constantSubData, &constantBuffer ) != S_OK )
{
return false;
}
//////////////////////////////////////////////////////////////////////////
ma_engine engine;
if ( ma_engine_init( nullptr, &engine ) != MA_SUCCESS )
{
return 1;
}
ma_sound sound;
if ( ma_sound_init_from_file( &engine, "audio.mp3", 0, nullptr, nullptr, &sound ) != MA_SUCCESS )
{
return 1;
}
ma_sound_start( &sound );
//////////////////////////////////////////////////////////////////////////
while ( !gWindowWantsToQuit )
{
MSG msg;
if ( PeekMessage( &msg, hWnd, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
context->OMSetRenderTargets( 1, &backBufferView, depthStencilView );
const D3D11_VIEWPORT viewport = CD3D11_VIEWPORT( 0.0f, 0.0f, (float)width, (float)height );
context->RSSetViewports( 1, &viewport );
const float clearColor[ 4 ] = { 0.0f };
context->ClearRenderTargetView( backBufferView, clearColor );
context->ClearDepthStencilView( depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0 );
float cursor = 0.0f;
ma_sound_get_cursor_in_seconds( &sound, &cursor );
//////////////////////////////////////////////////////////////////////////
// INSERT DEMO HERE
mat4x4 & projectionMatrix = *(mat4x4 *)&constantBufferData[ 0 ];
mat4x4Perspective( projectionMatrix, 3.1415f * 0.25f, width / (float)height, 0.01f, 10.0f );
mat4x4 & worldMatrix = *(mat4x4 *)&constantBufferData[ 16 ];
mat4x4Identity( worldMatrix );
mat4x4RotateY( worldMatrix, cursor );
vec3 translation = { 0.0f, 0.0f, -5.0f };
mat4x4Translate( worldMatrix, translation );
//////////////////////////////////////////////////////////////////////////
D3D11_MAPPED_SUBRESOURCE mappedSubRes;
context->Map( constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubRes );
CopyMemory( mappedSubRes.pData, constantBufferData, constantBufferDesc.ByteWidth );
context->Unmap( constantBuffer, 0 );
context->VSSetConstantBuffers( 0, 1, &constantBuffer );
context->VSSetShader( vertexShader, nullptr, 0 );
context->PSSetShaderResources( 0, 1, &textureSRV );
context->PSSetShader( pixelShader, nullptr, 0 );
context->RSSetState( rasterizerState );
context->IASetInputLayout( inputLayout );
ID3D11Buffer * buffers[] = { vertexBuffer };
const UINT stride[] = { (UINT)primitive.attributes[ 0 ].data->stride };
const UINT offset[] = { 0 };
context->IASetVertexBuffers( 0, 1, buffers, stride, offset );
context->IASetIndexBuffer( indexBuffer, primitive.indices->component_type == cgltf_component_type_r_32u ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT, 0 );
context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
context->DrawIndexed( (UINT)primitive.indices->count, 0, 0 );
//////////////////////////////////////////////////////////////////////////
swapChain->Present( 0, 0 );
}
ma_sound_stop( &sound );
ma_engine_stop( &engine );
rasterizerState->Release();
depthStencilView->Release();
depthStencil->Release();
backBufferView->Release();
backBuffer->Release();
textureSRV->Release();
texture->Release();
constantBuffer->Release();
pixelShader->Release();
vertexShader->Release();
vertexBuffer->Release();
indexBuffer->Release();
inputLayout->Release();
cgltf_free( meshData );
context->Release();
device->Release();
DestroyWindow( hWnd );
UnregisterClassA( windowClassName, GetModuleHandle( nullptr ) );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment