Files
lity3d/Demo/light_test.c
T

143 lines
7.1 KiB
C

// 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 <d3dcompiler.h>
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;
}