CG:指定不在顶点和片段着色器之间插值的变量

时间:2012-12-14 10:23:28

标签: unity3d shader interpolation cg

我正在使用GCUnity3D内编写着色器。

我正在使用顶点颜色属性将一些参数传递给着色器。它们不会用于定义颜色,应该从顶点着色器转发到像素着色器而不修改它们。

这是我从Unity3D输入到顶点着色器的结构:

struct appdata_full {
    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    float4 texcoord1 : TEXCOORD1;
    fixed4 color : COLOR;
#if defined(SHADER_API_XBOX360)
    half4 texcoord2 : TEXCOORD2;
    half4 texcoord3 : TEXCOORD3;
    half4 texcoord4 : TEXCOORD4;
    half4 texcoord5 : TEXCOORD5;
#endif
};

这是顶点着色器返回的结构作为片段的输入:

struct v2f {
  float4 pos : SV_POSITION;
  float2  uv : TEXCOORD0;
  fixed4 col: COLOR;           
};

如果我只是将参数转发给片段着色器,当然它将被插值:

v2f vert (appdata_full v)
{

  v2f output;
  //....
  output.col = v.color;
}

我想将未插入的v.color参数传递给片段着色器。 这可能吗?如果是的话怎么样?


修改

像Tim指出的那样,这是预期的行为,因为如果从顶点着色器传递到片段,着色器除了插值颜色之外什么也做不了。 我会试着更好地解释一下我想要实现的目标。我使用每个顶点颜色来存储除颜色之外的其他信息。在没有详细说明我正在做什么的情况下,假设您可以将每个颜色顶点视为一个id(同一个三角形的每个顶点,将具有相同的颜色。实际上是同一网格的每个顶点)。

所以我使用颜色技巧来掩盖一些参数,因为我没有其他方法可以做到这一点。现在,必须以某种方式在片段着色器中提供这条信息。 如果传递作为顶点着色器的out参数,则编码为颜色的此信息将在片段处内插到达,不能再使用它。

我正在寻找一种方法来传播这些信息,直到片段着色器(也许可以使用全局变量或类似的东西?如果是的话?)。

5 个答案:

答案 0 :(得分:3)

这是一个非常古老的主题,但我最近遇到了类似的问题,我找到了一个非常简单的答案。 OSX Mavericks现在支持OpenGL 4.1,它很快就不会成为问题,但在Unity3d选择它之前还需要一段时间。 无论如何,即使在早期的OSX(例如Mountain Lion)上,也有一种简洁的方法可以在Unity中启用平面阴影!

下面的着色器将完成这项工作(关键部分是使用#extension的行,否则你会因使用关键字flat而遇到编译错误“

Shader "GLSL flat shader" {
SubShader {
  Pass {
     GLSLPROGRAM

     #extension GL_EXT_gpu_shader4 : require
     flat varying vec4 color;

     #ifdef VERTEX
     void main()
     {
        color = gl_Color;
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
     }
     #endif

     #ifdef FRAGMENT
     void main()
     {
        gl_FragColor = color; // set the output fragment color
     }
     #endif

     ENDGLSL
  }
  }
}

通过组合以下内容来实现: http://poniesandlight.co.uk/notes/flat_shading_on_osx/ http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Debugging_of_Shaders

答案 1 :(得分:2)

GPU将始终在值之间进行插值。如果要为三角形设置常量值,则需要为该三角形的所有顶点设置相同的值。这有时可能效率低下,但它是OpenGL(和DirectX)的工作原理。没有固有的“面子”价值观念。

答案 2 :(得分:1)

您可以这样做:glShadeModel(GL_FLAT)。这将关闭所有片段着色器输入的插值,并且也可用于较旧的OpenGL(4.0之前版本)。

如果你有一些想要插值的输入而有些你没有插入,用GL_FLAT渲染一次到与输出相同分辨率的纹理,然后用GL_SMOOTH再次渲染并对纹理进行采样以读取平面值每个像素(同时也以通常的方式获得插值)。

如果您可以使用DirectX9,则可以在单个片段着色器输入(着色器模型4或更高版本)上使用nointerpolation修饰符。

答案 3 :(得分:1)

我知道这是一个旧线程,但是还是值得回答的,因为这是Google的最佳搜索结果之一。 现在,您可以在常规CG着色器中为变量使用nointerpolation选项。即

nointerpolation fixed3 diff : COLOR0;

答案 4 :(得分:0)

这对我有用。不幸的是,DX使用顶点0作为激发顶点,而GL默认使用2。您可以在GL中更改它,但glProvokingVertex似乎没有暴露。 我们正在做平面着色,这将大大减少我们的顶点数量。 我们必须重新排列三角形并以特殊方式计算法线(如果有人感兴趣,我可以发布示例源)。 问题是我们必须在GL与DX上具有不同的网格,因为需要旋转三角形索引才能使三角形使用适当的激发顶点。 也许有某种方法可以通过插件执行GL命令。