wined3d: Introduce a get_projection_matrix() function.
Notice that I'm using floats instead of doubles in the new function, mostly to be able to use struct wined3d_matrix and multiply_matrix(). At a rough estimate the precision should still be good enough.
This commit is contained in:
parent
65c8c40b18
commit
2d270f31c6
|
@ -4052,74 +4052,14 @@ static void transform_view(struct wined3d_context *context, const struct wined3d
|
||||||
void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
|
void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
|
||||||
{
|
{
|
||||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||||
|
struct wined3d_matrix projection;
|
||||||
|
|
||||||
gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
|
gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
|
||||||
checkGLcall("glMatrixMode(GL_PROJECTION)");
|
checkGLcall("glMatrixMode(GL_PROJECTION)");
|
||||||
|
|
||||||
/* There are a couple of additional things we have to take into account
|
get_projection_matrix(context, state, &projection);
|
||||||
* here besides the projection transformation itself:
|
gl_info->gl_ops.gl.p_glLoadMatrixf(&projection._11);
|
||||||
* - We need to flip along the y-axis in case of offscreen rendering.
|
checkGLcall("glLoadMatrixf");
|
||||||
* - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
|
|
||||||
* - D3D coordinates refer to pixel centers while GL coordinates refer
|
|
||||||
* to pixel corners.
|
|
||||||
* - D3D has a top-left filling convention. We need to maintain this
|
|
||||||
* even after the y-flip mentioned above.
|
|
||||||
* In order to handle the last two points, we translate by
|
|
||||||
* (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
|
|
||||||
* translating slightly less than half a pixel. We want the difference to
|
|
||||||
* be large enough that it doesn't get lost due to rounding inside the
|
|
||||||
* driver, but small enough to prevent it from interfering with any
|
|
||||||
* anti-aliasing. */
|
|
||||||
|
|
||||||
if (context->last_was_rhw)
|
|
||||||
{
|
|
||||||
/* Transform D3D RHW coordinates to OpenGL clip coordinates. */
|
|
||||||
double x = state->viewport.x;
|
|
||||||
double y = state->viewport.y;
|
|
||||||
double w = state->viewport.width;
|
|
||||||
double h = state->viewport.height;
|
|
||||||
double x_scale = 2.0 / w;
|
|
||||||
double x_offset = ((63.0 / 64.0) - (2.0 * x) - w) / w;
|
|
||||||
double y_scale = context->render_offscreen ? 2.0 / h : 2.0 / -h;
|
|
||||||
double y_offset = context->render_offscreen
|
|
||||||
? ((63.0 / 64.0) - (2.0 * y) - h) / h
|
|
||||||
: ((63.0 / 64.0) - (2.0 * y) - h) / -h;
|
|
||||||
enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
|
|
||||||
state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
|
|
||||||
double z_scale = zenable ? 2.0f : 0.0f;
|
|
||||||
double z_offset = zenable ? -1.0f : 0.0f;
|
|
||||||
const GLdouble projection[] =
|
|
||||||
{
|
|
||||||
x_scale, 0.0, 0.0, 0.0,
|
|
||||||
0.0, y_scale, 0.0, 0.0,
|
|
||||||
0.0, 0.0, z_scale, 0.0,
|
|
||||||
x_offset, y_offset, z_offset, 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
|
|
||||||
checkGLcall("glLoadMatrixd");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double y_scale = context->render_offscreen ? -1.0 : 1.0;
|
|
||||||
double x_offset = (63.0 / 64.0) / state->viewport.width;
|
|
||||||
double y_offset = context->render_offscreen
|
|
||||||
? (63.0 / 64.0) / state->viewport.height
|
|
||||||
: -(63.0 / 64.0) / state->viewport.height;
|
|
||||||
const GLdouble projection[] =
|
|
||||||
{
|
|
||||||
1.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, y_scale, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 2.0, 0.0,
|
|
||||||
x_offset, y_offset, -1.0, 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
|
|
||||||
checkGLcall("glLoadMatrixd");
|
|
||||||
|
|
||||||
gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_PROJECTION]._11);
|
|
||||||
checkGLcall("glLoadMatrixf");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This should match any arrays loaded in load_vertex_data.
|
/* This should match any arrays loaded in load_vertex_data.
|
||||||
|
|
|
@ -3138,6 +3138,70 @@ void get_modelview_matrix(const struct wined3d_context *context, const struct wi
|
||||||
multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]);
|
multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
|
||||||
|
struct wined3d_matrix *mat)
|
||||||
|
{
|
||||||
|
/* There are a couple of additional things we have to take into account
|
||||||
|
* here besides the projection transformation itself:
|
||||||
|
* - We need to flip along the y-axis in case of offscreen rendering.
|
||||||
|
* - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
|
||||||
|
* - D3D coordinates refer to pixel centers while GL coordinates refer
|
||||||
|
* to pixel corners.
|
||||||
|
* - D3D has a top-left filling convention. We need to maintain this
|
||||||
|
* even after the y-flip mentioned above.
|
||||||
|
* In order to handle the last two points, we translate by
|
||||||
|
* (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
|
||||||
|
* translating slightly less than half a pixel. We want the difference to
|
||||||
|
* be large enough that it doesn't get lost due to rounding inside the
|
||||||
|
* driver, but small enough to prevent it from interfering with any
|
||||||
|
* anti-aliasing. */
|
||||||
|
|
||||||
|
if (context->last_was_rhw)
|
||||||
|
{
|
||||||
|
/* Transform D3D RHW coordinates to OpenGL clip coordinates. */
|
||||||
|
float x = state->viewport.x;
|
||||||
|
float y = state->viewport.y;
|
||||||
|
float w = state->viewport.width;
|
||||||
|
float h = state->viewport.height;
|
||||||
|
float x_scale = 2.0f / w;
|
||||||
|
float x_offset = (float)((63.0 / 64.0 - (2.0 * x) - w) / w);
|
||||||
|
float y_scale = context->render_offscreen ? 2.0f / h : 2.0f / -h;
|
||||||
|
float y_offset = (float)(context->render_offscreen
|
||||||
|
? (63.0 / 64.0 - (2.0 * y) - h) / h
|
||||||
|
: (63.0 / 64.0 - (2.0 * y) - h) / -h);
|
||||||
|
enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
|
||||||
|
state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
|
||||||
|
float z_scale = zenable ? 2.0f : 0.0f;
|
||||||
|
float z_offset = zenable ? -1.0f : 0.0f;
|
||||||
|
const struct wined3d_matrix projection =
|
||||||
|
{
|
||||||
|
x_scale, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, y_scale, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, z_scale, 0.0f,
|
||||||
|
x_offset, y_offset, z_offset, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
*mat = projection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float y_scale = context->render_offscreen ? -1.0f : 1.0f;
|
||||||
|
float x_offset = 63.0f / 64.0f * (1.0f / state->viewport.width);
|
||||||
|
float y_offset = context->render_offscreen
|
||||||
|
? 63.0f / 64.0f * (1.0f / state->viewport.height)
|
||||||
|
: -63.0f / 64.0f * (1.0f / state->viewport.height);
|
||||||
|
const struct wined3d_matrix projection =
|
||||||
|
{
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, y_scale, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 2.0f, 0.0f,
|
||||||
|
x_offset, y_offset, -1.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
multiply_matrix(mat, &projection, &state->transforms[WINED3D_TS_PROJECTION]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup this textures matrix according to the texture flags. */
|
/* Setup this textures matrix according to the texture flags. */
|
||||||
/* Context activation is done by the caller (state handler). */
|
/* Context activation is done by the caller (state handler). */
|
||||||
void set_texture_matrix(const struct wined3d_gl_info *gl_info, const struct wined3d_matrix *matrix, DWORD flags,
|
void set_texture_matrix(const struct wined3d_gl_info *gl_info, const struct wined3d_matrix *matrix, DWORD flags,
|
||||||
|
|
|
@ -3037,6 +3037,8 @@ static inline BOOL shader_constant_is_local(const struct wined3d_shader *shader,
|
||||||
void get_identity_matrix(struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
|
void get_identity_matrix(struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
|
||||||
void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
|
void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
|
||||||
struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
|
struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
|
||||||
|
void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
|
||||||
|
struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Using additional shader constants (uniforms in GLSL / program environment
|
/* Using additional shader constants (uniforms in GLSL / program environment
|
||||||
* or local parameters in ARB) is costly:
|
* or local parameters in ARB) is costly:
|
||||||
|
|
Loading…
Reference in New Issue