diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index e6106cdee4b..7faf45c15cb 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -177,7 +177,7 @@ void shader_generate_arb_declarations( shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i); } - if(reg_maps->bumpmat /* Only a pshader can use texbem */) { + if(reg_maps->bumpmat != -1 /* Only a pshader can use texbem */) { /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying * bump mapping. @@ -510,6 +510,34 @@ static inline void pshader_gen_output_modifier_line( regstr, write_mask, regstr, shift_tab[shift]); } +void pshader_hw_bem(SHADER_OPCODE_ARG* arg) { + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + + SHADER_BUFFER* buffer = arg->buffer; + char dst_name[50]; + char src_name[2][50]; + char dst_wmask[20]; + + pshader_get_register_name(arg->dst, dst_name); + shader_arb_get_write_mask(arg->dst, dst_wmask); + strcat(dst_name, dst_wmask); + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); + pshader_gen_input_modifier_line(buffer, arg->src[1], 1, src_name[1]); + + if(This->bumpenvmatconst != -1) { + /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ + shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n"); + shader_addline(buffer, "DP3 TMP.r, TMP2, %s;\n", src_name[1]); + shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n"); + shader_addline(buffer, "DP3 TMP.g, TMP2, %s;\n", src_name[1]); + + shader_addline(buffer, "ADD %s, %s, TMP;\n", dst_name, src_name[0]); + } else { + shader_addline(buffer, "MOV %s, %s;\n", dst_name, src_name[0]); + } +} + void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; @@ -723,7 +751,7 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { /* Can directly use the name because texbem is only valid for <= 1.3 shaders */ pshader_get_register_name(dst, reg_coord); - if(This->bumpenvmatconst) { + if(This->bumpenvmatconst != -1) { /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */ shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n"); diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 3508835e6dd..34465709eb6 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -197,6 +197,8 @@ HRESULT shader_get_registers_used( /* There are some minor differences between pixel and vertex shaders */ char pshader = shader_is_pshader_version(This->baseShader.hex_version); + reg_maps->bumpmat = -1; + if (pToken == NULL) return WINED3D_OK; @@ -295,7 +297,15 @@ HRESULT shader_get_registers_used( DWORD snum = *pToken & WINED3DSP_REGNUM_MASK; reg_maps->labels[snum] = 1; pToken += curOpcode->num_params; - + + } else if(WINED3DSIO_BEM == curOpcode->opcode) { + DWORD regnum = *pToken & WINED3DSP_REGNUM_MASK; + if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != regnum) { + FIXME("Pixel shader uses bem or texbem instruction on more than 1 sampler\n"); + } else { + reg_maps->bumpmat = regnum; + } + /* Set texture, address, temporary registers */ } else { int i, limit; @@ -347,7 +357,7 @@ HRESULT shader_get_registers_used( /* texbem is only valid with < 1.4 pixel shaders */ if(WINED3DSIO_TEXBEM == curOpcode->opcode) { - if(reg_maps->bumpmat != 0 && reg_maps->bumpmat != sampler_code) { + if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) { FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n"); } else { reg_maps->bumpmat = sampler_code; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 598f5890e75..2508eaaa82c 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -355,7 +355,7 @@ void shader_glsl_load_constants( /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. * It can't be 0 for a valid texbem instruction. */ - if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != 0) { + if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != -1) { float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat")); checkGLcall("glGetUniformLocationARB"); @@ -400,7 +400,7 @@ void shader_generate_glsl_declarations( if(!pshader) shader_addline(buffer, "uniform vec4 posFixup;\n"); - else if(reg_maps->bumpmat) + else if(reg_maps->bumpmat != -1) shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); /* Declare texture samplers */ @@ -1824,6 +1824,17 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) { sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle); } +void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) { + glsl_src_param_t src0_param, src1_param; + + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src0_param); + shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &src1_param); + + shader_glsl_append_dst(arg->buffer, arg); + shader_addline(arg->buffer, "%s + bumpenvmat * %s);\n", + src0_param.param_str, src1_param.param_str); +} + /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index b74734d4681..962b3d5727b 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -239,7 +239,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texdp3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texm3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, 1, NULL, pshader_glsl_texdepth, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, - {WINED3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, + {WINED3DSIO_BEM, "bem", "undefined", 1, 3, pshader_hw_bem, pshader_glsl_bem, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, {WINED3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, 0, 0}, {WINED3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, 0, 0}, {WINED3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 1, 5, NULL, NULL, WINED3DPS_VERSION(2,1), -1}, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 74a6b42f063..3f69171c376 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1625,6 +1625,7 @@ extern void shader_arb_load_constants( extern void shader_hw_def(SHADER_OPCODE_ARG *arg); /* ARB pixel shader prototypes */ +extern void pshader_hw_bem(SHADER_OPCODE_ARG* arg); extern void pshader_hw_cnd(SHADER_OPCODE_ARG* arg); extern void pshader_hw_cmp(SHADER_OPCODE_ARG* arg); extern void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg); @@ -1700,6 +1701,7 @@ extern void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texkill(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg); +extern void pshader_glsl_bem(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg); extern void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg);