2012-12-19 74 views
2

摘要和目標:HLSL和XNA:我如何獲得當前像素着色器迭代周圍像素的位置和顏色?

我想讓着色器爲遊戲編輯器執行簡單的窗口效果。該效果將繪製具有低值邊框顏色和高值高光的框架。我已經嘗試了很多方法,但總體而言,我只想出了一種可能的解決方案來使用GPU實現這一點。

首先,我創建一個自定義頂點類型,用於在屏幕空間中存儲矢量的XY座標。

using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 

namespace WindowsGame1 { 
    public struct Vertex2D : IVertexType { 
     public Vector2 Position; 
     public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0)); 

     public Vertex2D(float x, float y) { 
      Position = new Vector2(x, y); 
     } 

     VertexDeclaration IVertexType.VertexDeclaration { 
      get { 
       return VertexDeclaration; 
      } 
     } 
    } 
} 

接下來我創建一個自定義Window類的實例。構造函數設置頂點緩衝區,並在效果中設置視圖,投影和顏色參數。

這裏是效果文件。

float4x4 view; 
float4x4 projection; 
float4 color; 
float shadowPercent = 0.36893203883495145631067961165049; 
float highlightPercent = 1.262135922330097087378640776699; 
Texture2D targetTexture; 

struct FillVertexShaderInput { 
    float4 position : POSITION0; 
}; 

struct FillPixelShaderInput { 
    float4 position : POSITION0; 
}; 

struct BorderPixelShaderInput { 
    float4 position : SV_Position; 
}; 

// Transforms color component range from 0-255 to 0-1. 
float4 ClampColor(float4 color) { 
    return float4(color[0]/255, color[1]/255, color[2]/255, color[3]/255); 
} 

// Shifts the value of a color by a percent to get border color and highlight color from a fill color. 
float4 ShiftValue(float4 color, float percent) { 
    return float4(clamp(color[0] * percent, 0, 1), clamp(color[1] * percent, 0, 1), clamp(color[2] * percent, 0, 1), clamp(color[3] * percent, 0, 1)); 
} 

FillPixelShaderInput FillVertexShader(FillVertexShaderInput input) { 
    FillPixelShaderInput output; 
    output.position = mul(mul(input.position, view), projection); 
    return output; 
} 

float4 FillPixelShader(FillPixelShaderInput input) : COLOR0 { 
    return color; 
} 

float4 BorderPixelShader(BorderPixelShaderInput input) : COLOR0 { 
    // Get color of pixel above? 
    // float4 tempColor = texture.Sample(sampler, (input.position[0], input.position[1] - width)); 
    return color; 
} 

technique Frame { 
    // Store Texture2D, sampler2D, and others to be stored between passes? 
    /*Texture2D texture; 
    sampler2D sampler; 
    float width; 
    float height; 
    texture.GetDimensions(width, height); 
    color = ClampColor(color); 
    float4 shadowColor = ShiftValue(color, shadowPercent); 
    float4 highlightColor = ShiftValue(color, highlightPercent);*/ 

    pass Fill { 
     VertexShader = compile vs_2_0 FillVertexShader(); 
     PixelShader = compile ps_2_0 FillPixelShader(); 
    } 

    pass Border { 
     PixelShader = compile ps_4_0 BorderPixelShader(); 
    } 
} 

我希望能夠將數據存儲之間傳遞,但我不知道這是可能的,所以我嘗試存儲XNA渲染目標,並用它作爲下一次的參數。

這是窗口的繪製代碼。

public void Draw(Game1 game) { 
    // rectangle is a simple window for this test. 
    RenderTarget2D target = new RenderTarget2D(game.GraphicsDevice, rectangle.Width, rectangle.Height); 
    game.GraphicsDevice.SetRenderTarget(target); 
    game.GraphicsDevice.BlendState = BlendState.AlphaBlend; 
    game.GraphicsDevice.Clear(Color.Transparent); 
    game.GraphicsDevice.SetVertexBuffer(vertexbuffer); 
    effect.Techniques["Frame"].Passes["Fill"].Apply(); 
    game.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); 
    game.GraphicsDevice.SetRenderTarget(null); 
    effect.Parameters["targetTexture"].SetValue(target); 
    effect.Techniques["Frame"].Passes["Border"].Apply(); 
} 

如果我能在像素着色器圍繞當前像素的像素位置和顏色,我能確定什麼顏色在當前位置繪製像素。填充工作正常。我只是不知道最好的方式來繪製邊界陰影和突出顯示。另外,我在alpha混合方面遇到問題。除了窗口以外的所有東西都是默認的深紫色,即使我設置了alpha混合並將渲染目標緩衝區清除爲透明。

如果您決定提供幫助,請事先致謝。

+0

對於混合,我認爲你想設置渲染目標緩衝區爲不透明,而不是,雖然我不積極。還要注意如何處理像素着色器中顏色的w分量,因爲這是不透明的。 – Thomas

+0

剛剛發現XNA內容管道只能編譯Shader Model 3_x和更低版本,所以我使用Texture2D.GetDimensions的想法將不起作用。此外,阿爾法混合只是因爲窗戶並不總是完美的正方形。有時角落會有透明的四捨五入。 – kkirkfield

+0

做了大量的研究,我發現了XNA如何使用RenderTargetUsage,並且默認情況下rendertargets共享後臺緩衝區的緩衝區。通過改變渲染目標我的後臺緩衝區被清除。我只是改變它來繪製背景和窗口來保存渲染目標,並解決了我的alpha問題的一部分。給任何人也有這個問題的提示:確保渲染目標格式支持alpha通道。不透明混合選項工作得很好,所以感謝。 – kkirkfield

回答

0

我相信它的工作原理是這樣的:

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input, float2 vPos : VPOS) 
{ 
// shader code here 
} 

然後,你可以使用vPos.xvPos.y訪問當前像素的座標,正在處理中。

相關問題