Files
lity3d/Demo/raw3d_test.c
T

129 lines
6.5 KiB
C

// raw3d_test.c - 用 draw_quad 画 3D 方块,验证场景图变换
#include "../Engine/Core/engine.h"
#include "../Engine/Window/window.h"
#include "../Engine/Rendering/graphics_device.h"
#include "../Engine/Rendering/shader.h"
#include "../Engine/Scene/scene_graph.h"
#include "../Engine/include/engine_api.h"
#include "../Engine/ASM/math_c_fallback.h"
static GraphicsDevice* g_dev = NULL;
static Shader* g_shader = NULL;
static Scene g_scene;
static float g_time = 0;
typedef struct { float p[3],n[3],uv[2],c[4]; } V;
static void draw_quad_3d(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={}; D3D11_SUBRESOURCE_DATA sd={};
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),off=0;
ctx->lpVtbl->IASetVertexBuffers(ctx,0,1,&vb,&stride,&off);
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;
scene_update(&g_scene);
g_time += (float)engine->delta_time;
float sw=(float)g_dev->width, sh=(float)g_dev->height;
float fov=1.0f/tanf(0.4f), asp=sw/sh;
// VP矩阵: 摄像机在(8,5,10)看原点
float ex=8,ey=5,ez=10;
float fx=-ex,fy=-ey,fz=-ez, fl=sqrtf(fx*fx+fy*fy+fz*fz); fx/=fl;fy/=fl;fz/=fl;
float rx=fy*0-fz*1,ry=fz*0-fx*0,rz=fx*1-fy*0;
float rl=sqrtf(rx*rx+ry*ry+rz*rz);rx/=rl;ry/=rl;rz/=rl;
float ux=ry*fz-rz*fy,uy=rz*fx-rx*fz,uz=rx*fy-ry*fx;
float mvp[16];
mvp[0]=rx*fov/asp;mvp[1]=ry*fov/asp;mvp[2]=rz*fov/asp;mvp[3]=0;
mvp[4]=ux*fov;mvp[5]=uy*fov;mvp[6]=uz*fov;mvp[7]=0;
mvp[8]=fx;mvp[9]=fy;mvp[10]=fz;mvp[11]=0;
mvp[12]=-(rx*ex+ry*ey+rz*ez)*fov/asp;
mvp[13]=-(ux*ex+uy*ey+uz*ez)*fov;
mvp[14]=-(fx*ex+fy*ey+fz*ez);mvp[15]=1;
graphics_device_clear(g_dev, 0.15f, 0.18f, 0.25f, 1.0f);
D3D11_VIEWPORT vp={};vp.Width=sw;vp.Height=sh;vp.MaxDepth=1;
ctx->lpVtbl->RSSetViewports(ctx,1,&vp);
D3D11_RASTERIZER_DESC rd={};rd.FillMode=D3D11_FILL_SOLID;rd.CullMode=D3D11_CULL_NONE;
ID3D11RasterizerState* rs=NULL;
g_dev->device->lpVtbl->CreateRasterizerState(g_dev->device,&rd,&rs);
ctx->lpVtbl->RSSetState(ctx,rs);
D3D11_DEPTH_STENCIL_DESC dsd={};dsd.DepthEnable=FALSE;
ID3D11DepthStencilState* dss=NULL;
g_dev->device->lpVtbl->CreateDepthStencilState(g_dev->device,&dsd,&dss);
ctx->lpVtbl->OMSetDepthStencilState(ctx,dss,0);
ctx->lpVtbl->IASetPrimitiveTopology(ctx,D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
shader_bind(g_shader, ctx);
// 地面
shader_set_matrix(g_shader, ctx, mvp);
draw_quad_3d(ctx, -5, 0, 10, 10, 0.3f, 0.35f, 0.4f, 1);
// 场景节点
for (int i=0;i<g_scene.node_count;i++) {
SceneNode*n=&g_scene.nodes[i];
if (!n->visible||n->id==0||n->user_type!=1) continue;
// 用世界矩阵变换4个角点
float corners[4][3] = {{-0.5f,-0.5f,0},{0.5f,-0.5f,0},{0.5f,0.5f,0},{-0.5f,0.5f,0}};
V v[4]; uint32_t idx[6]={0,1,2,0,2,3};
float colors[][3]={{1,0.2f,0.2f},{0.2f,1,0.2f},{0.2f,0.2f,1},{1,1,0.2f},{0.5f,0.2f,0.8f},{0.2f,0.8f,0.8f},{0.8f,0.5f,0.2f},{0.5f,0.5f,0.5f}};
int ci=(i-1)%8;
for(int c=0;c<4;c++){
float px=0,py=0,pz=0;
for(int r=0;r<4;r++) {float wc=n->world_matrix.m[0][r]*corners[c][0]+n->world_matrix.m[1][r]*corners[c][1]+n->world_matrix.m[2][r]*corners[c][2]+n->world_matrix.m[3][r]; px+=wc*mvp[r*4+0]; py+=wc*mvp[r*4+1]; pz+=wc*mvp[r*4+2];}
// 简化: 直接用世界坐标+投影
float wx=n->world_matrix.m[3][0]+corners[c][0];
float wy=n->world_matrix.m[3][1]+corners[c][1];
float wz=n->world_matrix.m[3][2]+corners[c][2];
v[c].p[0]=wx; v[c].p[1]=wy; v[c].p[2]=wz;
v[c].n[0]=0; v[c].n[1]=0; v[c].n[2]=1;
v[c].c[0]=colors[ci][0]; v[c].c[1]=colors[ci][1]; v[c].c[2]=colors[ci][2]; v[c].c[3]=1;
}
ID3D11Buffer* vb=NULL,*ib2=NULL;
D3D11_BUFFER_DESC bd2={}; D3D11_SUBRESOURCE_DATA sd2={};
bd2.ByteWidth=sizeof(V)*4; bd2.Usage=D3D11_USAGE_DEFAULT; bd2.BindFlags=D3D11_BIND_VERTEX_BUFFER;
sd2.pSysMem=v; g_dev->device->lpVtbl->CreateBuffer(g_dev->device,&bd2,&sd2,&vb);
bd2.ByteWidth=sizeof(uint32_t)*6; bd2.BindFlags=D3D11_BIND_INDEX_BUFFER;
sd2.pSysMem=idx; g_dev->device->lpVtbl->CreateBuffer(g_dev->device,&bd2,&sd2,&ib2);
UINT s2=sizeof(V),o2=0;
ctx->lpVtbl->IASetVertexBuffers(ctx,0,1,&vb,&s2,&o2);
ctx->lpVtbl->IASetIndexBuffer(ctx,ib2,DXGI_FORMAT_R32_UINT,0);
ctx->lpVtbl->DrawIndexed(ctx,6,0,0);
ib2->lpVtbl->Release(ib2); vb->lpVtbl->Release(vb);
}
if(rs) rs->lpVtbl->Release(rs);
if(dss) dss->lpVtbl->Release(dss);
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 hI,HINSTANCE,LPSTR,int) {
EngineConfig cfg=engine_default_config(); cfg.app_name="lity3d Raw3D";
Engine* e=engine_create(); if(!engine_init(e,&cfg))return -1;
g_dev=graphics_device_create();
if(!graphics_device_init(g_dev,window_get_handle(e->window),cfg.window_width,cfg.window_height,1))return -1;
g_shader=shader_create(); shader_compile(g_shader,g_dev->device,NULL,NULL,0,0);
scene_init(&g_scene);
SceneNode* c1=scene_create_node(&g_scene,"Cube1"); scene_set_position(c1,0,0.5f,0); c1->user_type=1;
SceneNode* c2=scene_create_node(&g_scene,"Cube2"); scene_set_position(c2,-3,0.5f,2); c2->user_type=1;
SceneNode* c3=scene_create_node(&g_scene,"Cube3"); scene_set_position(c3,3,0.5f,-2); scene_set_scale(c3,0.5f,0.5f,0.5f); c3->user_type=1;
SceneNode* ch=scene_create_node(&g_scene,"Child"); scene_set_position(ch,2,0,0); ch->user_type=1; scene_set_parent(ch,c1);
engine_set_render_callback(e,on_render); engine_set_key_callback(e,on_key);
engine_run(e);
shader_destroy(g_shader); graphics_device_destroy(g_dev); engine_shutdown(e);
return 0;
}