143 lines
7.1 KiB
C
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;
|
|
}
|