Rescaling resource bubbles through shader?

f1rpo

plastics
Joined
May 22, 2014
Messages
2,060
Location
Germany
I've come to realize that modders have access to the source files of the Direct3D shaders used by BtS, in particular a shader named PlotIndicator.fx. Now I'm wondering if this shader could be modified in a way that shrinks the plot indicators. The scaling of the plot indicators, especially resource bubbles, is an open issue for some (many?) players with HD displays. (I've elaborated a bit on this issue in the spoiler box in this post.) Re-compiling PlotIndicator.fx from its source seems easy enough (see below), but I don't know the programming language (High-Level Shader Language, HLSL) at all, and know very little about Direct3D or shaders in general. I'm pretty sure they're not intended for texture scaling, but it seems that a lot of things can be done through shaders in principle. Maybe someone with more knowledge about the subject would like to look into this, or at least provide some pointers or tell me that it's not possible?

Unfortunately, shaders are (apparently) only loaded from the BtS install directory, so, even if my approach works, players will have to modify the original files.

Regarding compilation, I'm attaching an archive extracted from the installer of patch 3.17. I don't know what the installer does with that, if anything (I haven't executed the installer). The compiler (fxc.exe) wasn't included; I've added that (from the DirectX SDK). Please see the readme.txt about the specific file versions. Invoking the compiler should only require a double-click on CompileShaders.bat (which was included in the patch – I didn't write it). The sources are also included in a 3dsmax plugin that Firaxis released in 2006, but I think those are outdated.

For a sanity test, I've replaced the resource button texture with an overlay texture; see the first attached screenshot. So - loading a modified shader works. It's a bit worrisome that...[edit - n/m. unrelated problem on my end; no worries.] My installation of Colonization (from the Civ 4 Complete Edition I think) also contains shader sources. Those are pretty different from the ones I've attached, but PlotIndicator.fx from Col seems to be compatible with BtS (2nd screenshot). Not any prettier, but perhaps helpful as a learning example:
Spoiler PlotIndicator.fx from Civ4Col :
Code:
//  *****************   CIV4 ********************
//
//  FILE:    PlotIndicator.fx
//
//  AUTHOR:  Nat Duca (03-24-2005)
//            Tom Whittaker 9.15.05 - simpipled Plot icons to 2 textures, simple draw call and not texturecompostiing
//
//  PURPOSE: Draw the plot widget with specified color, masked icon and border highlights
//
//------------------------------------------------------------------------------------------------
//  Copyright (c) 2005 Firaxis Games, Inc. All rights reserved.
//------------------------------------------------------------------------------------------------

float4 f4MaterialEmissive : MATERIALEMISSIVE = (1.0.xxxx);
float4 f4MaterialDiffuse : MATERIALDIFFUSE = (1.0.xxxx);
float4x4 mtxWorldViewProj: WORLDVIEWPROJECTIONTRANSPOSE;

//structs
struct VS_INPUT
{
   float4 f4Position : POSITION;
   float2 f2TexCoord1 : TEXCOORD0;
   float2 f2TexCoord2 : TEXCOORD1;
};

struct VS_OUTPUT
{
   float4 f4Position : POSITION;
   float2 f2TexCoord1 : TEXCOORD0;
   float2 f2TexCoord2 : TEXCOORD1;
   float2 f2TexCoord3 : TEXCOORD2;
};

//------------------------------------------------------------------------------------------------
//                          VERTEX SHADER
//------------------------------------------------------------------------------------------------
VS_OUTPUT PlotIndicatorVS( VS_INPUT vIn   )
{
    VS_OUTPUT vOut = (VS_OUTPUT) 0;

    //Transform point
       vOut.f4Position  = mul(mtxWorldViewProj, vIn.f4Position);
       vOut.f2TexCoord1 = vIn.f2TexCoord1;
       vOut.f2TexCoord2 = vIn.f2TexCoord2;
       vOut.f2TexCoord3 = vIn.f2TexCoord1;

   return vOut;
}

//------------------------------------------------------------------------------------------------
// TEXTURES
//------------------------------------------------------------------------------------------------
texture IconOverlayTexture <string NTM = "base";>;
texture ButtonTexture <string NTM = "decal"; int NTMIndex = 0;>;
texture OverlayAlphaTexture<string NTM = "decal"; int NTMIndex = 1;>;

//------------------------------------------------------------------------------------------------
//                          SAMPLERS
//------------------------------------------------------------------------------------------------
sampler IconOverlay = sampler_state { Texture = (IconOverlayTexture); AddressU = Clamp; AddressV = Clamp; MagFilter = Linear; MipFilter = Linear; MinFilter = Linear; };
sampler IconButton = sampler_state { Texture = (ButtonTexture); AddressU = Clamp; AddressV = Clamp; MagFilter = Linear;   MipFilter = Linear;   MinFilter = Linear; };
sampler IconOverlayAlpha = sampler_state { Texture = (OverlayAlphaTexture); AddressU = Clamp; AddressV = Clamp;   MagFilter = Linear;   MipFilter = Linear;   MinFilter = Linear; };

//------------------------------------------------------------------------------------------------
float4 PlotIndicatorPS( VS_OUTPUT vIn ) : COLOR
{
   // Get Base textures
   float4 f4InnerAlpha = tex2D(IconOverlay, vIn.f2TexCoord1);
   float4 f4Button = tex2D(IconButton, vIn.f2TexCoord2);
   float4 f4OuterAlpha = tex2D(IconOverlayAlpha, vIn.f2TexCoord3);
 
   float4 f4FinalColor = lerp(f4MaterialEmissive, f4Button, f4InnerAlpha.a);
   f4FinalColor.a = f4OuterAlpha.a * f4MaterialDiffuse.a;
   return f4FinalColor;
}

//------------------------------------------------------------------------------------------------
//                          TECHNIQUES
//------------------------------------------------------------------------------------------------
technique PlotIndicatorShader <string shadername= "PlotIndicatorShader"; int implementation=0;>
{
    pass P0
    {
        // Enable depth writing
        ZEnable        = true;
        ZWriteEnable   = true;
        ZFunc          = lessequal;

        //Alpha Testing
        AlphaBlendEnable= true;
        AlphaTestEnable   = true;
        AlphaREf       = 0;
        AlphaFunc       = greater;
        SrcBlend        = SRCALPHA;
        DestBlend       = INVSRCALPHA;

           VertexShader = compile vs_1_1 PlotIndicatorVS();
        PixelShader  = compile ps_1_1 PlotIndicatorPS();
   }
}
 

Attachments

  • Shaders_v3.17.zip
    Shaders_v3.17.zip
    79.8 KB · Views: 52
  • recompilation test.jpg
    recompilation test.jpg
    205.5 KB · Views: 84
  • Civ4Col plot indicators.jpg
    Civ4Col plot indicators.jpg
    201.8 KB · Views: 88
Last edited:
In short, it seems that this is not possible. What (I think) I've learned: In terms of computer graphics, the plot indicator is a "primitive". Vertex (and pixel) shaders only receive input about a single vertex (or, after rasterization, a single pixel) from a stream. For re-scaling, we'd have to know the relative position of the given vertex within the primitive (knowing its dimensions wouldn't be good enough). Indeed, the answer to this StackOverflow question suggests to me that passing a second vertex – as a point of reference – to the vertex shader is an idiom. Sounds like that would have to happen in the EXE. A geometry shader would receive all triangles that make up a primitive as input. Maybe such a shader could be instantiated without modifying the EXE, however, geometry shaders are not supported by DirectX9; they require "shader model 4", which is supported by DirectX10.

I'm not positive that the game will use only DirectX9 when higher versions are installed on the system. I've tried to test this by changing a vs_1_1 keyword in the shader code (vertex shader profile 1.1, requiring shader model 1) to vs_4_0 (requiring shader model 4), but, predictably, my effects compiler (fxc.exe) from 2008 doesn't recognize the "vs_4_0". The fxc.exe that comes with my OS (Win 8.1) is too recent, won't accept much of the Firaxis code. A legacy version that still seems to be used somewhat commonly is the one in Microsoft's DirectX SDK from June 2010 – but I can't get that SDK to install, and can't unpack the installer either. Well, it seems like a very long shot anyway. (That said: if someone happens to have that 2010 fcx.exe, I would be interested in an upload of the same.)
 
I don't think so. You can't change the type of shaders the game uses from vertex to geometry without changing how the entire rendering code works. And I am not sure if the actual graphics engine has been released along side the rest of the DLL.
 
It has not, the engine is still proprietary.
 
Top Bottom