// light_test.c - 光照系统测试(基ï¿?raw3d_test 已验证模式) #include "../Engine/Core/engine.h" #include "../Engine/Window/window.h" #include "../Engine/Rendering/graphics_device.h" #include "../Engine/Rendering/shader.h" #include "../Engine/Rendering/lighting.h" #include "../Engine/include/engine_api.h" #include "../Engine/ASM/math_c_fallback.h" #include static GraphicsDevice* g_dev = NULL; static Light* g_sun = NULL; static float g_time = 0; typedef struct { float p[3],n[3],uv[2],c[4]; } V; // 编译带光照的着色器 static ID3D11VertexShader* g_vs = NULL; static ID3D11PixelShader* g_ps = NULL; static ID3D11InputLayout* g_il = NULL; static ID3D11Buffer* g_cb = NULL; static const char* vs_src = "cbuffer CB:register(b0){float4x4 WVP;};" "struct I{float3 p:POSITION;float3 n:NORMAL;float2 u:TEXCOORD;float4 c:COLOR;};" "struct O{float4 p:SV_POSITION;float3 n:NORMAL;float4 c:COLOR;};" "O main(I i){O o;o.p=mul(float4(i.p,1),WVP);o.n=i.n;o.c=i.c;return o;}"; static const char* ps_src = "cbuffer Light:register(b1){float3 lightDir;float pad1;float3 lightColor;float intensity;float3 ambColor;float pad2;};" "struct O{float4 p:SV_POSITION;float3 n:NORMAL;float4 c:COLOR;};" "float4 main(O i):SV_TARGET{" "float3 n=normalize(i.n);" "float diff=max(dot(n,-normalize(lightDir)),0.0);" "float3 col=i.c.rgb*(ambColor+lightColor*diff*intensity);" "return float4(col,1.0);}"; static void InitShaders() { ID3DBlob *b1=NULL,*b2=NULL,*e=NULL; D3DCompile(vs_src,(UINT)strlen(vs_src),NULL,NULL,NULL,"main","vs_5_0",0,0,&b1,&e); if(e){e->lpVtbl->Release(e);e=NULL;} D3DCompile(ps_src,(UINT)strlen(ps_src),NULL,NULL,NULL,"main","ps_5_0",0,0,&b2,&e); if(e){e->lpVtbl->Release(e);e=NULL;} if(!b1||!b2) return; ID3D11Device* dev = g_dev->device; dev->lpVtbl->CreateVertexShader(dev,b1->lpVtbl->GetBufferPointer(b1),b1->lpVtbl->GetBufferSize(b1),NULL,&g_vs); dev->lpVtbl->CreatePixelShader(dev,b2->lpVtbl->GetBufferPointer(b2),b2->lpVtbl->GetBufferSize(b2),NULL,&g_ps); D3D11_INPUT_ELEMENT_DESC il[]={ {"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}, }; dev->lpVtbl->CreateInputLayout(dev,il,4,b1->lpVtbl->GetBufferPointer(b1),b1->lpVtbl->GetBufferSize(b1),&g_il); b1->lpVtbl->Release(b1); b2->lpVtbl->Release(b2); D3D11_BUFFER_DESC cbd={}; cbd.ByteWidth=256; cbd.Usage=D3D11_USAGE_DEFAULT; cbd.BindFlags=D3D11_BIND_CONSTANT_BUFFER; dev->lpVtbl->CreateBuffer(dev,&cbd,NULL,&g_cb); } static void draw_lit_cube(ID3D11DeviceContext* ctx, ID3D11Device* dev, float cx, float cy, float cz, float s, float cr, float cg, float cb) { V v[24]; float f[6][4][3]={{{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1}},{{1,-1,-1},{1,-1,1},{1,1,1},{1,1,-1}}, {{1,-1,1},{-1,-1,1},{-1,1,1},{1,1,1}},{{-1,-1,1},{-1,-1,-1},{-1,1,-1},{-1,1,1}}, {{-1,1,-1},{1,1,-1},{1,1,1},{-1,1,1}},{{-1,-1,1},{1,-1,1},{1,-1,-1},{-1,-1,-1}}}; float nm[6][3]={{0,0,-1},{1,0,0},{0,0,1},{-1,0,0},{0,1,0},{0,-1,0}}; for(int fi=0;fi<6;fi++) for(int vi=0;vi<4;vi++){ int i=fi*4+vi; v[i].p[0]=f[fi][vi][0]*s+cx; v[i].p[1]=f[fi][vi][1]*s+cy; v[i].p[2]=f[fi][vi][2]*s+cz; v[i].n[0]=nm[fi][0]; v[i].n[1]=nm[fi][1]; v[i].n[2]=nm[fi][2]; v[i].c[0]=cr; v[i].c[1]=cg; v[i].c[2]=cb; v[i].c[3]=1; } uint32_t idx[36]; for(int fi=0;fi<6;fi++){int b=fi*4;idx[fi*6]=b;idx[fi*6+1]=b+1;idx[fi*6+2]=b+2;idx[fi*6+3]=b;idx[fi*6+4]=b+2;idx[fi*6+5]=b+3;} ID3D11Buffer *vb,*ib;D3D11_BUFFER_DESC bd={};D3D11_SUBRESOURCE_DATA sd={}; bd.ByteWidth=sizeof(V)*24;bd.Usage=D3D11_USAGE_DEFAULT;bd.BindFlags=D3D11_BIND_VERTEX_BUFFER;sd.pSysMem=v; dev->lpVtbl->CreateBuffer(dev,&bd,&sd,&vb); bd.ByteWidth=sizeof(uint32_t)*36;bd.BindFlags=D3D11_BIND_INDEX_BUFFER;sd.pSysMem=idx; dev->lpVtbl->CreateBuffer(dev,&bd,&sd,&ib); UINT s2=sizeof(V),o=0; ctx->lpVtbl->IASetVertexBuffers(ctx,0,1,&vb,&s2,&o); ctx->lpVtbl->IASetIndexBuffer(ctx,ib,DXGI_FORMAT_R32_UINT,0); ctx->lpVtbl->DrawIndexed(ctx,36,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; g_time+=0.016f; float sw=(float)g_dev->width,sh=(float)g_dev->height; float fov=1.0f/tanf(0.4f),asp=sw/sh; float mvp[16]={0}; mvp[0]=fov/asp;mvp[5]=-fov;mvp[10]=1;mvp[11]=-1;mvp[14]=0.1f;mvp[15]=1; Mat4 pm,pt;memcpy(&pm,mvp,sizeof(Mat4));mat4_transpose(&pm,&pt); 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,&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,&dsd,&dss); ctx->lpVtbl->OMSetDepthStencilState(ctx,dss,0); ctx->lpVtbl->IASetPrimitiveTopology(ctx,D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 绑定光照 shader ctx->lpVtbl->VSSetShader(ctx,g_vs,NULL,0); ctx->lpVtbl->PSSetShader(ctx,g_ps,NULL,0); ctx->lpVtbl->IASetInputLayout(ctx,g_il); ctx->lpVtbl->VSSetConstantBuffers(ctx,0,1,&g_cb); ctx->lpVtbl->UpdateSubresource(ctx,(ID3D11Resource*)g_cb,0,NULL,&pt,0,0); // 更新光照 CB float light_data[16]={0}; light_data[0]=g_sun->direction[0];light_data[1]=g_sun->direction[1];light_data[2]=g_sun->direction[2]; light_data[4]=g_sun->color[0];light_data[5]=g_sun->color[1];light_data[6]=g_sun->color[2]; light_data[7]=g_sun->intensity; light_data[8]=0.15f;light_data[9]=0.15f;light_data[10]=0.2f; ctx->lpVtbl->VSSetConstantBuffers(ctx,1,1,&g_cb); draw_lit_cube(ctx,g_dev, 0,0,0.5f, 0.3f, 1,0.3f,0.3f); draw_lit_cube(ctx,g_dev,-0.8f,0,0.7f, 0.2f, 0.3f,1,0.3f); draw_lit_cube(ctx,g_dev, 0.8f,0.3f,0.3f, 0.15f, 0.3f,0.3f,1); draw_lit_cube(ctx,g_dev, 0,-0.2f,0.8f, 0.4f, 0.8f,0.8f,0.2f); if(rs)rs->lpVtbl->Release(rs);if(dss)dss->lpVtbl->Release(dss); graphics_device_present(g_dev); } static void on_key(Engine*e,int k){if(k==VK_ESCAPE)engine_request_quit(e);} int WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int){ EngineConfig cfg=engine_default_config();cfg.app_name="lity3d Light Test"; 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; InitShaders(); g_sun=light_create_dir(1.0f,0.95f,0.8f,1.2f, -0.5f,-1.0f,-0.3f); engine_set_render_callback(e,on_render);engine_set_key_callback(e,on_key); engine_run(e); light_destroy(g_sun);graphics_device_destroy(g_dev);engine_shutdown(e); return 0; }