Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
7cedd56d
Commit
7cedd56d
authored
Mar 22, 2007
by
Fabian Bieler
Committed by
Alexandre Julliard
Mar 23, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wined3d: Implement linear fog with pixel shader.
parent
67813450
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
136 additions
and
13 deletions
+136
-13
arb_program_shader.c
dlls/wined3d/arb_program_shader.c
+1
-1
directx.c
dlls/wined3d/directx.c
+4
-4
drawprim.c
dlls/wined3d/drawprim.c
+1
-1
pixelshader.c
dlls/wined3d/pixelshader.c
+34
-2
state.c
dlls/wined3d/state.c
+96
-5
No files found.
dlls/wined3d/arb_program_shader.c
View file @
7cedd56d
...
...
@@ -284,7 +284,7 @@ static void pshader_get_register_name(
break
;
case
WINED3DSPR_COLOROUT
:
if
(
reg
==
0
)
sprintf
(
regstr
,
"
result.color
"
);
sprintf
(
regstr
,
"
TMP_COLOR
"
);
else
{
/* TODO: See GL_ARB_draw_buffers */
FIXME
(
"Unsupported write to render target %u
\n
"
,
reg
);
...
...
dlls/wined3d/directx.c
View file @
7cedd56d
...
...
@@ -291,18 +291,18 @@ static void select_shader_max_constants(
switch
(
ps_selected_mode
)
{
case
SHADER_GLSL
:
/* Subtract the other potential uniforms from the max available (bools & ints).
/* Subtract the other potential uniforms from the max available (bools & ints)
, and 2 states for fog
.
* In theory the texbem instruction may need one more shader constant too. But lets assume
* that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
* and lets not take away a uniform needlessly from all other shaders.
*/
gl_info
->
max_pshader_constantsF
=
gl_info
->
ps_glsl_constantsF
-
(
MAX_CONST_B
/
4
)
-
MAX_CONST_I
;
gl_info
->
max_pshader_constantsF
=
gl_info
->
ps_glsl_constantsF
-
(
MAX_CONST_B
/
4
)
-
MAX_CONST_I
-
2
;
break
;
case
SHADER_ARB
:
/* The arb shader only loads the bump mapping environment matrix into the shader if it finds
* a free constant to do that, so
no need to reduce the number of available constant
s.
* a free constant to do that, so
only reduce the number of available constants by 2 for the fog state
s.
*/
gl_info
->
max_pshader_constantsF
=
gl_info
->
ps_arb_constantsF
;
gl_info
->
max_pshader_constantsF
=
gl_info
->
ps_arb_constantsF
-
2
;
break
;
default:
gl_info
->
max_pshader_constantsF
=
0
;
...
...
dlls/wined3d/drawprim.c
View file @
7cedd56d
...
...
@@ -682,7 +682,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
specularColor
=
ptrToCoords
[
0
];
VTRACE
((
"specularColor=%lx
\n
"
,
specularColor
));
/* special case where the fog density is stored in the
diffuse
alpha channel */
/* special case where the fog density is stored in the
specular
alpha channel */
if
(
This
->
stateBlock
->
renderState
[
WINED3DRS_FOGENABLE
]
&&
(
This
->
stateBlock
->
renderState
[
WINED3DRS_FOGVERTEXMODE
]
==
WINED3DFOG_NONE
||
sd
->
u
.
s
.
position
.
dwType
==
WINED3DDECLTYPE_FLOAT4
)
&&
This
->
stateBlock
->
renderState
[
WINED3DRS_FOGTABLEMODE
]
==
WINED3DFOG_NONE
)
{
...
...
dlls/wined3d/pixelshader.c
View file @
7cedd56d
...
...
@@ -381,6 +381,21 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
else
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
"
);
}
shader_addline
(
&
buffer
,
"}
\n
"
);
TRACE
(
"Compiling shader object %u
\n
"
,
shader_obj
);
...
...
@@ -407,11 +422,28 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader(
/* Base Declarations */
shader_generate_arb_declarations
(
(
IWineD3DBaseShader
*
)
This
,
reg_maps
,
&
buffer
,
&
GLINFO_LOCATION
);
/* We need two variables for fog blending */
shader_addline
(
&
buffer
,
"TEMP TMP_FOG;
\n
"
);
if
(
This
->
baseShader
.
hex_version
>=
WINED3DPS_VERSION
(
2
,
0
))
{
shader_addline
(
&
buffer
,
"TEMP TMP_COLOR;
\n
"
);
}
/* Base Shader Body */
shader_generate_main
(
(
IWineD3DBaseShader
*
)
This
,
&
buffer
,
reg_maps
,
pFunction
);
if
(
This
->
baseShader
.
hex_version
<
WINED3DPS_VERSION
(
2
,
0
))
shader_addline
(
&
buffer
,
"MOV result.color, R0;
\n
"
);
/* calculate fog and blend it
* NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
* -1/(e-s) and e/(e-s) respectively.
*/
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
))
{
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
"
);
}
shader_addline
(
&
buffer
,
"END
\n
"
);
/* TODO: change to resource.glObjectHandle or something like that */
...
...
dlls/wined3d/state.c
View file @
7cedd56d
...
...
@@ -689,6 +689,8 @@ static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock,
static
void
state_fog
(
DWORD
state
,
IWineD3DStateBlockImpl
*
stateblock
,
WineD3DContext
*
context
)
{
/* TODO: Put this into the vertex type block once that is in the state table */
BOOL
fogenable
=
stateblock
->
renderState
[
WINED3DRS_FOGENABLE
];
BOOL
is_ps3
=
use_ps
(
stateblock
->
wineD3DDevice
)
&&
((
IWineD3DPixelShaderImpl
*
)
stateblock
->
pixelShader
)
->
baseShader
.
hex_version
>=
WINED3DPS_VERSION
(
3
,
0
);
float
fogstart
,
fogend
;
union
{
...
...
@@ -700,6 +702,17 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
/* No fog? Disable it, and we're done :-) */
glDisable
(
GL_FOG
);
checkGLcall
(
"glDisable GL_FOG"
);
if
(
use_ps
(
stateblock
->
wineD3DDevice
)
&&
((
IWineD3DPixelShaderImpl
*
)
stateblock
->
pixelShader
)
->
baseShader
.
hex_version
<
WINED3DPS_VERSION
(
3
,
0
)
)
{
/* disable fog in the pixel shader
* NOTE: For pixel shader, 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.
*/
glFogf
(
GL_FOG_START
,
0
.
0
f
);
checkGLcall
(
"glFogf(GL_FOG_START, fogstart"
);
glFogf
(
GL_FOG_END
,
1
.
0
f
);
checkGLcall
(
"glFogf(GL_FOG_END, fogend"
);
}
return
;
}
...
...
@@ -726,18 +739,80 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
* FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
* Linear fog with start = 255.0, end = 0.0, input comes from the specular color
*
* Vertex shaders work in a simmilar way, but need more testing
*
* Rules for vertex fog with shaders:
*
* When mixing fixed function functionality with the programmable pipeline, D3D expects
* the fog computation to happen during transformation while openGL expects it to happen
* during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
* the pixel shader while openGL always expects the pixel shader to handle the blending.
* To solve this problem, WineD3D does:
* 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
* shader,
* and 2) disables the fog computation (in either the fixed function or programmable
* rasterizer) if using a vertex program.
*
*
* If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
* without shaders).
*/
if
(
is_ps3
)
{
if
(
!
use_vs
(
stateblock
->
wineD3DDevice
)
&&
stateblock
->
renderState
[
WINED3DRS_FOGTABLEMODE
]
==
WINED3DFOG_NONE
)
{
FIXME
(
"Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline
\n
"
);
}
}
if
(
use_vs
(
stateblock
->
wineD3DDevice
)
&&
((
IWineD3DVertexShaderImpl
*
)
stateblock
->
vertexShader
)
->
usesFog
)
{
glFogi
(
GL_FOG_MODE
,
GL_LINEAR
);
checkGLcall
(
"glFogi(GL_FOG_MODE, GL_LINEAR)"
);
if
(
stateblock
->
renderState
[
WINED3DRS_FOGTABLEMODE
]
==
WINED3DFOG_NONE
)
{
if
(
stateblock
->
renderState
[
WINED3DRS_FOGTABLEMODE
]
!=
WINED3DFOG_NONE
)
{
if
(
!
is_ps3
)
FIXME
(
"Implement table fog for foggy vertex shader
\n
"
);
/* Disable fog */
fogenable
=
FALSE
;
}
else
{
/* Set fog computation in the rasterizer to pass through the value (just blend it) */
glFogi
(
GL_FOG_MODE
,
GL_LINEAR
);
checkGLcall
(
"glFogi(GL_FOG_MODE, GL_LINEAR)"
);
fogstart
=
1
.
0
;
fogend
=
0
.
0
;
}
context
->
last_was_foggy_shader
=
TRUE
;
}
else
if
(
use_ps
(
stateblock
->
wineD3DDevice
)
)
{
/* NOTE: For pixel shader, 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 to simplify fog computation in the shader.
*/
WINED3DFOGMODE
mode
;
context
->
last_was_foggy_shader
=
FALSE
;
/* If both fogmodes are set use the table fog mode */
if
(
stateblock
->
renderState
[
WINED3DRS_FOGTABLEMODE
]
==
WINED3DFOG_NONE
)
mode
=
stateblock
->
renderState
[
WINED3DRS_FOGVERTEXMODE
];
else
mode
=
stateblock
->
renderState
[
WINED3DRS_FOGTABLEMODE
];
switch
(
mode
)
{
case
WINED3DFOG_EXP
:
case
WINED3DFOG_EXP2
:
if
(
!
is_ps3
)
FIXME
(
"Implement non linear fog for pixel shader < 3.0
\n
"
);
/* Disable fog */
fogenable
=
FALSE
;
break
;
case
WINED3DFOG_LINEAR
:
fogstart
=
-
1
.
0
f
/
(
fogend
-
fogstart
);
fogend
*=
-
fogstart
;
break
;
case
WINED3DFOG_NONE
:
if
(
!
is_ps3
)
FIXME
(
"Implement software vertex fog for pixel shader < 3.0
\n
"
);
/* Disable fog */
fogenable
=
FALSE
;
break
;
default:
FIXME
(
"Unexpected WINED3DRS_FOGVERTEXMODE %d
\n
"
,
stateblock
->
renderState
[
WINED3DRS_FOGVERTEXMODE
]);
}
}
/* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
* the system will apply only pixel(=table) fog effects."
*/
...
...
@@ -854,6 +929,16 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
}
else
{
glDisable
(
GL_FOG
);
checkGLcall
(
"glDisable GL_FOG"
);
if
(
use_ps
(
stateblock
->
wineD3DDevice
)
)
{
/* disable fog in the pixel shader
* NOTE: For pixel shader, 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.
*/
glFogf
(
GL_FOG_START
,
0
.
0
f
);
checkGLcall
(
"glFogf(GL_FOG_START, fogstart"
);
glFogf
(
GL_FOG_END
,
1
.
0
f
);
checkGLcall
(
"glFogf(GL_FOG_END, fogend"
);
}
}
if
(
GL_SUPPORT
(
NV_FOG_DISTANCE
))
{
...
...
@@ -864,7 +949,6 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
static
void
state_fogcolor
(
DWORD
state
,
IWineD3DStateBlockImpl
*
stateblock
,
WineD3DContext
*
context
)
{
float
col
[
4
];
D3DCOLORTOGLFLOAT4
(
stateblock
->
renderState
[
WINED3DRS_FOGCOLOR
],
col
);
/* Set the default alpha blend color */
glFogfv
(
GL_FOG_COLOR
,
&
col
[
0
]);
checkGLcall
(
"glFog GL_FOG_COLOR"
);
}
...
...
@@ -2001,6 +2085,7 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
IWineD3DDeviceImpl
*
device
=
stateblock
->
wineD3DDevice
;
BOOL
use_pshader
=
use_ps
(
device
);
BOOL
use_vshader
=
use_vs
(
device
);
BOOL
update_fog
=
FALSE
;
int
i
;
if
(
use_pshader
)
{
...
...
@@ -2014,6 +2099,7 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
sampler
(
STATE_SAMPLER
(
i
),
stateblock
,
context
);
}
}
update_fog
=
TRUE
;
}
else
{
/* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
* if a different texture was bound. I don't have to do anything.
...
...
@@ -2031,6 +2117,8 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
tex_colorop
(
STATE_TEXTURESTAGE
(
i
,
WINED3DTSS_COLOROP
),
stateblock
,
context
);
}
}
if
(
context
->
last_was_pshader
)
update_fog
=
TRUE
;
}
if
(
!
isStateDirty
(
context
,
StateTable
[
STATE_VSHADER
].
representative
))
{
...
...
@@ -2041,6 +2129,9 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
}
}
if
(
update_fog
)
state_fog
(
state
,
stateblock
,
context
);
context
->
last_was_pshader
=
use_pshader
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment