- WIN32 subsystem, D3D11 standalone rendering (no UILayer dependency) - Scene tree panel, Inspector panel, Console panel, Viewport - Chinese text via glyph_atlas (GDI GetGlyphOutlineW + D3D11 texture atlas) - .ly file format: INI-style scene serialization (save/load) - Ctrl+S/Ctrl+O keyboard shortcuts - Depth test disabled for all 2D rendering
453 lines
20 KiB
C
453 lines
20 KiB
C
#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/include/engine_api.h"
|
|
#include "../Engine/ASM/math_c_fallback.h"
|
|
#include "../Engine/Editor/glyph_atlas.h"
|
|
#include <d3dcompiler.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static GraphicsDevice* g_dev = NULL;
|
|
static GlyphAtlas g_atlas;
|
|
|
|
static ID3D11DepthStencilState* g_no_depth = NULL;
|
|
static ID3D11RasterizerState* g_no_cull = NULL;
|
|
static ID3D11BlendState* g_alpha_blend = NULL;
|
|
|
|
static ID3D11VertexShader* g_vs = NULL;
|
|
static ID3D11PixelShader* g_ps = NULL;
|
|
static ID3D11InputLayout* g_layout = NULL;
|
|
static ID3D11Buffer* g_cb = NULL;
|
|
static ID3D11SamplerState* g_sampler = NULL;
|
|
static ID3D11PixelShader* g_tex_ps = NULL;
|
|
static ID3D11VertexShader* g_tex_vs = NULL;
|
|
static ID3D11InputLayout* g_tex_layout = 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 draw_text(ID3D11DeviceContext* ctx, const wchar_t* text,
|
|
int x, int y, float r, float g, float b, float a) {
|
|
typedef struct { float p[3], n[3], uv[2], c[4]; } TV;
|
|
for (const wchar_t* p = text; *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)) continue;
|
|
TV tv[4] = {
|
|
{{(float)x,(float)y,0},{0,0,1},{u0,v0},{r,g,b,a}},
|
|
{{(float)x+adv_x,(float)y,0},{0,0,1},{u1,v0},{r,g,b,a}},
|
|
{{(float)x+adv_x,(float)y+adv_y,0},{0,0,1},{u1,v1},{r,g,b,a}},
|
|
{{(float)x,(float)y+adv_y,0},{0,0,1},{u0,v1},{r,g,b,a}},
|
|
};
|
|
uint32_t ti[6] = {0,1,2, 0,2,3};
|
|
ID3D11Buffer *tvb = NULL, *tib = NULL;
|
|
D3D11_BUFFER_DESC bd = {0}; D3D11_SUBRESOURCE_DATA sd = {0};
|
|
bd.ByteWidth = sizeof(TV)*4; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
sd.pSysMem = tv; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &tvb);
|
|
bd.ByteWidth = sizeof(uint32_t)*6; bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
|
sd.pSysMem = ti; g_dev->device->lpVtbl->CreateBuffer(g_dev->device, &bd, &sd, &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);
|
|
x += (int)adv_x + 1;
|
|
}
|
|
}
|
|
|
|
static void setup_2d(ID3D11DeviceContext* ctx, float sw, float sh) {
|
|
float proj[16] = {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;
|
|
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_cb, 0, NULL, proj, 0, 0);
|
|
ctx->lpVtbl->VSSetConstantBuffers(ctx, 0, 1, &g_cb);
|
|
D3D11_VIEWPORT vp = {0};
|
|
vp.Width = sw; vp.Height = sh; vp.MaxDepth = 1.0f;
|
|
ctx->lpVtbl->RSSetViewports(ctx, 1, &vp);
|
|
ctx->lpVtbl->RSSetState(ctx, g_no_cull);
|
|
ctx->lpVtbl->OMSetDepthStencilState(ctx, g_no_depth, 0);
|
|
ctx->lpVtbl->IASetPrimitiveTopology(ctx, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
}
|
|
|
|
static void setup_text_shader(ID3D11DeviceContext* ctx) {
|
|
ctx->lpVtbl->VSSetShader(ctx, g_tex_vs, NULL, 0);
|
|
ctx->lpVtbl->PSSetShader(ctx, g_tex_ps, NULL, 0);
|
|
ctx->lpVtbl->IASetInputLayout(ctx, g_tex_layout);
|
|
ctx->lpVtbl->PSSetSamplers(ctx, 0, 1, &g_sampler);
|
|
ctx->lpVtbl->OMSetBlendState(ctx, g_alpha_blend, NULL, 0xFFFFFFFF);
|
|
}
|
|
|
|
typedef struct {
|
|
char name[64];
|
|
float x, y, z;
|
|
float rx, ry, rz;
|
|
float sx, sy, sz;
|
|
int visible;
|
|
} SceneEntity;
|
|
|
|
#define MAX_ENTITIES 64
|
|
static SceneEntity g_entities[MAX_ENTITIES];
|
|
static int g_entity_count = 0;
|
|
static int g_selected = -1;
|
|
|
|
typedef struct {
|
|
char lines[64][256];
|
|
int count;
|
|
int scroll;
|
|
} ConsoleState;
|
|
static ConsoleState g_console = {0};
|
|
|
|
static char g_file_path[512] = "untitled.ly";
|
|
|
|
static void console_add(const char* msg) {
|
|
if (g_console.count >= 64) {
|
|
for (int i = 0; i < 63; i++)
|
|
strcpy(g_console.lines[i], g_console.lines[i+1]);
|
|
g_console.count = 63;
|
|
}
|
|
strncpy(g_console.lines[g_console.count], msg, 255);
|
|
g_console.lines[g_console.count][255] = 0;
|
|
g_console.count++;
|
|
}
|
|
|
|
static void save_ly_file(const char* path) {
|
|
FILE* f = fopen(path, "w");
|
|
if (!f) { console_add("ERROR: cannot save file"); return; }
|
|
fprintf(f, "# lity3d scene file\n");
|
|
fprintf(f, "# format: ly (lity)\n\n");
|
|
for (int i = 0; i < g_entity_count; i++) {
|
|
SceneEntity* e = &g_entities[i];
|
|
fprintf(f, "[Entity]\n");
|
|
fprintf(f, "name = %s\n", e->name);
|
|
fprintf(f, "position = %.2f, %.2f, %.2f\n", e->x, e->y, e->z);
|
|
fprintf(f, "rotation = %.2f, %.2f, %.2f\n", e->rx, e->ry, e->rz);
|
|
fprintf(f, "scale = %.2f, %.2f, %.2f\n", e->sx, e->sy, e->sz);
|
|
fprintf(f, "visible = %d\n\n", e->visible);
|
|
}
|
|
fclose(f);
|
|
char buf[256];
|
|
snprintf(buf, sizeof(buf), "Saved %d entities to %s", g_entity_count, path);
|
|
console_add(buf);
|
|
}
|
|
|
|
static void load_ly_file(const char* path) {
|
|
FILE* f = fopen(path, "r");
|
|
if (!f) { console_add("ERROR: cannot open file"); return; }
|
|
g_entity_count = 0;
|
|
g_selected = -1;
|
|
char line[256];
|
|
SceneEntity tmp = {0};
|
|
int in_entity = 0;
|
|
while (fgets(line, sizeof(line), f)) {
|
|
if (line[0] == '#' || line[0] == '\n') continue;
|
|
if (strstr(line, "[Entity]")) {
|
|
if (in_entity && g_entity_count < MAX_ENTITIES)
|
|
g_entities[g_entity_count++] = tmp;
|
|
memset(&tmp, 0, sizeof(tmp));
|
|
tmp.visible = 1;
|
|
tmp.sx = tmp.sy = tmp.sz = 1.0f;
|
|
in_entity = 1;
|
|
continue;
|
|
}
|
|
if (!in_entity) continue;
|
|
char* eq = strchr(line, '=');
|
|
if (!eq) continue;
|
|
*eq = 0; eq++;
|
|
char* key = line;
|
|
while (*key == ' ' || *key == '\t') key++;
|
|
char* nl = strchr(eq, '\n'); if (nl) *nl = 0;
|
|
while (*eq == ' ') eq++;
|
|
if (strstr(key, "name")) strncpy(tmp.name, eq, 63);
|
|
else if (strstr(key, "position")) sscanf(eq, "%f, %f, %f", &tmp.x, &tmp.y, &tmp.z);
|
|
else if (strstr(key, "rotation")) sscanf(eq, "%f, %f, %f", &tmp.rx, &tmp.ry, &tmp.rz);
|
|
else if (strstr(key, "scale")) sscanf(eq, "%f, %f, %f", &tmp.sx, &tmp.sy, &tmp.sz);
|
|
else if (strstr(key, "visible")) tmp.visible = atoi(eq);
|
|
}
|
|
if (in_entity && g_entity_count < MAX_ENTITIES)
|
|
g_entities[g_entity_count++] = tmp;
|
|
fclose(f);
|
|
char buf[256];
|
|
snprintf(buf, sizeof(buf), "Loaded %d entities from %s", g_entity_count, path);
|
|
console_add(buf);
|
|
strncpy(g_file_path, path, 511);
|
|
}
|
|
|
|
static void add_default_scene(void) {
|
|
g_entity_count = 0;
|
|
const char* names[] = {"Camera", "Directional Light", "Player", "Ground", "Tree", "Rock", "Water", "Skybox"};
|
|
for (int i = 0; i < 8 && i < 8; i++) {
|
|
strncpy(g_entities[i].name, names[i], 63);
|
|
g_entities[i].visible = 1;
|
|
g_entities[i].sx = g_entities[i].sy = g_entities[i].sz = 1.0f;
|
|
}
|
|
g_entity_count = 8;
|
|
g_selected = 2;
|
|
}
|
|
|
|
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.12f, 0.12f, 0.14f, 1.0f);
|
|
setup_2d(ctx, sw, sh);
|
|
|
|
float menu_h = 28, toolbar_h = 28, console_h = 180, panel_w = 220;
|
|
float status_h = 22;
|
|
|
|
draw_quad(ctx, 0, 0, sw, menu_h, 0.18f, 0.18f, 0.22f, 1.0f);
|
|
draw_quad(ctx, 0, menu_h, sw, toolbar_h, 0.16f, 0.16f, 0.19f, 1.0f);
|
|
draw_quad(ctx, 0, menu_h + toolbar_h, panel_w, sh - menu_h - toolbar_h - console_h - status_h, 0.14f, 0.14f, 0.16f, 1.0f);
|
|
draw_quad(ctx, panel_w, menu_h + toolbar_h, sw - 2*panel_w, sh - menu_h - toolbar_h - console_h - status_h, 0.10f, 0.10f, 0.12f, 1.0f);
|
|
draw_quad(ctx, sw - panel_w, menu_h + toolbar_h, panel_w, sh - menu_h - toolbar_h - console_h - status_h, 0.14f, 0.14f, 0.16f, 1.0f);
|
|
draw_quad(ctx, 0, sh - console_h - status_h, sw, console_h, 0.13f, 0.13f, 0.15f, 1.0f);
|
|
draw_quad(ctx, 0, sh - status_h, sw, status_h, 0.16f, 0.16f, 0.20f, 1.0f);
|
|
|
|
draw_quad(ctx, 0, 0, sw, 1, 0.30f, 0.30f, 0.35f, 1.0f);
|
|
|
|
setup_text_shader(ctx);
|
|
ctx->lpVtbl->PSSetShaderResources(ctx, 0, 1, &g_atlas.srv);
|
|
|
|
draw_text(ctx, L"lity3d Editor", 10, 6, 0.6f, 0.8f, 1.0f, 1.0f);
|
|
const wchar_t* menus[] = {L"\u6587\u4ef6", L"\u7f16\u8f91", L"\u89c6\u56fe", L"\u6784\u5efa", L"\u5e2e\u52a9"};
|
|
int mx = 120;
|
|
for (int i = 0; i < 5; i++) {
|
|
draw_text(ctx, menus[i], mx, 6, 0.85f, 0.85f, 0.88f, 1.0f);
|
|
mx += 70;
|
|
}
|
|
|
|
draw_text(ctx, L"\u573a\u666f", 10, 36, 0.85f, 0.85f, 0.88f, 1.0f);
|
|
draw_text(ctx, L"\u89c6\u53e3", (int)(panel_w + 10), 36, 0.85f, 0.85f, 0.88f, 1.0f);
|
|
draw_text(ctx, L"\u5c5e\u6027", (int)(sw - panel_w + 10), 36, 0.85f, 0.85f, 0.88f, 1.0f);
|
|
draw_text(ctx, L"\u63a7\u5236\u53f0", 10, (int)(sh - console_h - status_h + 6), 0.85f, 0.85f, 0.88f, 1.0f);
|
|
|
|
for (int i = 0; i < g_entity_count; i++) {
|
|
float ey = 60 + i * 22;
|
|
if (i == g_selected)
|
|
draw_quad(ctx, 4, (float)(int)ey - 2, panel_w - 8, 20, 0.25f, 0.30f, 0.45f, 1.0f);
|
|
float cr = (g_entities[i].visible) ? 0.9f : 0.5f;
|
|
draw_text(ctx, L"\u25b6", 10, (int)ey, cr, cr, cr, 1.0f);
|
|
wchar_t wname[64];
|
|
int len = (int)strlen(g_entities[i].name);
|
|
for (int j = 0; j < len && j < 63; j++) wname[j] = (wchar_t)g_entities[i].name[j];
|
|
wname[len] = 0;
|
|
draw_text(ctx, wname, 28, (int)ey, cr, cr, cr, 1.0f);
|
|
}
|
|
|
|
if (g_selected >= 0 && g_selected < g_entity_count) {
|
|
SceneEntity* e = &g_entities[g_selected];
|
|
int ix = (int)(sw - panel_w + 10);
|
|
int iy = 60;
|
|
draw_text(ctx, L"\u540d\u79f0:", ix, iy, 0.6f, 0.7f, 0.9f, 1.0f);
|
|
wchar_t wname[64];
|
|
int len = (int)strlen(e->name);
|
|
for (int j = 0; j < len && j < 63; j++) wname[j] = (wchar_t)e->name[j];
|
|
wname[len] = 0;
|
|
draw_text(ctx, wname, ix + 40, iy, 0.9f, 0.9f, 0.92f, 1.0f);
|
|
iy += 26;
|
|
draw_text(ctx, L"\u4f4d\u7f6e:", ix, iy, 0.6f, 0.7f, 0.9f, 1.0f);
|
|
iy += 18;
|
|
draw_text(ctx, L"\u65cb\u8f6c:", ix, iy, 0.6f, 0.7f, 0.9f, 1.0f);
|
|
iy += 18;
|
|
draw_text(ctx, L"\u7f29\u653e:", ix, iy, 0.6f, 0.7f, 0.9f, 1.0f);
|
|
iy += 26;
|
|
draw_text(ctx, L"\u53ef\u89c1:", ix, iy, 0.6f, 0.7f, 0.9f, 1.0f);
|
|
draw_text(ctx, e->visible ? L"\u2611" : L"\u2610", ix + 40, iy, 0.9f, 0.9f, 0.92f, 1.0f);
|
|
}
|
|
|
|
int cy = (int)(sh - console_h - status_h + 22);
|
|
for (int i = 0; i < g_console.count && i < 8; i++) {
|
|
int li = g_console.count - 1 - i;
|
|
if (li < 0) break;
|
|
wchar_t wline[256];
|
|
int len = (int)strlen(g_console.lines[li]);
|
|
for (int j = 0; j < len && j < 255; j++) wline[j] = (wchar_t)g_console.lines[li][j];
|
|
wline[len] = 0;
|
|
draw_text(ctx, wline, 10, cy, 0.7f, 0.7f, 0.72f, 1.0f);
|
|
cy += 18;
|
|
}
|
|
|
|
char status[256];
|
|
snprintf(status, sizeof(status), "%s | %d entities | %.1fs", g_file_path, g_entity_count, engine->total_time);
|
|
wchar_t wstatus[256];
|
|
int slen = (int)strlen(status);
|
|
for (int j = 0; j < slen && j < 255; j++) wstatus[j] = (wchar_t)status[j];
|
|
wstatus[slen] = 0;
|
|
draw_text(ctx, wstatus, 10, (int)(sh - 18), 0.55f, 0.55f, 0.6f, 1.0f);
|
|
|
|
graphics_device_present(g_dev);
|
|
}
|
|
|
|
static void on_key(Engine* engine, int key) {
|
|
if (key == VK_ESCAPE) engine_request_quit(engine);
|
|
if (key == 'S' && GetAsyncKeyState(VK_CONTROL) & 0x8000) {
|
|
save_ly_file(g_file_path);
|
|
}
|
|
if (key == 'O' && GetAsyncKeyState(VK_CONTROL) & 0x8000) {
|
|
load_ly_file(g_file_path);
|
|
}
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
|
(void)hInstance; (void)hPrevInstance; (void)nCmdShow;
|
|
LOG_INFO("=== lity3d Editor ===");
|
|
|
|
EngineConfig config = engine_default_config();
|
|
config.app_name = "lity3d Editor";
|
|
config.vsync = 1;
|
|
config.window_width = 1440;
|
|
config.window_height = 900;
|
|
|
|
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;
|
|
}
|
|
|
|
glyph_atlas_init(&g_atlas, g_dev->device);
|
|
|
|
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);
|
|
|
|
D3D11_RASTERIZER_DESC rdesc = {0};
|
|
rdesc.FillMode = D3D11_FILL_SOLID;
|
|
rdesc.CullMode = D3D11_CULL_NONE;
|
|
g_dev->device->lpVtbl->CreateRasterizerState(g_dev->device, &rdesc, &g_no_cull);
|
|
|
|
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_alpha_blend);
|
|
|
|
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_sampler);
|
|
|
|
const char* solid_vs =
|
|
"cbuffer CB:register(b0){float4x4 WVP;};"
|
|
"struct I{float4 p:POSITION;float3 n:NORMAL;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"struct O{float4 p:SV_POSITION;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"O main(I i){O o;o.p=mul(i.p,WVP);o.u=i.u;o.c=i.c;return o;}";
|
|
const char* solid_ps =
|
|
"struct O{float4 p:SV_POSITION;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"float4 main(O i):SV_TARGET{return i.c;}";
|
|
const char* tex_vs =
|
|
"cbuffer CB:register(b0){float4x4 WVP;};"
|
|
"struct I{float4 p:POSITION;float3 n:NORMAL;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"struct O{float4 p:SV_POSITION;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"O main(I i){O o;o.p=mul(i.p,WVP);o.u=i.u;o.c=i.c;return o;}";
|
|
const char* tex_ps =
|
|
"Texture2D t:register(t0);SamplerState s:register(s0);"
|
|
"struct O{float4 p:SV_POSITION;float2 u:TEXCOORD;float4 c:COLOR;};"
|
|
"float4 main(O i):SV_TARGET{float a=t.t.Sample(s,i.u).a;return float4(i.c.rgb,i.c.a*a);}";
|
|
|
|
ID3DBlob *b1 = NULL, *b2 = NULL, *e1 = NULL, *e2 = NULL;
|
|
D3DCompile(solid_vs, (UINT)strlen(solid_vs), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &b1, &e1);
|
|
if (e1) { e1->lpVtbl->Release(e1); e1 = NULL; }
|
|
D3DCompile(solid_ps, (UINT)strlen(solid_ps), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &b2, &e2);
|
|
if (e2) { e2->lpVtbl->Release(e2); e2 = NULL; }
|
|
if (b1 && b2) {
|
|
g_dev->device->lpVtbl->CreateVertexShader(g_dev->device, b1->lpVtbl->GetBufferPointer(b1), b1->lpVtbl->GetBufferSize(b1), NULL, &g_vs);
|
|
g_dev->device->lpVtbl->CreatePixelShader(g_dev->device, b2->lpVtbl->GetBufferPointer(b2), b2->lpVtbl->GetBufferSize(b2), NULL, &g_ps);
|
|
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, b1->lpVtbl->GetBufferPointer(b1), b1->lpVtbl->GetBufferSize(b1), &g_layout);
|
|
b1->lpVtbl->Release(b1); b2->lpVtbl->Release(b2);
|
|
}
|
|
|
|
ID3DBlob *b3 = NULL, *b4 = NULL, *e3 = NULL, *e4 = NULL;
|
|
D3DCompile(tex_vs, (UINT)strlen(tex_vs), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &b3, &e3);
|
|
if (e3) { e3->lpVtbl->Release(e3); e3 = NULL; }
|
|
D3DCompile(tex_ps, (UINT)strlen(tex_ps), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &b4, &e4);
|
|
if (e4) { e4->lpVtbl->Release(e4); e4 = NULL; }
|
|
if (b3 && b4) {
|
|
g_dev->device->lpVtbl->CreateVertexShader(g_dev->device, b3->lpVtbl->GetBufferPointer(b3), b3->lpVtbl->GetBufferSize(b3), NULL, &g_tex_vs);
|
|
g_dev->device->lpVtbl->CreatePixelShader(g_dev->device, b4->lpVtbl->GetBufferPointer(b4), b4->lpVtbl->GetBufferSize(b4), NULL, &g_tex_ps);
|
|
D3D11_INPUT_ELEMENT_DESC layout2[] = {
|
|
{"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, layout2, 4, b3->lpVtbl->GetBufferPointer(b3), b3->lpVtbl->GetBufferSize(b3), &g_tex_layout);
|
|
b3->lpVtbl->Release(b3); b4->lpVtbl->Release(b4);
|
|
}
|
|
|
|
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_cb);
|
|
|
|
if (lpCmdLine && lpCmdLine[0]) {
|
|
char fname[512] = {0};
|
|
if (lpCmdLine[0] == '"') { strncpy(fname, lpCmdLine+1, 510); char* q = strchr(fname, '"'); if (q) *q = 0; }
|
|
else strncpy(fname, lpCmdLine, 510);
|
|
load_ly_file(fname);
|
|
} else {
|
|
add_default_scene();
|
|
}
|
|
|
|
console_add("lity3d Editor started");
|
|
console_add("Ctrl+S: save .ly | Ctrl+O: load .ly | Esc: quit");
|
|
|
|
engine_set_render_callback(engine, on_render);
|
|
engine_set_key_callback(engine, on_key);
|
|
engine_run(engine);
|
|
|
|
if (g_tex_layout) g_tex_layout->lpVtbl->Release(g_tex_layout);
|
|
if (g_tex_ps) g_tex_ps->lpVtbl->Release(g_tex_ps);
|
|
if (g_tex_vs) g_tex_vs->lpVtbl->Release(g_tex_vs);
|
|
if (g_layout) g_layout->lpVtbl->Release(g_layout);
|
|
if (g_ps) g_ps->lpVtbl->Release(g_ps);
|
|
if (g_vs) g_vs->lpVtbl->Release(g_vs);
|
|
if (g_cb) g_cb->lpVtbl->Release(g_cb);
|
|
if (g_sampler) g_sampler->lpVtbl->Release(g_sampler);
|
|
if (g_alpha_blend) g_alpha_blend->lpVtbl->Release(g_alpha_blend);
|
|
if (g_no_cull) g_no_cull->lpVtbl->Release(g_no_cull);
|
|
if (g_no_depth) g_no_depth->lpVtbl->Release(g_no_depth);
|
|
glyph_atlas_destroy(&g_atlas);
|
|
graphics_device_destroy(g_dev);
|
|
engine_shutdown(engine);
|
|
return 0;
|
|
}
|