From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/ffp_gl.c | 12 +------- dlls/wined3d/glsl_shader.c | 38 ++----------------------- dlls/wined3d/stateblock.c | 57 +++++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 48 deletions(-)
diff --git a/dlls/wined3d/ffp_gl.c b/dlls/wined3d/ffp_gl.c index a50f7c7a4b0..f1f995f6e4c 100644 --- a/dlls/wined3d/ffp_gl.c +++ b/dlls/wined3d/ffp_gl.c @@ -1046,17 +1046,7 @@ void ffp_vertex_update_clip_plane_constants(const struct wined3d_gl_info *gl_inf
gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW); gl_info->gl_ops.gl.p_glPushMatrix(); - - /* Clip plane settings are affected by the model view in OpenGL, - * and the view transform in Direct3D. - * - * With vertex shaders, Direct3D clip planes are not transformed, - * whereas in OpenGL they are still transformed by the model view - * matrix. */ - if (!use_vs(state)) - gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11); - else - gl_info->gl_ops.gl.p_glLoadIdentity(); + gl_info->gl_ops.gl.p_glLoadIdentity();
plane[0] = state->clip_planes[i].x; plane[1] = state->clip_planes[i].y; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 295867c32b1..b4308906e4c 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1477,18 +1477,6 @@ static void reset_program_constant_version(struct wine_rb_entry *entry, void *co WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0; }
-static void transpose_matrix(struct wined3d_matrix *out, const struct wined3d_matrix *m) -{ - struct wined3d_matrix temp; - unsigned int i, j; - - for (i = 0; i < 4; ++i) - for (j = 0; j < 4; ++j) - (&temp._11)[4 * j + i] = (&m->_11)[4 * i + j]; - - *out = temp; -} - static void shader_glsl_ffp_vertex_normalmatrix_uniform(const struct wined3d_context_gl *context_gl, const struct wined3d_state *state, struct glsl_shader_prog_link *prog) { @@ -1636,20 +1624,8 @@ static void shader_glsl_clip_plane_uniform(const struct wined3d_context_gl *cont const struct wined3d_state *state, unsigned int index, struct glsl_shader_prog_link *prog) { const struct wined3d_gl_info *gl_info = context_gl->gl_info; - struct wined3d_matrix matrix; - struct wined3d_vec4 plane; - - plane = state->clip_planes[index];
- /* Clip planes are affected by the view transform in d3d for FFP draws. */ - if (!use_vs(state)) - { - invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]); - transpose_matrix(&matrix, &matrix); - wined3d_vec4_transform(&plane, &plane, &matrix); - } - - GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &plane.x)); + GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &state->clip_planes[index].x)); }
static void shader_glsl_load_constants(struct shader_glsl_priv *priv, @@ -11747,9 +11723,6 @@ static void glsl_vertex_pipe_vdecl(struct wined3d_context *context,
if (!use_vs(state)) { - if (context->last_was_vshader) - context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; - context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX;
/* Because of settings->texcoords, we have to regenerate the vertex @@ -11769,12 +11742,6 @@ static void glsl_vertex_pipe_vdecl(struct wined3d_context *context, && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3) context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; } - else - { - /* Vertex shader clipping ignores the view matrix. Update all clip planes. */ - if (!context->last_was_vshader) - context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; - }
context->last_was_vshader = use_vs(state); context->last_was_diffuse = diffuse; @@ -11849,8 +11816,7 @@ static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context, static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW - | WINED3D_SHADER_CONST_FFP_VERTEXBLEND - | WINED3D_SHADER_CONST_VS_CLIP_PLANES; + | WINED3D_SHADER_CONST_FFP_VERTEXBLEND; }
static void glsl_vertex_pipe_projection(struct wined3d_context *context, diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 5d275be1ae1..ed11babb1ab 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -249,6 +249,19 @@ static const DWORD vertex_states_sampler[] = WINED3D_SAMP_DMAP_OFFSET, };
+static void transpose_matrix(struct wined3d_matrix *out, const struct wined3d_matrix *m) +{ + struct wined3d_matrix temp; + + for (unsigned int i = 0; i < 4; ++i) + { + for (unsigned int j = 0; j < 4; ++j) + (&temp._11)[4 * j + i] = (&m->_11)[4 * i + j]; + } + + *out = temp; +} + static inline void stateblock_set_all_bits(uint32_t *map, UINT map_size) { DWORD mask = (1u << (map_size & 0x1f)) - 1; @@ -2709,7 +2722,12 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, TRACE("device %p, stateblock %p.\n", device, stateblock);
if (changed->vertexShader) + { wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, state->vs); + /* Clip planes are affected by the view matrix, but only if not using + * vertex shaders. */ + changed->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES); + } if (changed->pixelShader) wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, state->ps);
@@ -3296,11 +3314,17 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, idx = i * word_bit_count + j;
if (idx == WINED3D_TS_VIEW) + { changed->lights = 1; + changed->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES); + }
wined3d_device_set_transform(device, idx, &state->transforms[idx]); } } + + /* Clip planes are affected by the view matrix. */ + changed->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES); }
if (changed->indices) @@ -3345,7 +3369,38 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, while (map) { i = wined3d_bit_scan(&map); - wined3d_device_set_clip_plane(device, i, &state->clip_planes[i]); + + /* In Direct3D, clipping is done based on the position as transformed + * by the world (model) matrix, but not the view matrix. + * + * GL and Vulkan do not distinguish the world and view, so we pass them + * as a single uniform. That means, however, that we need to unapply the + * view matrix from the clip planes that we are applying. We do this by + * multiplying by the transpose of the inverse of the view matrix. + * + * This works mathematically (c = clip plane, p = position): + * + * clip distance = dot((V⁻¹)ᵀc, VMp) + * = ((V⁻¹)ᵀc)ᵀVMp + * = cᵀV⁻¹VMp + * = cᵀMp + * = dot(c, Mp) + */ + + if (!state->vs) + { + struct wined3d_matrix matrix; + struct wined3d_vec4 plane; + + invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]); + transpose_matrix(&matrix, &matrix); + wined3d_vec4_transform(&plane, &state->clip_planes[i], &matrix); + wined3d_device_set_clip_plane(device, i, &plane); + } + else + { + wined3d_device_set_clip_plane(device, i, &state->clip_planes[i]); + } }
if (changed->lights)