📄 state.c
字号:
float col[4];
D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
/* And now the default texture color as well */
for (i = 0; i < GL_LIMITS(texture_stages); i++) {
/* Note the WINED3DRS value applies to all textures, but GL has one
* per texture, so apply it now ready to be used!
*/
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
checkGLcall("glActiveTextureARB");
} else if (i>0) {
FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
}
} else {
GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
}
}
static void
renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
#if 0 /* Don't use OpenGL 2.0 calls for now */
if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
checkGLcall("glStencilFuncSeparate(...)");
GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
checkGLcall("glStencilOpSeparate(...)");
}
else
#endif
if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
GL_EXTCALL(glActiveStencilFaceEXT(face));
checkGLcall("glActiveStencilFaceEXT(...)");
glStencilFunc(func, ref, mask);
checkGLcall("glStencilFunc(...)");
glStencilOp(stencilFail, depthFail, stencilPass);
checkGLcall("glStencilOp(...)");
} else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
checkGLcall("glStencilFuncSeparateATI(...)");
GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
checkGLcall("glStencilOpSeparateATI(...)");
} else {
ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
}
}
static void
state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD onesided_enable = FALSE;
DWORD twosided_enable = FALSE;
GLint func = GL_ALWAYS;
GLint func_ccw = GL_ALWAYS;
GLint ref = 0;
GLuint mask = 0;
GLint stencilFail = GL_KEEP;
GLint depthFail = GL_KEEP;
GLint stencilPass = GL_KEEP;
GLint stencilFail_ccw = GL_KEEP;
GLint depthFail_ccw = GL_KEEP;
GLint stencilPass_ccw = GL_KEEP;
/* No stencil test without a stencil buffer */
if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
glDisable(GL_STENCIL_TEST);
checkGLcall("glDisable GL_STENCIL_TEST");
return;
}
onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
func = GL_ALWAYS;
if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
func = GL_ALWAYS;
ref = stateblock->renderState[WINED3DRS_STENCILREF];
mask = stateblock->renderState[WINED3DRS_STENCILMASK];
stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
"GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
"GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
onesided_enable, twosided_enable, ref, mask,
func, stencilFail, depthFail, stencilPass,
func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
if (twosided_enable) {
renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
} else {
if (onesided_enable) {
glEnable(GL_STENCIL_TEST);
checkGLcall("glEnable GL_STENCIL_TEST");
glStencilFunc(func, ref, mask);
checkGLcall("glStencilFunc(...)");
glStencilOp(stencilFail, depthFail, stencilPass);
checkGLcall("glStencilOp(...)");
} else {
glDisable(GL_STENCIL_TEST);
checkGLcall("glDisable GL_STENCIL_TEST");
}
}
}
static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
if(stateblock->wineD3DDevice->stencilBufferTarget) {
glStencilMask(stateblock->renderState[WINED3DRS_STENCILWRITEMASK]);
} else {
glStencilMask(0);
}
checkGLcall("glStencilMask");
}
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 {
DWORD d;
float f;
} tmpvalue;
if (!fogenable) {
/* 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.0f);
checkGLcall("glFogf(GL_FOG_START, fogstart");
glFogf(GL_FOG_END, 1.0f);
checkGLcall("glFogf(GL_FOG_END, fogend");
}
return;
}
tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
fogstart = tmpvalue.f;
tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
fogend = tmpvalue.f;
/* Fog Rules:
*
* With fixed function vertex processing, Direct3D knows 2 different fog input sources.
* It can use the Z value of the vertex, or the alpha component of the specular color.
* This depends on the fog vertex, fog table and the vertex declaration. If the Z value
* is used, fogstart, fogend and the equation type are used, otherwise linear fog with
* start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
*
* FOGTABLEMODE != NONE:
* The Z value is used, with the equation specified, no matter what vertex type.
*
* FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
* Per vertex fog is calculated using the specified fog equation and the parameters
*
* FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
* FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
* Linear fog with start = 255.0, end = 0.0, input comes from the specular color
*
*
* 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)->baseShader.reg_maps.fog) {
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.0f/(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."
*/
else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
glHint(GL_FOG_HINT, GL_FASTEST);
checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
context->last_was_foggy_shader = FALSE;
switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
/* If processed vertices are used, fall through to the NONE case */
case WINED3DFOG_EXP: {
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
if(GL_SUPPORT(EXT_FOG_COORD)) {
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
}
break;
}
}
case WINED3DFOG_EXP2: {
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP2);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
if(GL_SUPPORT(EXT_FOG_COORD)) {
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
}
break;
}
}
case WINED3DFOG_LINEAR: {
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
if(GL_SUPPORT(EXT_FOG_COORD)) {
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -