- Scene Demo: cube + sphere + ground plane with proper lighting - Audio: XAudio2 dynamic loading + WAV playback - Physics: expanded collision system - Renderer: improved pipeline with materials - UI: extended widget system - VisualScript: enhanced serializer + block interactions - ASM: optimized math/memory/profiling routines - Window: mouse input + scroll support
191 lines
8.3 KiB
C
191 lines
8.3 KiB
C
#include "block_renderer.h"
|
|
#include "block_core.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
// 5x7 位图字体 (列优先, LSB 在上)
|
|
#include "block_font.inc"
|
|
|
|
int block_renderer_init(BlockRenderer* renderer, void* device, void* context) {
|
|
memset(renderer, 0, sizeof(BlockRenderer));
|
|
renderer->device = (ID3D11Device*)device;
|
|
renderer->context = (ID3D11DeviceContext*)context;
|
|
renderer->vertex_capacity = 65536;
|
|
renderer->vertex_data = (float*)malloc(renderer->vertex_capacity * 7 * sizeof(float));
|
|
renderer->index_capacity = 65536;
|
|
renderer->index_data = (uint32_t*)malloc(renderer->index_capacity * sizeof(uint32_t));
|
|
return 1;
|
|
}
|
|
|
|
void block_renderer_shutdown(BlockRenderer* renderer) {
|
|
if (renderer->vertex_data) free(renderer->vertex_data);
|
|
if (renderer->index_data) free(renderer->index_data);
|
|
if (renderer->vertex_buffer) renderer->vertex_buffer->lpVtbl->Release(renderer->vertex_buffer);
|
|
if (renderer->index_buffer) renderer->index_buffer->lpVtbl->Release(renderer->index_buffer);
|
|
if (renderer->vertex_shader) renderer->vertex_shader->lpVtbl->Release(renderer->vertex_shader);
|
|
if (renderer->pixel_shader) renderer->pixel_shader->lpVtbl->Release(renderer->pixel_shader);
|
|
if (renderer->input_layout) renderer->input_layout->lpVtbl->Release(renderer->input_layout);
|
|
memset(renderer, 0, sizeof(BlockRenderer));
|
|
}
|
|
|
|
void block_renderer_begin(BlockRenderer* renderer) {
|
|
renderer->vertex_count = 0;
|
|
renderer->index_count = 0;
|
|
}
|
|
|
|
void block_renderer_end(BlockRenderer* renderer) {
|
|
if (renderer->vertex_count == 0) return;
|
|
ID3D11DeviceContext* ctx = renderer->context;
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
|
if (SUCCEEDED(ctx->lpVtbl->Map(ctx, (ID3D11Resource*)renderer->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) {
|
|
memcpy(mapped.pData, renderer->vertex_data, renderer->vertex_count * 7 * sizeof(float));
|
|
ctx->lpVtbl->Unmap(ctx, (ID3D11Resource*)renderer->vertex_buffer, 0);
|
|
}
|
|
|
|
if (renderer->index_count > 0) {
|
|
if (SUCCEEDED(ctx->lpVtbl->Map(ctx, (ID3D11Resource*)renderer->index_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) {
|
|
memcpy(mapped.pData, renderer->index_data, renderer->index_count * sizeof(uint32_t));
|
|
ctx->lpVtbl->Unmap(ctx, (ID3D11Resource*)renderer->index_buffer, 0);
|
|
}
|
|
}
|
|
|
|
UINT stride = 7 * sizeof(float);
|
|
UINT offset = 0;
|
|
ID3D11Buffer* vb = renderer->vertex_buffer;
|
|
ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &vb, &stride, &offset);
|
|
|
|
if (renderer->index_buffer) {
|
|
ctx->lpVtbl->IASetIndexBuffer(ctx, renderer->index_buffer, DXGI_FORMAT_R32_UINT, 0);
|
|
}
|
|
ctx->lpVtbl->IASetInputLayout(ctx, renderer->input_layout);
|
|
ctx->lpVtbl->IASetPrimitiveTopology(ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
ctx->lpVtbl->VSSetShader(ctx, renderer->vertex_shader, NULL, 0);
|
|
ctx->lpVtbl->PSSetShader(ctx, renderer->pixel_shader, NULL, 0);
|
|
|
|
if (renderer->index_count > 0) {
|
|
ctx->lpVtbl->DrawIndexed(ctx, renderer->index_count, 0, 0);
|
|
} else {
|
|
ctx->lpVtbl->Draw(ctx, renderer->vertex_count, 0);
|
|
}
|
|
}
|
|
|
|
void block_renderer_add_quad(BlockRenderer* renderer, float x, float y, float w, float h, float r, float g, float b, float a) {
|
|
if (renderer->vertex_count + 4 > renderer->vertex_capacity) return;
|
|
if (renderer->index_count + 6 > renderer->index_capacity) return;
|
|
|
|
uint32_t base = renderer->vertex_count;
|
|
float* v = renderer->vertex_data + base * 7;
|
|
|
|
v[0*7+0] = x; v[0*7+1] = y; v[0*7+2] = 0; v[0*7+3] = r; v[0*7+4] = g; v[0*7+5] = b; v[0*7+6] = a;
|
|
v[1*7+0] = x + w; v[1*7+1] = y; v[1*7+2] = 0; v[1*7+3] = r; v[1*7+4] = g; v[1*7+5] = b; v[1*7+6] = a;
|
|
v[2*7+0] = x + w; v[2*7+1] = y + h; v[2*7+2] = 0; v[2*7+3] = r; v[2*7+4] = g; v[2*7+5] = b; v[2*7+6] = a;
|
|
v[3*7+0] = x; v[3*7+1] = y + h; v[3*7+2] = 0; v[3*7+3] = r; v[3*7+4] = g; v[3*7+5] = b; v[3*7+6] = a;
|
|
|
|
renderer->vertex_count += 4;
|
|
|
|
renderer->index_data[renderer->index_count++] = base + 0;
|
|
renderer->index_data[renderer->index_count++] = base + 1;
|
|
renderer->index_data[renderer->index_count++] = base + 2;
|
|
renderer->index_data[renderer->index_count++] = base + 0;
|
|
renderer->index_data[renderer->index_count++] = base + 2;
|
|
renderer->index_data[renderer->index_count++] = base + 3;
|
|
}
|
|
|
|
void block_renderer_add_line(BlockRenderer* renderer, float x1, float y1, float x2, float y2, float r, float g, float b, float a) {
|
|
float dx = x2 - x1;
|
|
float dy = y2 - y1;
|
|
float len = sqrtf(dx * dx + dy * dy);
|
|
if (len < 0.001f) return;
|
|
|
|
const float thickness = 1.0f;
|
|
float nx = -dy / len * thickness * 0.5f;
|
|
float ny = dx / len * thickness * 0.5f;
|
|
|
|
if (renderer->vertex_count + 4 > renderer->vertex_capacity) return;
|
|
if (renderer->index_count + 6 > renderer->index_capacity) return;
|
|
|
|
uint32_t base = renderer->vertex_count;
|
|
float* v = renderer->vertex_data + base * 7;
|
|
|
|
v[0*7+0] = x1 + nx; v[0*7+1] = y1 + ny; v[0*7+2] = 0; v[0*7+3] = r; v[0*7+4] = g; v[0*7+5] = b; v[0*7+6] = a;
|
|
v[1*7+0] = x2 + nx; v[1*7+1] = y2 + ny; v[1*7+2] = 0; v[1*7+3] = r; v[1*7+4] = g; v[1*7+5] = b; v[1*7+6] = a;
|
|
v[2*7+0] = x2 - nx; v[2*7+1] = y2 - ny; v[2*7+2] = 0; v[2*7+3] = r; v[2*7+4] = g; v[2*7+5] = b; v[2*7+6] = a;
|
|
v[3*7+0] = x1 - nx; v[3*7+1] = y1 - ny; v[3*7+2] = 0; v[3*7+3] = r; v[3*7+4] = g; v[3*7+5] = b; v[3*7+6] = a;
|
|
|
|
renderer->vertex_count += 4;
|
|
|
|
renderer->index_data[renderer->index_count++] = base + 0;
|
|
renderer->index_data[renderer->index_count++] = base + 1;
|
|
renderer->index_data[renderer->index_count++] = base + 2;
|
|
renderer->index_data[renderer->index_count++] = base + 0;
|
|
renderer->index_data[renderer->index_count++] = base + 2;
|
|
renderer->index_data[renderer->index_count++] = base + 3;
|
|
}
|
|
|
|
static void block_renderer_add_bezier(BlockRenderer* renderer, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, float r, float g, float b, float a) {
|
|
int segments = 16;
|
|
float prev_x = x1, prev_y = y1;
|
|
for (int i = 1; i <= segments; i++) {
|
|
float t = (float)i / segments;
|
|
float mt = 1.0f - t;
|
|
float px = mt*mt*mt*x1 + 3*mt*mt*t*cx1 + 3*mt*t*t*cx2 + t*t*t*x2;
|
|
float py = mt*mt*mt*y1 + 3*mt*mt*t*cy1 + 3*mt*t*t*cy2 + t*t*t*y2;
|
|
block_renderer_add_line(renderer, prev_x, prev_y, px, py, r, g, b, a);
|
|
prev_x = px;
|
|
prev_y = py;
|
|
}
|
|
}
|
|
|
|
void block_renderer_draw_block(BlockRenderer* renderer, Block* block, float view_x, float view_y, float zoom) {
|
|
float x = (block->x - view_x) * zoom;
|
|
float y = (block->y - view_y) * zoom;
|
|
float w = block->width * zoom;
|
|
float h = block->height * zoom;
|
|
|
|
block_renderer_add_quad(renderer, x, y, w, h, 0.3f, 0.3f, 0.35f, 1.0f);
|
|
block_renderer_add_quad(renderer, x, y, w, 20 * zoom, 0.2f, 0.2f, 0.25f, 1.0f);
|
|
|
|
if (block->label[0]) {
|
|
block_renderer_draw_text(renderer, block->label, x + 4.0f * zoom, y + 4.0f * zoom, 0.9f, 0.9f, 0.9f);
|
|
}
|
|
}
|
|
|
|
void block_renderer_draw_connection(BlockRenderer* renderer, BlockSlot* from, BlockSlot* to, float view_x, float view_y, float zoom) {
|
|
float x1 = (from->owner->x + from->x - view_x) * zoom;
|
|
float y1 = (from->owner->y + from->y - view_y) * zoom;
|
|
float x2 = (to->owner->x + to->x - view_x) * zoom;
|
|
float y2 = (to->owner->y + to->y - view_y) * zoom;
|
|
|
|
float dx = fabsf(x2 - x1) * 0.5f;
|
|
if (dx < 50.0f) dx = 50.0f;
|
|
|
|
block_renderer_add_bezier(renderer, x1, y1, x1 + dx, y1, x2 - dx, y2, x2, y2, 0.8f, 0.8f, 0.2f, 1.0f);
|
|
}
|
|
|
|
void block_renderer_draw_text(BlockRenderer* renderer, const char* text, float x, float y, float r, float g, float b) {
|
|
if (!text) return;
|
|
const float scale = 2.0f;
|
|
const float advance = 5.0f * scale + 1.0f;
|
|
float cx = x;
|
|
for (const char* p = text; *p; ++p) {
|
|
unsigned char ch = (unsigned char)*p;
|
|
if (ch < 32 || ch > 127) ch = '?';
|
|
int idx = ch - 32;
|
|
for (int col = 0; col < 5; ++col) {
|
|
uint8_t column = BLOCK_FONT[idx][col];
|
|
for (int row = 0; row < 7; ++row) {
|
|
if (column & (1u << row)) {
|
|
block_renderer_add_quad(renderer,
|
|
cx + col * scale,
|
|
y + row * scale,
|
|
scale, scale,
|
|
r, g, b, 1.0f);
|
|
}
|
|
}
|
|
}
|
|
cx += advance;
|
|
}
|
|
}
|