native render: transliterate D3D8 fixed-function pipeline (unit A)
- Texture coordinates: TEXCOORDINDEX generation (camera-space normal / position / reflection vector, LOCALVIEWER) and D3DTS_TEXTUREn under TEXTURETRANSFORMFLAGS (incl. PROJECTED) now run in native.vert; the RecordingDevice CPU uv baking and the sphere-map / multiplicative-shadow shader hacks are removed. Godot consumer uses Render3DStageTexcoords. - Lighting: 8 D3D lights in camera space, 1/(a0+a1d+a2d^2) without clamp, spot cone theta/2 phi/2 with falloff, diffuse/ambient/emissive material sources, NORMALIZENORMALS, inverse-transpose normal matrix. - Alpha test compares 8-bit alpha against ALPHAREF with ALPHAFUNC. - Back-buffer Clear() is recorded in draw order and executed with vkCmdClearAttachments; render pass clears to 0xff000000. - D3DVIEWPORT8 (incl. MinZ/MaxZ) is dynamic per-draw state. - Missing vertex diffuse is opaque white; alpha blend mirrors SRC/DESTBLEND. - CScreen::ms_clearDepth / ms_diffuseColor initialised to 40250's 1.0f / 0xffffffff (were zero; exposed once clears were executed). - Capture format v8; --screenshot-out FILE.bmp swapchain readback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
425e6f37fb
commit
5285ca85fd
@@ -403,6 +403,8 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
out.resize(static_cast<int64_t>(draws.size()));
|
||||
int64_t draw_index = 0;
|
||||
for (const Render3DDraw &draw : draws) {
|
||||
if (draw.clear_flags)
|
||||
continue; // back-buffer clears are consumed by the native renderer only
|
||||
Dictionary item;
|
||||
item["geometry_key"] = static_cast<int64_t>(draw.geometry_key);
|
||||
item["geometry_revision"] = static_cast<int64_t>(draw.geometry_revision);
|
||||
@@ -414,8 +416,14 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
item["pretransformed"] = draw.pretransformed;
|
||||
item["lines"] = draw.lines;
|
||||
|
||||
// Stage-0 coordinates the D3D8 pipeline generates or transforms depend on per-draw matrices,
|
||||
// so such draws carry them outside the geometry cache.
|
||||
const bool stage0_texgen = (draw.texcoord_index[0] & 0xFFFF0000u) != 0 ||
|
||||
(draw.texcoord_index[0] & 0xFFFFu) != 0 || draw.texture_transform_flags[0] != 0;
|
||||
if (stage0_texgen)
|
||||
item["geometry_key"] = static_cast<int64_t>(0);
|
||||
Dictionary geometry;
|
||||
if (draw.geometry_key != 0) {
|
||||
if (draw.geometry_key != 0 && !stage0_texgen) {
|
||||
auto cached = geometry_cache.find(draw.geometry_key);
|
||||
if (cached != geometry_cache.end() && cached->second.revision == draw.geometry_revision) {
|
||||
cached->second.last_used = extraction;
|
||||
@@ -461,7 +469,11 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
}
|
||||
return out;
|
||||
};
|
||||
if (!draw.uv0.empty())
|
||||
if (stage0_texgen) {
|
||||
std::vector<float> stage_uv;
|
||||
Render3DStageTexcoords(draw, 0, stage_uv);
|
||||
geometry["uv0"] = uvs(stage_uv);
|
||||
} else if (!draw.uv0.empty())
|
||||
geometry["uv0"] = uvs(draw.uv0);
|
||||
if (!draw.uv1.empty())
|
||||
geometry["uv1"] = uvs(draw.uv1);
|
||||
@@ -477,7 +489,7 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
for (int64_t i = 0; i < indices.size(); ++i)
|
||||
indices[i] = static_cast<int32_t>(draw.indices[i]);
|
||||
geometry["indices"] = indices;
|
||||
if (draw.geometry_key != 0)
|
||||
if (draw.geometry_key != 0 && !stage0_texgen)
|
||||
geometry_cache[draw.geometry_key] = {draw.geometry_revision, extraction, geometry};
|
||||
}
|
||||
item.merge(geometry);
|
||||
@@ -530,6 +542,7 @@ Array Metin2PythonHost::render3d_draws() {
|
||||
item["viewport"] = vp;
|
||||
out[draw_index++] = item;
|
||||
}
|
||||
out.resize(draw_index);
|
||||
if (extraction % 120 == 0) {
|
||||
for (auto it = geometry_cache.begin(); it != geometry_cache.end();) {
|
||||
if (extraction - it->second.last_used > 120)
|
||||
|
||||
Reference in New Issue
Block a user