wined3d: Implement texbem in arb, improve it in glsl.

This commit is contained in:
Stefan Dösinger 2007-02-15 03:00:57 +01:00 committed by Alexandre Julliard
parent 49a49fcfec
commit 99576ea24e
2 changed files with 93 additions and 7 deletions

View File

@ -119,6 +119,15 @@ void shader_arb_load_constants(
GL_LIMITS(pshader_constantsF), GL_LIMITS(pshader_constantsF),
stateBlock->pixelShaderConstantF, stateBlock->pixelShaderConstantF,
&stateBlock->set_pconstantsF); &stateBlock->set_pconstantsF);
if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst) {
/* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the
* number of the constant to load the matrix into.
* The state manager takes care that this function is always called if the bump env matrix changes
*/
IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader;
float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data));
}
} }
} }
@ -159,6 +168,19 @@ void shader_generate_arb_declarations(
shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i); shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i);
} }
if(reg_maps->bumpmat /* 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.
*/
if(max_constantsF < GL_LIMITS(pshader_constantsF)) {
((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = max_constantsF;
shader_addline(buffer, "PARAM bumpenvmat = program.env[%d];\n", ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst);
} else {
FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
}
}
/* Need to PARAM the environment parameters (constants) so we can use relative addressing */ /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n", shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
max_constantsF, max_constantsF - 1); max_constantsF, max_constantsF - 1);
@ -662,7 +684,7 @@ void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
} }
void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
#if 0
SHADER_BUFFER* buffer = arg->buffer; SHADER_BUFFER* buffer = arg->buffer;
DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK;
DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK; DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
@ -672,6 +694,35 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
sprintf(dst_str, "T%u", reg1); sprintf(dst_str, "T%u", reg1);
shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%u], T%u;\n", reg1, reg2); shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%u], T%u;\n", reg1, reg2);
shader_hw_sample(arg, reg1, dst_str, "TMP"); shader_hw_sample(arg, reg1, dst_str, "TMP");
#endif
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD dst = arg->dst;
DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK;
SHADER_BUFFER* buffer = arg->buffer;
char reg_coord[40];
DWORD reg_dest_code;
/* All versions have a destination register */
reg_dest_code = dst & WINED3DSP_REGNUM_MASK;
/* Can directly use the name because texbem is only valid for <= 1.3 shaders */
pshader_get_register_name(dst, reg_coord);
if(This->bumpenvmatconst) {
/*shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", 1, 1); Not needed - done already */
shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n");
shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
/* Not sure about this, but hl2 needs it. It uses a projected texture with texbem and depends on the 4th coordinate */
shader_addline(buffer, "MOV TMP.a, %s;\n", reg_coord);
shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP");
} else {
/* Without a bump matrix loaded, just sample with the unmodified coordinates */
shader_hw_sample(arg, reg_dest_code, reg_coord, reg_coord);
}
} }
void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) { void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {

View File

@ -1767,15 +1767,50 @@ void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
/** Process the WINED3DSIO_TEXBEM instruction in GLSL. /** Process the WINED3DSIO_TEXBEM instruction in GLSL.
* Apply a fake bump map transform. * Apply a fake bump map transform.
* FIXME: Should apply the BUMPMAPENV matrix. For now, just sample the texture */ * texbem is pshader <= 1.3 only, this saves a few version checks
*/
void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) { void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
char dst_swizzle[6];
glsl_sample_function_t sample_function;
DWORD sampler_type;
DWORD sampler_idx;
BOOL projected;
DWORD mask = 0;
DWORD flags;
char coord_mask[6];
DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; /* All versions have a destination register */
DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK; shader_glsl_append_dst(arg->buffer, arg);
FIXME("Not applying the BUMPMAPENV matrix for pixel shader instruction texbem.\n"); sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
shader_addline(arg->buffer, "T%u = texture2D(Psampler%u, gl_TexCoord[%u].xy + T%u.xy);\n", flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
reg1, reg1, reg1, reg2);
/* TODO: Does texbem even support projected textures? half-life 2 uses it */
if (flags & WINED3DTTFF_PROJECTED) {
projected = TRUE;
switch (flags & ~WINED3DTTFF_PROJECTED) {
case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break;
case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break;
case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break;
case WINED3DTTFF_COUNT4:
case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break;
}
} else {
projected = FALSE;
}
sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
shader_glsl_get_sample_function(sampler_type, projected, &sample_function);
mask |= sample_function.coord_mask;
shader_glsl_get_write_mask(arg->dst, dst_swizzle);
shader_glsl_get_write_mask(mask, coord_mask);
FIXME("Bump map transform not handled yet\n");
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, dst_swizzle);
} }
/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL