⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -