#include "../Engine/Core/engine.h" #include "../Engine/Core/logger.h" #include "../Engine/Core/timer.h" #include "../Engine/Window/window.h" #include "../Engine/Rendering/graphics_device.h" #include "../Engine/Rendering/shader.h" #include "../Engine/Rendering/mesh.h" #include "../Engine/include/engine_api.h" #include "../Engine/ASM/math_c_fallback.h" #include "../Engine/Editor/glyph_atlas.h" #include static GraphicsDevice* g_dev = NULL; static Shader* g_shader = NULL; static Mesh* g_tri = NULL; static GlyphAtlas g_atlas; static ID3D11VertexShader* g_tvs = NULL; static ID3D11PixelShader* g_tps = NULL; static ID3D11InputLayout* g_tlayout = NULL; static ID3D11BlendState* g_tblend = NULL; static ID3D11SamplerState* g_tsampler = NULL; static ID3D11Buffer* g_tcb = NULL; static ID3D11DepthStencilState* g_no_depth = NULL; typedef struct { float p[3], n[3], uv[2], c[4]; } V; static void draw_quad(ID3D11DeviceContext* ctx, float x, float y, float w, float h, float r, float g, float b, float a) { V v[4] = { {{x,y,0},{0,0,-1},{0,0},{r,g,b,a}}, {{x+w,y,0},{0,0,-1},{1,0},{r,g,b,a}}, {{x+w,y+h,0},{0,0,-1},{1,1},{r,g,b,a}}, {{x,y+h,0},{0,0,-1},{0,1},{r,g,b,a}}, }; uint32_t idx[6] = {0,1,2, 0,2,3}; ID3D11Buffer *vb = NULL, *ib = NULL; D3D11_BUFFER_DESC bd = {0}; D3D11_SUBRESOURCE_DATA sd = {0}; bd.ByteWidth = sizeof(V)*4; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; sd.pSysMem = v; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &vb); bd.ByteWidth = sizeof(uint32_t)*6; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; sd.pSysMem = idx; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &ib); UINT stride = sizeof(V), offset = 0; ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &vb, &stride, &offset); ctx->lpVtbl->IASetIndexBuffer(ctx, ib, DXGI_FORMAT_R32_UINT, 0); ctx->lpVtbl->DrawIndexed(ctx, 6, 0, 0); ib->lpVtbl->Release(ib); vb->lpVtbl->Release(vb); } static void on_render(Engine* engine) { if (!g_dev) return; ID3D11DeviceContext* ctx = g_dev->context; float sw = (float)g_dev->width; float sh = (float)g_dev->height; graphics_device_clear(g_dev, 0.0f, 0.0f, 0.0f, 1.0f); float proj[64] = {0}; proj[0] = 2.0f / sw; proj[5] = -2.0f / sh; proj[10] = 1.0f; proj[12] = -1.0f; proj[13] = 1.0f; proj[15] = 1.0f; Mat4 proj_m, proj_t; memcpy(&proj_m, proj, sizeof(Mat4)); mat4_transpose(&proj_m, &proj_t); D3D11_VIEWPORT vp = {0}; vp.Width = sw; vp.Height = sh; vp.MaxDepth = 1.0f; ctx->lpVtbl->RSSetViewports(ctx, 1, &vp); D3D11_RASTERIZER_DESC rdesc = {0}; rdesc.FillMode = D3D11_FILL_SOLID; rdesc.CullMode = D3D11_CULL_NONE; ID3D11RasterizerState* rstate = NULL; g_dev->device->lpVtbl->CreateRasterizerState(g_dev->device, &rdesc, &rstate); ctx->lpVtbl->RSSetState(ctx, rstate); ctx->lpVtbl->IASetPrimitiveTopology(ctx, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); shader_bind(g_shader, ctx); shader_set_matrix(g_shader, ctx, (float*)&proj_t); mesh_draw(g_tri, ctx); ctx->lpVtbl->OMSetDepthStencilState(ctx, g_no_depth, 0); draw_quad(ctx, sw - 200, 10, 180, 60, 1, 1, 1, 1); if (g_tvs && g_tps && g_tlayout && g_tcb && g_tblend && g_tsampler && g_atlas.srv) { ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_tcb, 0, NULL, &proj_t, 0, 0); ctx->lpVtbl->VSSetShader(ctx, g_tvs, NULL, 0); ctx->lpVtbl->PSSetShader(ctx, g_tps, NULL, 0); ctx->lpVtbl->IASetInputLayout(ctx, g_tlayout); ctx->lpVtbl->VSSetConstantBuffers(ctx, 0, 1, &g_tcb); ctx->lpVtbl->PSSetShaderResources(ctx, 0, 1, &g_atlas.srv); ctx->lpVtbl->PSSetSamplers(ctx, 0, 1, &g_tsampler); ctx->lpVtbl->OMSetBlendState(ctx, g_tblend, NULL, 0xFFFFFFFF); typedef struct { float p[3], n[3], uv[2], c[4]; } TV; TV tverts[4]; uint32_t tidx[6] = {0,1,2, 0,2,3}; int cx = (int)(sw - 195), cy = 35; for (const wchar_t* p = L"\u6d4b\u8bd5"; *p; p++) { float u0, v0, u1, v1, adv_x, adv_y; if (glyph_atlas_get_or_create(&g_atlas, g_dev->device, ctx, *p, &u0, &v0, &u1, &v1, &adv_x, &adv_y)) { tverts[0] = (TV){{(float)cx,(float)cy,0},{0,0,1},{u0,v0},{0,0,0,1}}; tverts[1] = (TV){{(float)cx+adv_x,(float)cy,0},{0,0,1},{u1,v0},{0,0,0,1}}; tverts[2] = (TV){{(float)cx+adv_x,(float)cy+adv_y,0},{0,0,1},{u1,v1},{0,0,0,1}}; tverts[3] = (TV){{(float)cx,(float)cy+adv_y,0},{0,0,1},{u0,v1},{0,0,0,1}}; ID3D11Buffer *tvb = NULL, *tib = NULL; D3D11_BUFFER_DESC bd2 = {0}; D3D11_SUBRESOURCE_DATA sd2 = {0}; bd2.ByteWidth = sizeof(TV)*4; bd2.Usage = D3D11_USAGE_DEFAULT; bd2.BindFlags = D3D11_BIND_VERTEX_BUFFER; sd2.pSysMem = tverts; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd2, &sd2, &tvb); bd2.ByteWidth = sizeof(uint32_t)*6; bd2.BindFlags = D3D11_BIND_INDEX_BUFFER; sd2.pSysMem = tidx; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd2, &sd2, &tib); UINT stride2 = sizeof(TV), offset2 = 0; ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &tvb, &stride2, &offset2); ctx->lpVtbl->IASetIndexBuffer(ctx, tib, DXGI_FORMAT_R32_UINT, 0); ctx->lpVtbl->DrawIndexed(ctx, 6, 0, 0); tib->lpVtbl->Release(tib); tvb->lpVtbl->Release(tvb); cx += (int)adv_x + 2; } } } if (rstate) rstate->lpVtbl->Release(rstate); graphics_device_present(g_dev); } static void on_key(Engine* engine, int key) { if (key == VK_ESCAPE) engine_request_quit(engine); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { (void)hInstance; (void)hPrevInstance; (void)lpCmdLine; (void)nCmdShow; LOG_INFO("=== Compatibility Test ==="); EngineConfig config = engine_default_config(); config.app_name = "Compatibility Test"; config.vsync = 1; config.window_width = 1280; config.window_height = 720; Engine* engine = engine_create(); if (!engine_init(engine, &config)) return -1; g_dev = graphics_device_create(); if (!graphics_device_init(g_dev, window_get_handle(engine->window), config.window_width, config.window_height, 1)) { LOG_FATAL("D3D11 init failed"); return -1; } g_shader = shader_create(); shader_compile(g_shader, g_dev->device, NULL, NULL, 0, 0); glyph_atlas_init(&g_atlas, g_dev->device); const char* tvs_src = "cbuffer CB:register(b0){float4x4 WVP;};struct VS_IN{float4 pos:POSITION;float3 n:NORMAL;float2 uv:TEXCOORD;float4 col:COLOR;};struct PS_IN{float4 pos:SV_POSITION;float2 uv:TEXCOORD;float4 col:COLOR;};PS_IN main(VS_IN i){PS_IN o;o.pos=mul(i.pos,WVP);o.uv=i.uv;o.col=i.col;return o;}"; const char* tps_src = "Texture2D tex:register(t0);SamplerState smp:register(s0);struct PS_IN{float4 pos:SV_POSITION;float2 uv:TEXCOORD;float4 col:COLOR;};float4 main(PS_IN i):SV_TARGET{float a=tex.Sample(smp,i.uv).a;return float4(i.col.rgb,i.col.a*a);}"; ID3DBlob *vsb = NULL, *psb = NULL, *err = NULL; D3DCompile(tvs_src, (UINT)strlen(tvs_src), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vsb, &err); if (err) { err->lpVtbl->Release(err); err = NULL; } D3DCompile(tps_src, (UINT)strlen(tps_src), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &psb, &err); if (err) { err->lpVtbl->Release(err); err = NULL; } if (vsb && psb) { g_dev->device->lpVtbl->CreateVertexShader(g_dev->device, vsb->lpVtbl->GetBufferPointer(vsb), vsb->lpVtbl->GetBufferSize(vsb), NULL, &g_tvs); g_dev->device->lpVtbl->CreatePixelShader(g_dev->device, psb->lpVtbl->GetBufferPointer(psb), psb->lpVtbl->GetBufferSize(psb), NULL, &g_tps); D3D11_INPUT_ELEMENT_DESC layout[] = { {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0}, {"NORMAL",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0}, {"TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,24,D3D11_INPUT_PER_VERTEX_DATA,0}, {"COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,32,D3D11_INPUT_PER_VERTEX_DATA,0}, }; g_dev->device->lpVtbl->CreateInputLayout(g_dev->device, layout, 4, vsb->lpVtbl->GetBufferPointer(vsb), vsb->lpVtbl->GetBufferSize(vsb), &g_tlayout); vsb->lpVtbl->Release(vsb); psb->lpVtbl->Release(psb); } D3D11_SAMPLER_DESC sdesc = {0}; sdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sdesc.AddressU = sdesc.AddressV = sdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; g_dev->device->lpVtbl->CreateSamplerState(g_dev->device, &sdesc, &g_tsampler); D3D11_BLEND_DESC bdesc = {0}; bdesc.RenderTarget[0].BlendEnable = TRUE; bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; bdesc.RenderTarget[0].RenderTargetWriteMask = 0x0F; g_dev->device->lpVtbl->CreateBlendState(g_dev->device, &bdesc, &g_tblend); D3D11_BUFFER_DESC cbd = {0}; cbd.ByteWidth = 256; cbd.Usage = D3D11_USAGE_DEFAULT; cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &cbd, NULL, &g_tcb); D3D11_DEPTH_STENCIL_DESC dsdesc = {0}; dsdesc.DepthEnable = FALSE; dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; g_dev->device->lpVtbl->CreateDepthStencilState(g_dev->device, &dsdesc, &g_no_depth); V tri[3] = { {{640, 300, 0}, {0,0,-1}, {0,0}, {1, 0.2f, 0.2f, 1}}, {{500, 550, 0}, {0,0,-1}, {0,1}, {0.2f, 1, 0.2f, 1}}, {{780, 550, 0}, {0,0,-1}, {1,0}, {0.2f, 0.2f, 1, 1}}, }; uint32_t idx[3] = {0, 1, 2}; g_tri = (Mesh*)calloc(1, sizeof(Mesh)); g_tri->stride = sizeof(V); g_tri->vcount = 3; g_tri->icount = 3; D3D11_BUFFER_DESC bd = {0}; D3D11_SUBRESOURCE_DATA sd = {0}; bd.ByteWidth = sizeof(V)*3; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; sd.pSysMem = tri; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &g_tri->vb); bd.ByteWidth = sizeof(uint32_t)*3; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; sd.pSysMem = idx; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &g_tri->ib); engine_set_render_callback(engine, on_render); engine_set_key_callback(engine, on_key); LOG_INFO("Running..."); engine_run(engine); mesh_destroy(g_tri); shader_destroy(g_shader); glyph_atlas_destroy(&g_atlas); graphics_device_destroy(g_dev); engine_shutdown(engine); return 0; }