MiMoEngine ASM: x86-64 MASM汇编+C混合架构游戏引擎

核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2)
外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言
含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
This commit is contained in:
shuiyu1123 committed 2026-07-10 19:20:40 +08:00
commit 2d56cb3bc9
91 files changed
+9988

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
#include "camera.h"
#include <math.h>
#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
Camera camera_perspective(float fov_y, float aspect, float near_z, float far_z) {
Camera cam = {0};
cam.type = CAMERA_PERSPECTIVE;
cam.position = (Vec3){0, 0, -5};
cam.target = (Vec3){0, 0, 0};
cam.up = (Vec3){0, 1, 0};
cam.fov_y = fov_y;
cam.aspect = aspect;
cam.near_z = near_z;
cam.far_z = far_z;
cam.dirty = 1;
return cam;
}
Camera camera_orthographic(float width, float height, float near_z, float far_z) {
Camera cam = {0};
cam.type = CAMERA_ORTHOGRAPHIC;
cam.position = (Vec3){0, 0, -5};
cam.target = (Vec3){0, 0, 0};
cam.up = (Vec3){0, 1, 0};
cam.ortho_width = width;
cam.ortho_height = height;
cam.near_z = near_z;
cam.far_z = far_z;
cam.dirty = 1;
return cam;
}
void camera_update(Camera* camera) {
if (!camera->dirty) return;
mat4_lookat(&camera->position, &camera->target, &camera->up, &camera->view);
if (camera->type == CAMERA_PERSPECTIVE) {
mat4_perspective(camera->fov_y, camera->aspect, camera->near_z, camera->far_z, &camera->projection);
} else {
mat4_orthographic(camera->ortho_width, camera->ortho_height, camera->near_z, camera->far_z, &camera->projection);
}
camera->dirty = 0;
}
const Mat4* camera_get_view(Camera* camera) {
camera_update(camera);
return &camera->view;
}
const Mat4* camera_get_projection(Camera* camera) {
camera_update(camera);
return &camera->projection;
}
void camera_move_forward(Camera* camera, float distance) {
Vec3 dir;
vec3_sub(&camera->target, &camera->position, &dir);
vec3_normalize(&dir, &dir);
Vec3 move;
vec3_scale(&dir, distance, &move);
vec3_add(&camera->position, &move, &camera->position);
vec3_add(&camera->target, &move, &camera->target);
camera->dirty = 1;
}
void camera_move_right(Camera* camera, float distance) {
Vec3 forward, right;
vec3_sub(&camera->target, &camera->position, &forward);
vec3_normalize(&forward, &forward);
vec3_cross(&forward, &camera->up, &right);
vec3_normalize(&right, &right);
Vec3 move;
vec3_scale(&right, distance, &move);
vec3_add(&camera->position, &move, &camera->position);
vec3_add(&camera->target, &move, &camera->target);
camera->dirty = 1;
}
void camera_move_up(Camera* camera, float distance) {
Vec3 move;
vec3_scale(&camera->up, distance, &move);
vec3_add(&camera->position, &move, &camera->position);
vec3_add(&camera->target, &move, &camera->target);
camera->dirty = 1;
}
void camera_rotate_yaw(Camera* camera, float angle) {
Vec3 forward;
vec3_sub(&camera->target, &camera->position, &forward);
float cs = cosf(angle), sn = sinf(angle);
Vec3 right;
vec3_cross(&forward, &camera->up, &right);
vec3_normalize(&right, &right);
Vec3 new_forward = {
forward.x * cs + right.x * sn,
forward.y * cs + right.y * sn,
forward.z * cs + right.z * sn,
};
vec3_add(&camera->position, &new_forward, &camera->target);
camera->dirty = 1;
}
void camera_rotate_pitch(Camera* camera, float angle) {
Vec3 forward;
vec3_sub(&camera->target, &camera->position, &forward);
Vec3 right;
vec3_cross(&forward, &camera->up, &right);
vec3_normalize(&right, &right);
float cs = cosf(angle), sn = sinf(angle);
Vec3 new_forward = {
forward.x * cs + camera->up.x * sn,
forward.y * cs + camera->up.y * sn,
forward.z * cs + camera->up.z * sn,
};
Vec3 new_up;
vec3_cross(&right, &new_forward, &new_up);
camera->up = new_up;
vec3_add(&camera->position, &new_forward, &camera->target);
camera->dirty = 1;
}
void camera_look_at(Camera* camera, Vec3 target) {
camera->target = target;
camera->dirty = 1;
}
+54
View File
@@ -0,0 +1,54 @@
#pragma once
// ============================================================================
// camera.h - 摄像机
// ============================================================================
#include "../include/engine_api.h"
#include "../ASM/math_c_fallback.h"
typedef enum {
CAMERA_PERSPECTIVE,
CAMERA_ORTHOGRAPHIC,
} CameraType;
typedef struct {
CameraType type;
Vec3 position;
Vec3 target;
Vec3 up;
float fov_y;
float aspect;
float near_z;
float far_z;
float ortho_width;
float ortho_height;
Mat4 view;
Mat4 projection;
int dirty;
} Camera;
// 创建默认透视摄像机
Camera camera_perspective(float fov_y, float aspect, float near_z, float far_z);
// 创建正交摄像机
Camera camera_orthographic(float width, float height, float near_z, float far_z);
// 更新矩阵
void camera_update(Camera* camera);
// 获取矩阵
const Mat4* camera_get_view(Camera* camera);
const Mat4* camera_get_projection(Camera* camera);
// 移动
void camera_move_forward(Camera* camera, float distance);
void camera_move_right(Camera* camera, float distance);
void camera_move_up(Camera* camera, float distance);
// 旋转
void camera_rotate_yaw(Camera* camera, float angle);
void camera_rotate_pitch(Camera* camera, float angle);
// 设置目标
void camera_look_at(Camera* camera, Vec3 target);
+98
View File
@@ -0,0 +1,98 @@
#include "graphics_device.h"
#include <stdlib.h>
#include <string.h>
GraphicsDevice* graphics_device_create(void) {
return (GraphicsDevice*)calloc(1, sizeof(GraphicsDevice));
}
void graphics_device_destroy(GraphicsDevice* d) {
if (!d) return;
if (d->depth_stencil) d->depth_stencil->lpVtbl->Release(d->depth_stencil);
if (d->depth_texture) d->depth_texture->lpVtbl->Release(d->depth_texture);
if (d->render_target) d->render_target->lpVtbl->Release(d->render_target);
if (d->swap_chain) d->swap_chain->lpVtbl->Release(d->swap_chain);
if (d->context) d->context->lpVtbl->Release(d->context);
if (d->device) d->device->lpVtbl->Release(d->device);
free(d);
}
static int create_depth_stencil(GraphicsDevice* d, uint32_t w, uint32_t h) {
D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = w; desc.Height = h;
desc.MipLevels = 1; desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
HRESULT hr = d->device->lpVtbl->CreateTexture2D(d->device, &desc, NULL, &d->depth_texture);
if (FAILED(hr)) return 0;
D3D11_DEPTH_STENCIL_VIEW_DESC dsv = {0};
dsv.Format = desc.Format;
dsv.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
hr = d->device->lpVtbl->CreateDepthStencilView(d->device, (ID3D11Resource*)d->depth_texture, &dsv, &d->depth_stencil);
return SUCCEEDED(hr);
}
int graphics_device_init(GraphicsDevice* d, void* hwnd, uint32_t w, uint32_t h, int vsync) {
d->width = w; d->height = h; d->vsync = vsync;
DXGI_SWAP_CHAIN_DESC scd = {0};
scd.BufferCount = 1;
scd.BufferDesc.Width = w;
scd.BufferDesc.Height = h;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.RefreshRate.Numerator = 60;
scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = (HWND)hwnd;
scd.SampleDesc.Count = 1;
scd.Windowed = TRUE;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
D3D_FEATURE_LEVEL levels[] = {D3D_FEATURE_LEVEL_11_0};
UINT flags = 0;
#ifdef _DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, 1, D3D11_SDK_VERSION, &scd, &d->swap_chain, &d->device, NULL, &d->context);
if (FAILED(hr)) return 0;
ID3D11Texture2D* back_buffer = NULL;
d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer);
d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target);
if (back_buffer) back_buffer->lpVtbl->Release(back_buffer);
create_depth_stencil(d, w, h);
d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil);
D3D11_VIEWPORT vp = {0};
vp.Width = (float)w; vp.Height = (float)h;
vp.MaxDepth = 1.0f;
d->context->lpVtbl->RSSetViewports(d->context, 1, &vp);
return 1;
}
void graphics_device_resize(GraphicsDevice* d, uint32_t w, uint32_t h) {
if (w == 0 || h == 0) return;
d->context->lpVtbl->OMSetRenderTargets(d->context, 0, NULL, NULL);
if (d->render_target) { d->render_target->lpVtbl->Release(d->render_target); d->render_target = NULL; }
if (d->depth_stencil) { d->depth_stencil->lpVtbl->Release(d->depth_stencil); d->depth_stencil = NULL; }
if (d->depth_texture) { d->depth_texture->lpVtbl->Release(d->depth_texture); d->depth_texture = NULL; }
d->swap_chain->lpVtbl->ResizeBuffers(d->swap_chain, 0, w, h, DXGI_FORMAT_UNKNOWN, 0);
ID3D11Texture2D* back_buffer = NULL;
d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer);
d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target);
if (back_buffer) back_buffer->lpVtbl->Release(back_buffer);
create_depth_stencil(d, w, h);
d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil);
D3D11_VIEWPORT vp = {0};
vp.Width = (float)w; vp.Height = (float)h; vp.MaxDepth = 1.0f;
d->context->lpVtbl->RSSetViewports(d->context, 1, &vp);
d->width = w; d->height = h;
}
void graphics_device_clear(GraphicsDevice* d, float r, float g, float b, float a) {
float color[4] = {r, g, b, a};
d->context->lpVtbl->ClearRenderTargetView(d->context, d->render_target, color);
d->context->lpVtbl->ClearDepthStencilView(d->context, d->depth_stencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
}
void graphics_device_present(GraphicsDevice* d) {
d->swap_chain->lpVtbl->Present(d->swap_chain, d->vsync ? 1 : 0, 0);
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <d3d11.h>
#include <dxgi.h>
#include <stdint.h>
typedef struct {
ID3D11Device* device;
ID3D11DeviceContext* context;
IDXGISwapChain* swap_chain;
ID3D11RenderTargetView* render_target;
ID3D11DepthStencilView* depth_stencil;
ID3D11Texture2D* depth_texture;
uint32_t width;
uint32_t height;
int vsync;
} GraphicsDevice;
GraphicsDevice* graphics_device_create(void);
void graphics_device_destroy(GraphicsDevice* d);
int graphics_device_init(GraphicsDevice* d, void* hwnd, uint32_t w, uint32_t h, int vsync);
void graphics_device_resize(GraphicsDevice* d, uint32_t w, uint32_t h);
void graphics_device_clear(GraphicsDevice* d, float r, float g, float b, float a);
void graphics_device_present(GraphicsDevice* d);
+110
View File
@@ -0,0 +1,110 @@
#include "mesh.h"
#include <stdlib.h>
#include <math.h>
#ifndef MATH_ASM_AVAILABLE
#include "../ASM/math_c_fallback.h"
#endif
#define POS(n,x,y,z,nx,ny,nz,u,v,r,g,b,a) {x,y,z, nx,ny,nz, u,v, r,g,b,a}
static Mesh* create_mesh(ID3D11Device* dev, const void* verts, uint32_t vc, const uint32_t* idx, uint32_t ic, uint32_t stride) {
Mesh* m = (Mesh*)calloc(1, sizeof(Mesh));
m->stride = stride; m->vcount = vc; m->icount = ic;
D3D11_BUFFER_DESC bd = {0};
D3D11_SUBRESOURCE_DATA sd = {0};
bd.ByteWidth = stride * vc; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
sd.pSysMem = verts;
dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &m->vb);
if (idx && ic > 0) {
bd.ByteWidth = sizeof(uint32_t) * ic; bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
sd.pSysMem = idx;
dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &m->ib);
}
return m;
}
void mesh_destroy(Mesh* m) {
if (!m) return;
if (m->ib) m->ib->lpVtbl->Release(m->ib);
if (m->vb) m->vb->lpVtbl->Release(m->vb);
free(m);
}
void mesh_draw(Mesh* m, ID3D11DeviceContext* ctx) {
UINT stride = m->stride, offset = 0;
ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &m->vb, &stride, &offset);
if (m->ib) {
ctx->lpVtbl->IASetIndexBuffer(ctx, m->ib, DXGI_FORMAT_R32_UINT, 0);
ctx->lpVtbl->DrawIndexed(ctx, m->icount, 0, 0);
} else {
ctx->lpVtbl->Draw(ctx, m->vcount, 0);
}
}
Mesh* mesh_create_cube(ID3D11Device* dev) {
typedef struct { float p[3], n[3], uv[2], c[4]; } V;
V v[24] = {
POS(0,-.5f,-.5f,-.5f, 0,0,-1, 0,1, 1,1,1,1), POS(1, .5f,-.5f,-.5f, 0,0,-1, 1,1, 1,1,1,1),
POS(2, .5f, .5f,-.5f, 0,0,-1, 1,0, 1,1,1,1), POS(3,-.5f, .5f,-.5f, 0,0,-1, 0,0, 1,1,1,1),
POS(4, .5f,-.5f, .5f, 0,0, 1, 0,1, 1,1,1,1), POS(5,-.5f,-.5f, .5f, 0,0, 1, 1,1, 1,1,1,1),
POS(6,-.5f, .5f, .5f, 0,0, 1, 1,0, 1,1,1,1), POS(7, .5f, .5f, .5f, 0,0, 1, 0,0, 1,1,1,1),
POS(8,-.5f, .5f,-.5f, 0,1, 0, 0,1, 1,1,1,1), POS(9, .5f, .5f,-.5f, 0,1, 0, 1,1, 1,1,1,1),
POS(10,.5f, .5f, .5f, 0,1, 0, 1,0, 1,1,1,1), POS(11,-.5f, .5f, .5f, 0,1, 0, 0,0, 1,1,1,1),
POS(12,-.5f,-.5f, .5f, 0,-1,0, 0,1, 1,1,1,1), POS(13,.5f,-.5f, .5f, 0,-1,0, 1,1, 1,1,1,1),
POS(14,.5f,-.5f,-.5f, 0,-1,0, 1,0, 1,1,1,1), POS(15,-.5f,-.5f,-.5f, 0,-1,0, 0,0, 1,1,1,1),
POS(16,.5f,-.5f,-.5f, 1,0, 0, 0,1, 1,1,1,1), POS(17,.5f,-.5f, .5f, 1,0, 0, 1,1, 1,1,1,1),
POS(18,.5f, .5f, .5f, 1,0, 0, 1,0, 1,1,1,1), POS(19,.5f, .5f,-.5f, 1,0, 0, 0,0, 1,1,1,1),
POS(20,-.5f,-.5f, .5f, -1,0,0, 0,1, 1,1,1,1), POS(21,-.5f,-.5f,-.5f, -1,0,0, 1,1, 1,1,1,1),
POS(22,-.5f, .5f,-.5f, -1,0,0, 1,0, 1,1,1,1), POS(23,-.5f, .5f, .5f, -1,0,0, 0,0, 1,1,1,1),
};
uint32_t idx[36];
for (int i = 0; i < 6; i++) { int b = i*4; idx[i*6]=b; idx[i*6+1]=b+1; idx[i*6+2]=b+2; idx[i*6+3]=b; idx[i*6+4]=b+2; idx[i*6+5]=b+3; }
return create_mesh(dev, v, 24, idx, 36, sizeof(V));
}
Mesh* mesh_create_plane(ID3D11Device* dev, float size) {
typedef struct { float p[3], n[3], uv[2], c[4]; } V;
float h = size * 0.5f;
V v[4] = {
{{-h,0,h},{0,1,0},{0,1},{1,1,1,1}},
{{ h,0,h},{0,1,0},{1,1},{1,1,1,1}},
{{ h,0,-h},{0,1,0},{1,0},{1,1,1,1}},
{{-h,0,-h},{0,1,0},{0,0},{1,1,1,1}},
};
uint32_t idx[6] = {0,1,2,0,2,3};
return create_mesh(dev, v, 4, idx, 6, sizeof(V));
}
Mesh* mesh_create_sphere(ID3D11Device* dev, float r, int seg) {
typedef struct { float p[3], n[3], uv[2], c[4]; } V;
int vc = (seg+1)*(seg+1);
V* v = (V*)malloc(vc * sizeof(V));
int vi = 0;
for (int lat = 0; lat <= seg; lat++) {
float theta = 3.14159265f * lat / seg;
float st = sinf(theta), ct = cosf(theta);
for (int lon = 0; lon <= seg; lon++) {
float phi = 2.0f * 3.14159265f * lon / seg;
float sp = sinf(phi), cp = cosf(phi);
float nx = cp*st, ny = ct, nz = sp*st;
v[vi].p[0] = nx*r; v[vi].p[1] = ny*r; v[vi].p[2] = nz*r;
v[vi].n[0] = nx; v[vi].n[1] = ny; v[vi].n[2] = nz;
v[vi].uv[0] = (float)lon/seg; v[vi].uv[1] = (float)lat/seg;
v[vi].c[0]=1; v[vi].c[1]=1; v[vi].c[2]=1; v[vi].c[3]=1;
vi++;
}
}
int ic = seg*seg*6;
uint32_t* idx = (uint32_t*)malloc(ic * sizeof(uint32_t));
int ii = 0;
for (int lat = 0; lat < seg; lat++) {
for (int lon = 0; lon < seg; lon++) {
uint32_t f = lat*(seg+1)+lon, s = f+seg+1;
idx[ii++]=f; idx[ii++]=s; idx[ii++]=f+1;
idx[ii++]=s; idx[ii++]=s+1; idx[ii++]=f+1;
}
}
Mesh* m = create_mesh(dev, v, vc, idx, ic, sizeof(V));
free(v); free(idx);
return m;
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <d3d11.h>
#include <stdint.h>
typedef struct {
float pos[3];
float norm[3];
float uv[2];
float color[4];
} Vertex;
typedef struct {
ID3D11Buffer* vb;
ID3D11Buffer* ib;
uint32_t vcount;
uint32_t icount;
uint32_t stride;
} Mesh;
Mesh* mesh_create_cube(ID3D11Device* dev);
Mesh* mesh_create_plane(ID3D11Device* dev, float size);
Mesh* mesh_create_sphere(ID3D11Device* dev, float r, int seg);
void mesh_destroy(Mesh* m);
void mesh_draw(Mesh* m, ID3D11DeviceContext* ctx);
+55
View File
@@ -0,0 +1,55 @@
#include "renderer.h"
#include <stdlib.h>
Renderer* renderer_create(GraphicsDevice* device) {
Renderer* r = (Renderer*)calloc(1, sizeof(Renderer));
r->device = device;
mat4_identity(&r->view);
mat4_identity(&r->projection);
r->light_dir = (Vec3){0.5f, -1.0f, 0.3f};
r->light_color = (Vec4){1,1,1,1};
r->ambient_color = (Vec4){0.2f,0.2f,0.3f,1};
return r;
}
void renderer_destroy(Renderer* r) { free(r); }
void renderer_begin_frame(Renderer* r) {
graphics_device_clear(r->device, 0.1f, 0.1f, 0.15f, 1.0f);
}
void renderer_end_frame(Renderer* r) {
graphics_device_present(r->device);
}
void renderer_draw_mesh(Renderer* r, Mesh* m) {
if (!m) return;
ID3D11DeviceContext* ctx = r->device->context;
UINT stride = sizeof(Vertex);
UINT offset = 0;
ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &m->vb, &stride, &offset);
if (m->ib) {
ctx->lpVtbl->IASetIndexBuffer(ctx, m->ib, DXGI_FORMAT_R32_UINT, 0);
ctx->lpVtbl->DrawIndexed(ctx, m->icount, 0, 0);
} else {
ctx->lpVtbl->Draw(ctx, m->vcount, 0);
}
}
void renderer_draw_mesh_with_shader(Renderer* r, Mesh* m, Shader* s, const Mat4* world, Texture* t) {
if (!m || !s) return;
ID3D11DeviceContext* ctx = r->device->context;
shader_bind(s, ctx);
renderer_draw_mesh(r, m);
}
void renderer_set_view(Renderer* r, const Mat4* v) { r->view = *v; }
void renderer_set_projection(Renderer* r, const Mat4* p) { r->projection = *p; }
void renderer_set_light(Renderer* r, Vec3 d, Vec4 c, Vec4 a) { r->light_dir=d; r->light_color=c; r->ambient_color=a; }
GraphicsDevice* renderer_get_device(Renderer* r) { return r ? r->device : NULL; }
void renderer_resize(Renderer* r, int width, int height) {
if (r && r->device && width > 0 && height > 0) {
graphics_device_resize(r->device, width, height);
}
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "graphics_device.h"
#include "shader.h"
#include "mesh.h"
#include "texture.h"
#include "camera.h"
#include "../include/engine_api.h"
#include "../ASM/math_c_fallback.h"
typedef struct {
GraphicsDevice* device;
Shader* current_shader;
Mat4 view;
Mat4 projection;
Vec3 light_dir;
Vec4 light_color;
Vec4 ambient_color;
} Renderer;
Renderer* renderer_create(GraphicsDevice* device);
void renderer_destroy(Renderer* renderer);
void renderer_begin_frame(Renderer* renderer);
void renderer_end_frame(Renderer* renderer);
void renderer_draw_mesh(Renderer* renderer, Mesh* mesh);
void renderer_draw_mesh_with_shader(Renderer* renderer, Mesh* mesh, Shader* shader, const Mat4* world, Texture* tex);
void renderer_set_view(Renderer* renderer, const Mat4* view);
void renderer_set_projection(Renderer* renderer, const Mat4* projection);
void renderer_set_light(Renderer* renderer, Vec3 dir, Vec4 color, Vec4 ambient);
GraphicsDevice* renderer_get_device(Renderer* renderer);
void renderer_resize(Renderer* renderer, int width, int height);
+74
View File
@@ -0,0 +1,74 @@
#include "shader.h"
#include <d3dcompiler.h>
#include <stdlib.h>
#include <string.h>
static const char* default_vs =
"struct VS_IN{float3 pos:POSITION;float3 n:NORMAL;float2 uv:TEXCOORD;float4 col:COLOR;};"
"struct PS_IN{float4 pos:SV_POSITION;float4 col:COLOR;};"
"cbuffer CB:register(b0){float4x4 WVP;};"
"PS_IN main(VS_IN i){PS_IN o;o.pos=mul(float4(i.pos,1),WVP);o.col=i.col;return o;}";
static const char* default_ps =
"struct PS_IN{float4 pos:SV_POSITION;float4 col:COLOR;};"
"float4 main(PS_IN i):SV_TARGET{return i.col;}";
static ID3DBlob* compile_shader(const char* code, uint32_t len, const char* target) {
ID3DBlob *blob = NULL, *err = NULL;
D3DCompile(code, len, NULL, NULL, NULL, "main", target, D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &blob, &err);
if (err) err->lpVtbl->Release(err);
return blob;
}
Shader* shader_create(void) {
return (Shader*)calloc(1, sizeof(Shader));
}
void shader_destroy(Shader* s) {
if (!s) return;
if (s->cb) s->cb->lpVtbl->Release(s->cb);
if (s->layout) s->layout->lpVtbl->Release(s->layout);
if (s->ps) s->ps->lpVtbl->Release(s->ps);
if (s->vs) s->vs->lpVtbl->Release(s->vs);
free(s);
}
int shader_compile(Shader* s, ID3D11Device* dev, const char* vs_code, const char* ps_code, uint32_t vs_len, uint32_t ps_len) {
if (!vs_code || !ps_code) {
vs_code = default_vs; ps_code = default_ps;
vs_len = (uint32_t)strlen(default_vs); ps_len = (uint32_t)strlen(default_ps);
}
ID3DBlob* vs_blob = compile_shader(vs_code, vs_len, "vs_5_0");
ID3DBlob* ps_blob = compile_shader(ps_code, ps_len, "ps_5_0");
if (!vs_blob || !ps_blob) {
if (vs_blob) vs_blob->lpVtbl->Release(vs_blob);
if (ps_blob) ps_blob->lpVtbl->Release(ps_blob);
return 0;
}
dev->lpVtbl->CreateVertexShader(dev, vs_blob->lpVtbl->GetBufferPointer(vs_blob), vs_blob->lpVtbl->GetBufferSize(vs_blob), NULL, &s->vs);
dev->lpVtbl->CreatePixelShader(dev, ps_blob->lpVtbl->GetBufferPointer(ps_blob), ps_blob->lpVtbl->GetBufferSize(ps_blob), NULL, &s->ps);
D3D11_INPUT_ELEMENT_DESC layout[] = {
{"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, layout, 4, vs_blob->lpVtbl->GetBufferPointer(vs_blob), vs_blob->lpVtbl->GetBufferSize(vs_blob), &s->layout);
D3D11_BUFFER_DESC bd = {0};
bd.ByteWidth = 256; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
dev->lpVtbl->CreateBuffer(dev, &bd, NULL, &s->cb);
vs_blob->lpVtbl->Release(vs_blob);
ps_blob->lpVtbl->Release(ps_blob);
return 1;
}
void shader_bind(Shader* s, ID3D11DeviceContext* ctx) {
ctx->lpVtbl->VSSetShader(ctx, s->vs, NULL, 0);
ctx->lpVtbl->PSSetShader(ctx, s->ps, NULL, 0);
ctx->lpVtbl->IASetInputLayout(ctx, s->layout);
ctx->lpVtbl->VSSetConstantBuffers(ctx, 0, 1, &s->cb);
}
void shader_set_matrix(Shader* s, ID3D11DeviceContext* ctx, const float* data) {
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)s->cb, 0, NULL, data, 0, 0);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <d3d11.h>
#include <stdint.h>
typedef struct {
ID3D11VertexShader* vs;
ID3D11PixelShader* ps;
ID3D11InputLayout* layout;
ID3D11Buffer* cb;
} Shader;
Shader* shader_create(void);
void shader_destroy(Shader* s);
int shader_compile(Shader* s, ID3D11Device* dev, const char* vs_code, const char* ps_code, uint32_t vs_len, uint32_t ps_len);
void shader_bind(Shader* s, ID3D11DeviceContext* ctx);
void shader_set_matrix(Shader* s, ID3D11DeviceContext* ctx, const float* data);
+188
View File
@@ -0,0 +1,188 @@
#include "texture.h"
#include <wincodec.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "windowscodecs.lib")
static IWICImagingFactory* wic_factory = NULL;
static HRESULT ensure_wic(void) {
if (wic_factory) return S_OK;
return CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICImagingFactory, (void**)&wic_factory);
}
Texture* texture_create(void) {
return (Texture*)calloc(1, sizeof(Texture));
}
void texture_destroy(Texture* texture) {
if (!texture) return;
if (texture->srv) ID3D11ShaderResourceView_Release(texture->srv);
if (texture->texture) ID3D11Texture2D_Release(texture->texture);
free(texture);
}
static Texture* create_from_wic(ID3D11Device* device, IWICBitmapDecoder* decoder) {
IWICBitmapFrameDecode* frame = NULL;
IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
uint32_t w, h;
IWICBitmapFrameDecode_GetSize(frame, &w, &h);
IWICFormatConverter* converter = NULL;
IWICImagingFactory_CreateFormatConverter(wic_factory, &converter);
IWICFormatConverter_Initialize(converter, (IWICBitmapSource*)frame,
&GUID_WICPixelFormat32bppRGBA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom);
uint8_t* pixels = (uint8_t*)malloc(w * h * 4);
IWICFormatConverter_CopyPixels(converter, NULL, w * 4, w * h * 4, pixels);
IWICFormatConverter_Release(converter);
IWICBitmapFrameDecode_Release(frame);
D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = w;
desc.Height = h;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
D3D11_SUBRESOURCE_DATA init = {pixels, w * 4, 0};
Texture* tex = texture_create();
ID3D11Device_CreateTexture2D(device, &desc, &init, &tex->texture);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd = {0};
srvd.Format = desc.Format;
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvd.Texture2D.MipLevels = 1;
ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource*)tex->texture, &srvd, &tex->srv);
tex->width = w;
tex->height = h;
tex->mip_levels = 1;
free(pixels);
return tex;
}
Texture* texture_load_from_file(ID3D11Device* device, const char* path) {
if (FAILED(ensure_wic())) return NULL;
IWICBitmapDecoder* decoder = NULL;
wchar_t wpath[512];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, 512);
HRESULT hr = IWICImagingFactory_CreateDecoderFromFilename(wic_factory, wpath, NULL,
GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);
if (FAILED(hr)) return NULL;
Texture* tex = create_from_wic(device, decoder);
IWICBitmapDecoder_Release(decoder);
return tex;
}
Texture* texture_load_from_memory(ID3D11Device* device, const uint8_t* data, uint32_t size) {
if (FAILED(ensure_wic())) return NULL;
IWICStream* stream = NULL;
IWICImagingFactory_CreateStream(wic_factory, &stream);
IWICStream_InitializeFromMemory(stream, (BYTE*)data, size);
IWICBitmapDecoder* decoder = NULL;
IWICImagingFactory_CreateDecoderFromStream(wic_factory, (IStream*)stream, NULL,
WICDecodeMetadataCacheOnLoad, &decoder);
IWICStream_Release(stream);
if (!decoder) return NULL;
Texture* tex = create_from_wic(device, decoder);
IWICBitmapDecoder_Release(decoder);
return tex;
}
Texture* texture_create_solid(ID3D11Device* device, uint32_t w, uint32_t h,
uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
uint8_t* pixels = (uint8_t*)malloc(w * h * 4);
for (uint32_t i = 0; i < w * h; i++) {
pixels[i * 4 + 0] = r;
pixels[i * 4 + 1] = g;
pixels[i * 4 + 2] = b;
pixels[i * 4 + 3] = a;
}
D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = w;
desc.Height = h;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
D3D11_SUBRESOURCE_DATA init = {pixels, w * 4, 0};
Texture* tex = texture_create();
ID3D11Device_CreateTexture2D(device, &desc, &init, &tex->texture);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd = {0};
srvd.Format = desc.Format;
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvd.Texture2D.MipLevels = 1;
ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource*)tex->texture, &srvd, &tex->srv);
tex->width = w;
tex->height = h;
free(pixels);
return tex;
}
Texture* texture_create_checkerboard(ID3D11Device* device, uint32_t size, uint32_t checks) {
uint8_t* pixels = (uint8_t*)malloc(size * size * 4);
uint32_t cell = size / checks;
for (uint32_t y = 0; y < size; y++) {
for (uint32_t x = 0; x < size; x++) {
uint8_t c = ((x / cell) + (y / cell)) % 2 ? 200 : 55;
uint32_t i = (y * size + x) * 4;
pixels[i] = pixels[i + 1] = pixels[i + 2] = c;
pixels[i + 3] = 255;
}
}
D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = size;
desc.Height = size;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
D3D11_SUBRESOURCE_DATA init = {pixels, size * 4, 0};
Texture* tex = texture_create();
ID3D11Device_CreateTexture2D(device, &desc, &init, &tex->texture);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd = {0};
srvd.Format = desc.Format;
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvd.Texture2D.MipLevels = 1;
ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource*)tex->texture, &srvd, &tex->srv);
tex->width = size;
tex->height = size;
free(pixels);
return tex;
}
void texture_bind(Texture* texture, ID3D11DeviceContext* ctx, uint32_t slot) {
if (!texture || !texture->srv) return;
ID3D11DeviceContext_PSSetShaderResources(ctx, slot, 1, &texture->srv);
ID3D11DeviceContext_PSSetSamplers(ctx, slot, 1, &(ID3D11SamplerState*){NULL});
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
// ============================================================================
// texture.h - 纹理加载 (WIC)
// ============================================================================
#include <d3d11.h>
#include <stdint.h>
typedef struct {
ID3D11Texture2D* texture;
ID3D11ShaderResourceView* srv;
uint32_t width;
uint32_t height;
uint32_t mip_levels;
} Texture;
// 创建/销毁
Texture* texture_create(void);
void texture_destroy(Texture* texture);
// 从文件加载
Texture* texture_load_from_file(ID3D11Device* device, const char* path);
// 从内存加载
Texture* texture_load_from_memory(ID3D11Device* device,
const uint8_t* data, uint32_t size);
// 创建纯色纹理
Texture* texture_create_solid(ID3D11Device* device, uint32_t w, uint32_t h,
uint8_t r, uint8_t g, uint8_t b, uint8_t a);
// 创建棋盘格
Texture* texture_create_checkerboard(ID3D11Device* device, uint32_t size, uint32_t checks);
// 绑定
void texture_bind(Texture* texture, ID3D11DeviceContext* ctx, uint32_t slot);