wined3d: Fog is applied after sRGB correction.
This commit is contained in:
parent
d2ac521cd3
commit
ba5c61ba20
|
@ -4888,6 +4888,107 @@ void test_vshader_input(IDirect3DDevice9 *device)
|
||||||
IDirect3DVertexDeclaration9_Release(decl_color_float);
|
IDirect3DVertexDeclaration9_Release(decl_color_float);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fog_srgbwrite_test(IDirect3DDevice9 *device)
|
||||||
|
{
|
||||||
|
/* Draw a black quad, half fogged with white fog -> grey color. Enable sRGB writing.
|
||||||
|
* if sRGB writing is applied before fogging, the 0.0 will be multiplied with ~ 12.92, so still
|
||||||
|
* stay 0.0. After that the fog gives 0.5. If sRGB writing is applied after fogging, the
|
||||||
|
* 0.5 will run through the alternative path(0^5 ^ 0.41666 * 1.055 - 0.055), resulting in approx.
|
||||||
|
* 0.73
|
||||||
|
*
|
||||||
|
* At the time of this writing, wined3d could not apply sRGB correction to fixed function rendering,
|
||||||
|
* so use shaders for this task
|
||||||
|
*/
|
||||||
|
IDirect3DPixelShader9 *pshader;
|
||||||
|
IDirect3DVertexShader9 *vshader;
|
||||||
|
IDirect3D9 *d3d;
|
||||||
|
DWORD vshader_code[] = {
|
||||||
|
0xfffe0101, /* vs_1_1 */
|
||||||
|
0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
|
||||||
|
0x00000051, 0xa00f0000, 0x3f000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0 */
|
||||||
|
0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
|
||||||
|
0x00000001, 0xc00f0001, 0xa0000000, /* mov oFog, c0.x */
|
||||||
|
0x0000ffff /* end */
|
||||||
|
};
|
||||||
|
DWORD pshader_code[] = {
|
||||||
|
0xffff0101, /* ps_1_1 */
|
||||||
|
0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
|
||||||
|
0x00000001, 0x800f0000, 0xa0e40000, /* mov r0, c0 */
|
||||||
|
0x0000ffff /* end */
|
||||||
|
};
|
||||||
|
const float quad[] = {
|
||||||
|
-1.0, -1.0, 0.1,
|
||||||
|
1.0, -1.0, 0.1,
|
||||||
|
-1.0, 1.0, 0.1,
|
||||||
|
1.0, 1.0, 0.1
|
||||||
|
};
|
||||||
|
HRESULT hr;
|
||||||
|
DWORD color;
|
||||||
|
|
||||||
|
IDirect3DDevice9_GetDirect3D(device, &d3d);
|
||||||
|
if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||||
|
D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE,
|
||||||
|
D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8) != D3D_OK) {
|
||||||
|
skip("No SRGBWRITEENABLE support on D3DFMT_X8R8G8B8\n");
|
||||||
|
IDirect3D9_Release(d3d);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IDirect3D9_Release(d3d);
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xffffffff);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code, &pshader);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetVertexShader(device, vshader);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetPixelShader(device, pshader);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_BeginScene(device);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
|
||||||
|
if(SUCCEEDED(hr)) {
|
||||||
|
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 3);
|
||||||
|
ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_EndScene(device);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_SetVertexShader(device, NULL);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetPixelShader(device, NULL);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
|
||||||
|
IDirect3DPixelShader9_Release(pshader);
|
||||||
|
IDirect3DVertexShader9_Release(vshader);
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
|
||||||
|
|
||||||
|
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
|
||||||
|
ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
|
||||||
|
color = getPixelColor(device, 160, 360);
|
||||||
|
ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181,
|
||||||
|
"Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(visual)
|
START_TEST(visual)
|
||||||
{
|
{
|
||||||
IDirect3DDevice9 *device_ptr;
|
IDirect3DDevice9 *device_ptr;
|
||||||
|
@ -4988,6 +5089,7 @@ START_TEST(visual)
|
||||||
if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
|
if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
|
||||||
{
|
{
|
||||||
fog_with_shader_test(device_ptr);
|
fog_with_shader_test(device_ptr);
|
||||||
|
fog_srgbwrite_test(device_ptr);
|
||||||
}
|
}
|
||||||
else skip("No vs_1_1 and ps_1_1 support\n");
|
else skip("No vs_1_1 and ps_1_1 support\n");
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,7 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
|
||||||
|
|
||||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||||
SHADER_BUFFER buffer;
|
SHADER_BUFFER buffer;
|
||||||
|
const char *fragcolor;
|
||||||
|
|
||||||
#if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
|
#if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
|
||||||
it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
|
it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
|
||||||
|
@ -341,27 +342,12 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
|
||||||
shader_addline(&buffer, "gl_FragColor = R0;\n");
|
shader_addline(&buffer, "gl_FragColor = R0;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pixel shader < 3.0 do not replace the fog stage.
|
|
||||||
* This implements linear fog computation and blending.
|
|
||||||
* TODO: non linear fog
|
|
||||||
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
|
|
||||||
* -1/(e-s) and e/(e-s) respectively.
|
|
||||||
*/
|
|
||||||
if(This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
|
|
||||||
shader_addline(&buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n");
|
|
||||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS))
|
|
||||||
shader_addline(&buffer, "gl_FragData[0].xyz = mix(gl_Fog.color.xyz, gl_FragData[0].xyz, Fog);\n");
|
|
||||||
else
|
|
||||||
shader_addline(&buffer, "gl_FragColor.xyz = mix(gl_Fog.color.xyz, gl_FragColor.xyz, Fog);\n");
|
|
||||||
}
|
|
||||||
if(This->srgb_enabled) {
|
|
||||||
const char *fragcolor;
|
|
||||||
|
|
||||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
||||||
fragcolor = "gl_FragData[0]";
|
fragcolor = "gl_FragData[0]";
|
||||||
} else {
|
} else {
|
||||||
fragcolor = "gl_FragColor";
|
fragcolor = "gl_FragColor";
|
||||||
}
|
}
|
||||||
|
if(This->srgb_enabled) {
|
||||||
shader_addline(&buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
|
shader_addline(&buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
|
||||||
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
|
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
|
||||||
srgb_sub_high, srgb_sub_high, srgb_sub_high);
|
srgb_sub_high, srgb_sub_high, srgb_sub_high);
|
||||||
|
@ -371,6 +357,16 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
|
||||||
shader_addline(&buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
|
shader_addline(&buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
|
||||||
shader_addline(&buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
|
shader_addline(&buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
|
||||||
}
|
}
|
||||||
|
/* Pixel shader < 3.0 do not replace the fog stage.
|
||||||
|
* This implements linear fog computation and blending.
|
||||||
|
* TODO: non linear fog
|
||||||
|
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
|
||||||
|
* -1/(e-s) and e/(e-s) respectively.
|
||||||
|
*/
|
||||||
|
if(This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
|
||||||
|
shader_addline(&buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n");
|
||||||
|
shader_addline(&buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||||
|
}
|
||||||
|
|
||||||
shader_addline(&buffer, "}\n");
|
shader_addline(&buffer, "}\n");
|
||||||
|
|
||||||
|
@ -413,48 +409,34 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
|
||||||
*/
|
*/
|
||||||
shader_addline(&buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
|
shader_addline(&buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
|
||||||
|
|
||||||
|
if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
|
||||||
|
fragcolor = "R0";
|
||||||
|
} else {
|
||||||
|
fragcolor = "TMP_COLOR";
|
||||||
|
}
|
||||||
if(This->srgb_enabled) {
|
if(This->srgb_enabled) {
|
||||||
const char *color_reg;
|
|
||||||
|
|
||||||
if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
|
|
||||||
color_reg = "R0";
|
|
||||||
} else {
|
|
||||||
color_reg = "TMP_COLOR";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
|
|
||||||
shader_addline(&buffer, "LRP R0.rgb, TMP_FOG.x, R0, state.fog.color;\n");
|
|
||||||
shader_addline(&buffer, "MOV result.color.a, R0.a;\n");
|
|
||||||
} else {
|
|
||||||
shader_addline(&buffer, "LRP TMP_COLOR.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n");
|
|
||||||
shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n");
|
|
||||||
}
|
|
||||||
/* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
|
/* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
|
||||||
|
|
||||||
/* Calculate the > 0.0031308 case */
|
/* Calculate the > 0.0031308 case */
|
||||||
shader_addline(&buffer, "POW TMP.x, %s.x, srgb_pow.x;\n", color_reg);
|
shader_addline(&buffer, "POW TMP.x, %s.x, srgb_pow.x;\n", fragcolor);
|
||||||
shader_addline(&buffer, "POW TMP.y, %s.y, srgb_pow.y;\n", color_reg);
|
shader_addline(&buffer, "POW TMP.y, %s.y, srgb_pow.y;\n", fragcolor);
|
||||||
shader_addline(&buffer, "POW TMP.z, %s.z, srgb_pow.z;\n", color_reg);
|
shader_addline(&buffer, "POW TMP.z, %s.z, srgb_pow.z;\n", fragcolor);
|
||||||
shader_addline(&buffer, "MUL TMP, TMP, srgb_mul_hi;\n");
|
shader_addline(&buffer, "MUL TMP, TMP, srgb_mul_hi;\n");
|
||||||
shader_addline(&buffer, "SUB TMP, TMP, srgb_sub_hi;\n");
|
shader_addline(&buffer, "SUB TMP, TMP, srgb_sub_hi;\n");
|
||||||
/* Calculate the < case */
|
/* Calculate the < case */
|
||||||
shader_addline(&buffer, "MUL TMP2, srgb_mul_low, %s;\n", color_reg);
|
shader_addline(&buffer, "MUL TMP2, srgb_mul_low, %s;\n", fragcolor);
|
||||||
/* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
|
/* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
|
||||||
shader_addline(&buffer, "SLT TA, srgb_comparison, %s;\n", color_reg);
|
shader_addline(&buffer, "SLT TA, srgb_comparison, %s;\n", fragcolor);
|
||||||
shader_addline(&buffer, "SGE TB, srgb_comparison, %s;\n", color_reg);
|
shader_addline(&buffer, "SGE TB, srgb_comparison, %s;\n", fragcolor);
|
||||||
/* Store the components > 0.0031308 in the destination */
|
/* Store the components > 0.0031308 in the destination */
|
||||||
shader_addline(&buffer, "MUL %s, TMP, TA;\n", color_reg);
|
shader_addline(&buffer, "MUL %s, TMP, TA;\n", fragcolor);
|
||||||
/* Add the components that are < 0.0031308 */
|
/* Add the components that are < 0.0031308 */
|
||||||
shader_addline(&buffer, "MAD result.color.xyz, TMP2, TB, %s;\n", color_reg);
|
shader_addline(&buffer, "MAD result.color.xyz, TMP2, TB, %s;\n", fragcolor);
|
||||||
/* [0.0;1.0] clamping. Not needed, this is done implicitly */
|
/* [0.0;1.0] clamping. Not needed, this is done implicitly */
|
||||||
} else {
|
|
||||||
if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
|
|
||||||
shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, R0, state.fog.color;\n");
|
|
||||||
shader_addline(&buffer, "MOV result.color.a, R0.a;\n");
|
|
||||||
} else {
|
|
||||||
shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n");
|
|
||||||
shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n");
|
|
||||||
}
|
}
|
||||||
|
if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
|
||||||
|
shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
|
||||||
|
shader_addline(&buffer, "MOV result.color.a, %s.a;\n", fragcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_addline(&buffer, "END\n");
|
shader_addline(&buffer, "END\n");
|
||||||
|
|
Loading…
Reference in New Issue