122 lines
5.0 KiB
C
122 lines
5.0 KiB
C
// scene_test.c - 场景图 + 网格渲染
|
|
#include "../Engine/Core/engine.h"
|
|
#include "../Engine/Core/logger.h"
|
|
#include "../Engine/Window/window.h"
|
|
#include "../Engine/Rendering/graphics_device.h"
|
|
#include "../Engine/Rendering/shader.h"
|
|
#include "../Engine/Rendering/mesh.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 Mesh* g_cube = NULL;
|
|
static Mesh* g_plane = NULL;
|
|
static Scene g_scene;
|
|
static SceneNode* g_camera = NULL;
|
|
static float g_time = 0;
|
|
|
|
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.5f * 0.785f), aspect = sw / sh;
|
|
Vec3 cam_pos;
|
|
scene_get_world_position(g_camera, &cam_pos);
|
|
|
|
// VP 矩阵
|
|
float proj[16] = {0};
|
|
proj[0] = fov / aspect; proj[5] = -fov;
|
|
proj[10] = 1.0f; proj[11] = -1.0f; proj[14] = 0.1f; proj[15] = 1.0f;
|
|
|
|
Vec3 eye = cam_pos, target = {0,0,0}, up = {0,1,0};
|
|
Vec3 f, r, u;
|
|
vec3_sub(&target, &eye, &f); vec3_normalize(&f, &f);
|
|
vec3_cross(&up, &f, &r); vec3_normalize(&r, &r);
|
|
vec3_cross(&f, &r, &u);
|
|
|
|
float view[16] = {0};
|
|
view[0]=r.x; view[1]=u.x; view[2]=-f.x;
|
|
view[4]=r.y; view[5]=u.y; view[6]=-f.y;
|
|
view[8]=r.z; view[9]=u.z; view[10]=-f.z;
|
|
view[12]=-vec3_dot(&r,&eye); view[13]=-vec3_dot(&u,&eye); view[14]=vec3_dot(&f,&eye); view[15]=1.0f;
|
|
|
|
float vp_raw[16] = {0};
|
|
for (int i = 0; i < 4; i++)
|
|
for (int j = 0; j < 4; j++)
|
|
vp_raw[i*4+j] = view[i*4+0]*proj[0*4+j]+view[i*4+1]*proj[1*4+j]+view[i*4+2]*proj[2*4+j]+view[i*4+3]*proj[3*4+j];
|
|
Mat4 vp_m, vp_t;
|
|
memcpy(&vp_m, vp_raw, sizeof(Mat4));
|
|
mat4_transpose(&vp_m, &vp_t);
|
|
|
|
graphics_device_clear(g_dev, 0.15f, 0.18f, 0.25f, 1.0f);
|
|
|
|
D3D11_VIEWPORT vport = {0}; vport.Width = sw; vport.Height = sh; vport.MaxDepth = 1.0f;
|
|
ctx->lpVtbl->RSSetViewports(ctx, 1, &vport);
|
|
|
|
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*)&vp_t);
|
|
|
|
if (g_plane) mesh_draw(g_plane, ctx);
|
|
|
|
for (int i = 0; i < g_scene.node_count; i++) {
|
|
SceneNode* node = &g_scene.nodes[i];
|
|
if (!node->visible || node->id == 0 || node->user_type != 1 || !g_cube) continue;
|
|
float wvp_raw[16] = {0};
|
|
for (int r2 = 0; r2 < 4; r2++)
|
|
for (int c = 0; c < 4; c++)
|
|
wvp_raw[r2*4+c] = view[r2*4+0]*node->world_matrix.m[0][c]+view[r2*4+1]*node->world_matrix.m[1][c]+view[r2*4+2]*node->world_matrix.m[2][c]+view[r2*4+3]*node->world_matrix.m[3][c];
|
|
Mat4 wvp_m, wvp_t;
|
|
memcpy(&wvp_m, wvp_raw, sizeof(Mat4));
|
|
mat4_transpose(&wvp_m, &wvp_t);
|
|
shader_set_matrix(g_shader, ctx, (float*)&wvp_t);
|
|
mesh_draw(g_cube, ctx);
|
|
}
|
|
|
|
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 hI, HINSTANCE hP, LPSTR cmd, int nS) {
|
|
(void)hI;(void)hP;(void)cmd;(void)nS;
|
|
EngineConfig cfg = engine_default_config();
|
|
cfg.app_name = "lity3d Scene Test";
|
|
Engine* engine = engine_create();
|
|
if (!engine_init(engine, &cfg)) return -1;
|
|
g_dev = graphics_device_create();
|
|
if (!graphics_device_init(g_dev, window_get_handle(engine->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);
|
|
g_cube = mesh_create_cube(g_dev->device);
|
|
g_plane = mesh_create_plane(g_dev->device, 10.0f);
|
|
scene_init(&g_scene);
|
|
g_camera = scene_create_node(&g_scene, "Camera");
|
|
scene_set_position(g_camera, 5, 4, 8);
|
|
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); c3->user_type = 1; scene_set_scale(c3, 0.5f, 0.5f, 0.5f);
|
|
SceneNode* child = scene_create_node(&g_scene, "Child");
|
|
scene_set_position(child, 2, 0, 0); child->user_type = 1; scene_set_parent(child, c1);
|
|
engine_set_render_callback(engine, on_render);
|
|
engine_set_key_callback(engine, on_key);
|
|
engine_run(engine);
|
|
mesh_destroy(g_cube); mesh_destroy(g_plane); shader_destroy(g_shader);
|
|
graphics_device_destroy(g_dev); engine_shutdown(engine);
|
|
return 0;
|
|
}
|