1

我正在尝试编写一个着色器来逐个像素地读取整个帧,并在进行一些计算后重新写入像素。我查看了一些代码,但其中大多数都不相关。你能给我一些关于如何在 Unity 着色器编程中读取像素和写入像素的提示吗?

4

3 回答 3

1

如果你有 Unity 的 Pro 版本,你可以通过图像(后处理)效果来实现这一点。您所要做的就是在OnRenderImage相机的组件上实现回调。然后你调用Graphics.Blit一个有着色器的材质。着色器接收屏幕内容作为主纹理。

于 2013-09-23T11:33:40.427 回答
0

感谢您的意见。他们真的很有帮助。我终于得到了我的着色器的这段代码。而现在,一个新的问题刚刚出现。

我的解决方案: 为了解决我的基石问题,我采用了“戴眼镜”的想法!这意味着我已经放置在相机前面的一个平面上,并在上面附加了下面的着色器。然后我将飞机连接到相机上。现在的问题是着色器工作得很好,但在我的 VR 设置中它不起作用,因为我有几个摄像机,其中一个摄像机的场景失真(如我所愿),但其他摄像机的场景正常。一切都很好,直到这两个场景有交集。在那种情况下,我有一个不连贯的场景(如果不是正确的词,请原谅我)。顺便说一句,我认为与其将这个着色器用于“相机前面的平面”,不如将它应用到相机本身上。当我将它添加到相机时,我的着色器不起作用尽管它与平面对象完美配合。您能告诉我如何修改此代码以与相机兼容吗?除了我的解决方案之外,我非常欢迎听到您的建议和想法。

Shader "Custom/she1" {
    Properties {
    top("Top", Range(0,2)) = 1
    bottom("Bottom", Range(0,2)) = 1
}
    SubShader {

        // Draw ourselves after all opaque geometry
        Tags { "Queue" = "Transparent" }

        // Grab the screen behind the object into _GrabTexture
        GrabPass { }

        // Render the object with the texture generated above
        Pass {


CGPROGRAM
#pragma debug
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0

            sampler2D _GrabTexture : register(s0);
            float top;
            float bottom;

struct data {

    float4 vertex : POSITION;

    float3 normal : NORMAL;

};



struct v2f {

    float4 position : POSITION;

    float4 screenPos : TEXCOORD0;

};



v2f vert(data i){

    v2f o;

    o.position = mul(UNITY_MATRIX_MVP, i.vertex);

    o.screenPos = o.position;

    return o;

}



half4 frag( v2f i ) : COLOR

{

    float2 screenPos = i.screenPos.xy / i.screenPos.w;
    float _half = (top + bottom) * 0.5;
    float _diff = (bottom - top) * 0.5;
    screenPos.x = screenPos.x * (_half + _diff * screenPos.y);
      screenPos.x = (screenPos.x + 1) * 0.5;
    screenPos.y = 1-(screenPos.y + 1) * 0.5 ;
    half4 sum = half4(0.0h,0.0h,0.0h,0.0h);  
    sum = tex2D( _GrabTexture, screenPos);
    return sum;

}
ENDCG
        }
    }

Fallback Off
} 
于 2013-10-16T19:09:23.317 回答
0

您需要帧大小的纹理缓冲区。然后你想将你的帧渲染到一个缓冲区中。现在您需要编写一个片段着色器来读取一个缓冲区并写入另一个缓冲区。最后,您将片段着色器输出绘制为覆盖屏幕的平面对象。

在着色器编程中,您不会逐个像素地工作,您定义一个函数,该函数将用于单个像素的位置,该位置是所有 3 轴上从 0 到 1 的浮点数(尽管您只会使用 2)。然后该片段着色器并行运行大量像素,这就是它如何更快地完成所有事情的方式。

我希望简短的解释足以让您入门。Unity 片段着色器是用 Cg 编写的。Cg 是一种介于 OpenGL 语言 GLSL 和 DirectX 语言 HLSL 之间的语言,因为所有高级语言都编译成显卡上的本机指令,它们都非常相似。所以有很多关于Cg的示例,一旦你会写Cg,你阅读HLSL和GLSL就没有问题了。

于 2013-09-21T05:32:59.477 回答