129 lines
6.5 KiB
C
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;
|
|
}
|