Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

The following HLSL shader (without preprocessing) results in 65 arithmetic operations (see below). Can the same effect achieved with <=64 operations?

// Center of "light"
float x;
float y;

// Size of "light"
float viewsizeQ;
float fadesizeQ;

// Rotational shift
float angleShift;

// Resolution
float screenResolutionWidth;
float screenResolutionHeight;
float screenZoom;

// Texture sampler
sampler TextureSampler : register(s0);

float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up the texture color.
    float4 color = tex2D(TextureSampler, texCoord);

    // Calculate distance
    float dx = (x-texCoord.x) * screenResolutionWidth;
    float dy = (y-texCoord.y) * screenResolutionHeight;

    // Get angle from center
    // Added into next line to save that variable
    //float angleFactor = sin((atan2(dx, dy) + angleShift) * 12) * 13000 * screenZoom * screenZoom;

    float distQ = dx*dx + dy*dy - /*angleFactor*/ sin((atan2(dx, dy) + angleShift) * 12) * 13000 * screenZoom * screenZoom;

    // Get greyscale
    float greyscale = dot(color.rgb, float3(0.3, 0.59, 0.11));

    // Within fadeSize
    if (distQ < fadesizeQ)
    {
       // Within viewSize
       if (distQ < viewsizeQ)
       {
          // Make blue-greyscale
          color.r = 0.3f * greyscale; 
          color.g = 0.5f * greyscale; 
          color.b = 1.0f * greyscale;
       }
       // Outside viewSize but still in fadeSize
       else
       {
          // Make 
          float factor = 1.0f - ((distQ  - viewsizeQ) / (fadesizeQ - viewsizeQ));
          color.r = factor * 0.3f * greyscale + (1-factor) * 0.2f * greyscale;
          color.g = factor * 0.5f * greyscale + (1-factor) * 0.25f * greyscale;
          color.b = factor * 1.0f * greyscale + (1-factor) * 0.2f * greyscale;
       } 
    }
    // Outside fadeSize (just show grey terrain)
    else
    {
        color.rb = 0.2f * greyscale;
        color.g = 0.25f * greyscale;
    }

    return color;
}   

technique Thermal
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 main();
    }
}

The following output is created by the Microsoft Shader Compiler:

C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86>fxc 07_EffectThermalVisionLevel.fx /T ps_2_a /Zi

Microsoft (R) Direct3D Shader Compiler 9.29.952.3111
Copyright (C) Microsoft Corporation 2002-2009. All rights reserved.

//
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
//
//   fxc 07_EffectThermalVisionLevel.fx /T ps_2_a /Zi
//
//
// Parameters:
//
//   sampler2D TextureSampler;
//   float angleShift;
//   float fadesizeQ;
//   float screenResolutionHeight;
//   float screenResolutionWidth;
//   float screenZoom;
//   float viewsizeQ;
//   float x;
//   float y;
//
//
// Registers:
//
//   Name                   Reg   Size
//   ---------------------- ----- ----
//   x                      c0       1
//   y                      c1       1
//   viewsizeQ              c2       1
//   fadesizeQ              c3       1
//   angleShift             c4       1
//   screenResolutionWidth  c5       1
//   screenResolutionHeight c6       1
//   screenZoom             c7       1
//   TextureSampler         s0       1
//

ps_2_x
def c8, 0.0208350997, -0.0851330012, 0.180141002, -0.330299497
def c9, 0.999866009, 0, 1, 3.14159274
def c10, -2, 1.57079637, 1.9098593, 0.5
def c11, 6.28318548, -3.14159274, 13000, 0
def c12, 0.300000012, 0.589999974, 0.109999999, 0.5
def c13, 0.200000003, 0.25, 0, 0
def c14, -1.55009923e-006, -2.17013894e-005, 0.00260416674, 0.00026041668
def c15, -0.020833334, -0.125, 1, 0.5
dcl t0.xy  // texCoord<0,1>
dcl_2d s0

#line 26 "C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\07_EffectThermalVisionLevel.fx"
add r0.w, -t0.x, c0.x
mul r0.x, r0.w, c5.x  // ::dx<0>
add r0.z, -t0.y, c1.x
mul r0.z, r0.z, c6.x  // ::dy<0>

#line 33
abs r0.yw, r0.xxzz
max r1.w, r0.y, r0.w
rcp r1.x, r1.w
min r1.y, r0.w, r0.y
add r0.y, -r0.y, r0.w
cmp r0.y, r0.y, c9.y, c9.z
mul r0.w, r1.x, r1.y
mul r1.x, r0.w, r0.w
mad r1.y, r1.x, c8.x, c8.y
mad r1.y, r1.x, r1.y, c8.z
mad r1.y, r1.x, r1.y, c8.w
mad r1.x, r1.x, r1.y, c9.x
mul r0.w, r0.w, r1.x
mad r1.x, r0.w, c10.x, c10.y
mad r0.y, r1.x, r0.y, r0.w
cmp r0.w, r0.z, -c9.y, -c9.w
add r0.y, r0.w, r0.y
add r0.w, r0.y, r0.y
max r1.x, r0.x, r0.z
cmp r1.x, r1.x, c9.z, c9.y
min r1.y, r0.z, r0.x
mul r0.z, r0.z, r0.z
mad r0.x, r0.x, r0.x, r0.z
cmp r0.z, r1.y, c9.y, r1.x
mad r0.y, r0.z, -r0.w, r0.y
add r0.y, r0.y, c4.x
mad r0.y, r0.y, c10.z, c10.w
frc r0.y, r0.y
mad r0.y, r0.y, c11.x, c11.y
sincos r1.y, r0.y, c14, c15
mul r0.y, c7.x, c7.x
mul r0.y, r1.y, r0.y
mad r0.x, r0.y, -c11.z, r0.x  // ::distQ<0>

#line 39
add r0.y, r0.x, -c3.x

#line 42
add r0.x, r0.x, -c2.x

#line 53
mov r1.x, c3.x  // ::fadesizeQ<0>
add r0.z, r1.x, -c2.x
rcp r0.z, r0.z
mad r0.z, r0.x, -r0.z, c9.z  // ::factor<0>

#line 23
texld r1, t0, s0  // ::color<0,1,2,3>

#line 36
dp3 r2.z, r1, c12  // ::greyscale<0>

#line 54
mul r0.w, r0.z, r2.z
add r2.w, -r0.z, c9.z
mul r2.w, r2.z, r2.w
mul r3.xy, r2.w, c13
mad r4.xy, r0.w, c12.xwzw, r3  // ::color<0,1>
mad r4.z, r0.z, r2.z, r3.x  // ::color<2>

#line 42
mul r2.xy, r2.z, c12.xwzw
cmp r0.xzw, r0.x, r4.xyyz, r2.xyyz  // ::color<0,1,2>

#line 63
mul r2.xyz, r2.z, c13.xyxw  // ::color<0,1,0>

#line 39
cmp r1.xyz, r0.y, r2, r0.xzww  // ::color<0,1,2>
mov oC0, r1  // ::main<0,1,2,3>
share|improve this question

closed as too localized by Byte56, Sam Hocevar, Maik Semder, Darth Satan, Josh Petrie Jan 14 '13 at 21:14

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1  
Most of the shader source seems to be missing. –  Sam Hocevar Jan 13 '13 at 18:48
2  
I think how to optimize your shader code is too localized for the site. See the FAQ about which sites you can ask discussion oriented questions like this one. –  Byte56 Jan 13 '13 at 18:54
    
@samhocevar: Strange, if you edit my question, all the code is there. I am not sure how to fix this. –  pad_ares Jan 14 '13 at 1:59
    
@byte56: You may be right, I will try to reformulate my question in a more general way. –  pad_ares Jan 14 '13 at 2:00
    
@samhoc: Thanks for the edit ! –  pad_ares Jan 14 '13 at 2:12

2 Answers 2

up vote 2 down vote accepted

You need to think of the built-in HLSL functions that let you perform tests (min, max, saturate…) or interpolations (lerp, smoothstep…). Many times they map to a single assembly instruction on the hardware.

Also, as Adam mentioned in his answer, it’s best to try to parallelise operations. Adding two float has exactly the same cost as adding two float4.

Using all these ideas, the following code uses a lot fewer instructions. I took the liberty of renaming greyscale to luminance:

float4 main(float2 texCoord : TEXCOORD0) : COLOR0
{
    // Look up the texture color.
    float4 color = tex2D(TextureSampler, texCoord);

    // Calculate distance
    float2 delta = (float2(x, y) - texCoord.xy)
                 * float2(screenResolutionWidth, screenResolutionHeight);

    // Get angle from center
    float distQ = dot(delta, delta)
       - /*angleFactor*/ sin((atan2(delta.x, delta.y) + angleShift) * 12)
                          * 13000 * screenZoom * screenZoom;

    float luminance = dot(color.rgb, float3(0.3, 0.59, 0.11));
    float3 grey = float3(0.3, 0.5, 1.0);
    float3 blue = float3(0.2, 0.25, 0.2);
    float factor = saturate((distQ  - viewsizeQ) / (fadesizeQ - viewsizeQ));

    color.rgb = luminance * lerp(grey, blue, factor);
    return color;
}
share|improve this answer
    
Great! There is only one small error. I get an error X3017: cannot implicitly convert from 'float3' to 'float4' when you set color to a or b. –  pad_ares Jan 14 '13 at 2:24
1  
@pad_ares I think I managed to fix it; sorry for the multiple edits. –  Sam Hocevar Jan 14 '13 at 2:49
    
Amazing! That brought it down to 53 instruction. I would never have though that could be possible. Thank you very much! I learned a lot studying your changes! –  pad_ares Jan 14 '13 at 3:19

My first suggestion would be to combine both the x and y variables and the screen resolution into a float2 which then lets you do the distance calculation in one line. That should get rid of a few instructions.

I'd also suggest passing the square of the screenZoom as a constant if you only use it squared in the calculations.

float2 lightPosition;
float2 screenResolution;

    // Calculate distance
    float2 distance = (lightPosition-texCoord) * screenResolution;
share|improve this answer
    
Thank you for these hints. That will do the trick. –  pad_ares Jan 14 '13 at 1:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.