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
+31
-53
@@ -10,22 +10,21 @@ layout(set = 0, binding = 1) uniform sampler2D mask_sampler;
|
||||
|
||||
layout(push_constant) uniform DrawConstants {
|
||||
mat4 mvp;
|
||||
vec4 tint_color;
|
||||
vec4 ambient_emissive;
|
||||
vec4 light_dir;
|
||||
vec4 light_diffuse;
|
||||
vec4 params; // bone base + 1, pretransformed, UI mask, unused
|
||||
} draw;
|
||||
|
||||
layout(set = 1, binding = 1, std430) readonly buffer FixedFunctionState {
|
||||
uvec4 stage0_color;
|
||||
uvec4 stage0_alpha;
|
||||
uvec4 stage1_color;
|
||||
uvec4 stage1_alpha;
|
||||
uvec4 stage_color[2];
|
||||
uvec4 stage_alpha[2];
|
||||
vec4 fog_color;
|
||||
vec4 fog_params;
|
||||
vec4 texture_factor;
|
||||
mat4 world_view;
|
||||
uvec4 flags;
|
||||
mat4 normal_matrix;
|
||||
uvec4 lighting_flags;
|
||||
uvec4 material_sources;
|
||||
uvec4 alpha_test; // ALPHATESTENABLE, ALPHAFUNC, ALPHAREF, unused
|
||||
} fixed_state;
|
||||
|
||||
vec4 stage_arg(uint selector, vec4 diffuse, vec4 current, vec4 texel) {
|
||||
@@ -79,61 +78,40 @@ vec4 apply_stage(uvec4 color_state, uvec4 alpha_state,
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 tex0 = texture(tex_sampler, in_uv);
|
||||
if (fixed_state.flags.x == 2u) {
|
||||
vec3 shadow = tex0.rgb;
|
||||
if (fixed_state.flags.z != 0u && fixed_state.stage1_color.x == 4u)
|
||||
shadow *= texture(mask_sampler, in_mask_uv).rgb;
|
||||
shadow = mix(fixed_state.fog_color.rgb, shadow, in_fog);
|
||||
if (all(greaterThanEqual(shadow, vec3(0.997)))) discard;
|
||||
out_color = vec4(shadow, 1.0);
|
||||
return;
|
||||
}
|
||||
if (fixed_state.flags.x != 0u) {
|
||||
// D3D8 texture stage cascade: stage 1 runs unless its COLOROP is D3DTOP_DISABLE.
|
||||
vec4 diffuse = in_color;
|
||||
vec4 color = apply_stage(fixed_state.stage0_color, fixed_state.stage0_alpha,
|
||||
diffuse, diffuse, tex0);
|
||||
if (fixed_state.flags.z != 0u && fixed_state.stage1_color.x > 1u) {
|
||||
vec4 tex1 = texture(mask_sampler, in_mask_uv);
|
||||
color = apply_stage(fixed_state.stage1_color, fixed_state.stage1_alpha,
|
||||
diffuse, color, tex1);
|
||||
}
|
||||
if (fixed_state.stage1_alpha.w != 0u) {
|
||||
float ref = draw.ambient_emissive.a;
|
||||
uint func = fixed_state.stage0_alpha.w;
|
||||
vec4 color = apply_stage(fixed_state.stage_color[0], fixed_state.stage_alpha[0],
|
||||
diffuse, diffuse, texture(tex_sampler, in_uv));
|
||||
if (fixed_state.stage_color[0].x > 1u && fixed_state.stage_color[1].x > 1u)
|
||||
color = apply_stage(fixed_state.stage_color[1], fixed_state.stage_alpha[1],
|
||||
diffuse, color, texture(mask_sampler, in_mask_uv));
|
||||
if (fixed_state.alpha_test.x != 0u) {
|
||||
// D3DRS_ALPHAREF is an 8-bit reference compared against the 8-bit pixel alpha.
|
||||
uint a = uint(clamp(color.a, 0.0, 1.0) * 255.0 + 0.5);
|
||||
uint ref = fixed_state.alpha_test.z & 255u;
|
||||
uint func = fixed_state.alpha_test.y;
|
||||
bool passes = func == 1u ? false :
|
||||
func == 2u ? color.a < ref :
|
||||
func == 3u ? abs(color.a - ref) < (0.5 / 255.0) :
|
||||
func == 4u ? color.a <= ref :
|
||||
func == 5u ? color.a > ref :
|
||||
func == 6u ? abs(color.a - ref) >= (0.5 / 255.0) :
|
||||
func == 7u ? color.a >= ref : true;
|
||||
func == 2u ? a < ref :
|
||||
func == 3u ? a == ref :
|
||||
func == 4u ? a <= ref :
|
||||
func == 5u ? a > ref :
|
||||
func == 6u ? a != ref :
|
||||
func == 7u ? a >= ref : true;
|
||||
if (!passes) discard;
|
||||
}
|
||||
color.rgb = mix(fixed_state.fog_color.rgb, color.rgb, in_fog);
|
||||
out_color = color;
|
||||
return;
|
||||
}
|
||||
vec4 color = in_color * tex0;
|
||||
if (draw.light_dir.w < -0.4) {
|
||||
// 2D UI batch (UIRenderCommand): vertex color times texture, optionally clipped by a mask.
|
||||
vec4 color = in_color * texture(tex_sampler, in_uv);
|
||||
if (draw.params.z > 0.5) {
|
||||
if (in_mask_uv.x < 0.0 || in_mask_uv.x > 1.0 || in_mask_uv.y < 0.0 || in_mask_uv.y > 1.0)
|
||||
discard;
|
||||
vec4 mask_val = texture(mask_sampler, in_mask_uv);
|
||||
if (draw.light_dir.w < -0.8) {
|
||||
if (in_mask_uv.x < 0.0 || in_mask_uv.x > 1.0 || in_mask_uv.y < 0.0 || in_mask_uv.y > 1.0) {
|
||||
discard;
|
||||
}
|
||||
color.rgb *= mask_val.rgb;
|
||||
color.a = mask_val.a * in_color.a;
|
||||
} else {
|
||||
color.a = mask_val.a * in_color.a;
|
||||
if (color.a <= 0.003) discard;
|
||||
}
|
||||
} else if (draw.light_dir.w > 1.001) {
|
||||
// Specular sphere-map stage 1 (D3DTOP_MODULATEALPHA_ADDCOLOR)
|
||||
float spec_power = draw.light_dir.w - 1.0;
|
||||
vec4 spec_map = texture(mask_sampler, in_mask_uv);
|
||||
color.rgb = min(color.rgb + (tex0.a * spec_power) * spec_map.rgb, vec3(1.5));
|
||||
color.a = 1.0;
|
||||
color.rgb *= mask_val.rgb;
|
||||
color.a = mask_val.a * in_color.a;
|
||||
}
|
||||
if (color.a <= draw.ambient_emissive.a) discard;
|
||||
out_color = color;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user