Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Surface Shader with StructuredBuffer Error [SOLVED]

Discussion in 'Shaders' started by vladstorm_, Feb 27, 2017.

  1. vladstorm_

    vladstorm_

    Joined:
    Nov 26, 2013
    Posts:
    184
    Hi,

    How can I use Surface Shader with StructuredBuffer input?
    Code (CSharp):
    1. Shader "Custom/DirectX 11 Diffuse Mapping" {
    2.    Properties
    3.     {
    4.         _MainTex ("Texture", 2D) = "white" {}
    5.     }
    6.      SubShader {
    7.          Tags {"LightMode" = "ForwardBase" }
    8.            
    9.              
    10.          Pass {
    11.          CGPROGRAM
    12.          #include "UnityCG.cginc"
    13.          #pragma target 5.0
    14.          #pragma vertex vertex_shader
    15.          #pragma surface surf Lambert vertex:vert
    16.    
    17.          sampler2D _MainTex;
    18.          float4 _MainTex_ST;
    19.          uniform fixed4 _LightColor0;
    20.            
    21.          struct Point{
    22.              float3         vertex;
    23.              float3         normal;
    24.              float4         tangent;
    25.              float2 uv;
    26.          };  
    27.          StructuredBuffer<Point> points;
    28.  
    29.          struct v2f {
    30.             float4 pos : SV_POSITION;
    31.             float4 col : COLOR;
    32.             float2 uv : TEXCOORD0;
    33.          };
    34.          v2f vertex_shader (uint id : SV_VertexID, uint inst : SV_InstanceID) {
    35.             float4 vertex_position =  float4(points[id].vertex,1.0f);
    36.             float4 vertex_normal = float4(points[id].normal, 1.0f);        
    37.             v2f o;
    38.             // . . .
    39.             return o;
    40.          }
    41.    
    42.          struct Input {
    43.             float4 color : COLOR;
    44.          };
    45.          void surf (Input IN, inout SurfaceOutput o) {
    46.              o.Albedo = 1; // 1 = (1,1,1,1) = white
    47.          }
    48.  
    49.          ENDCG
    50.      }
    51.      }
    52. }
    When I'm trying to get vertices in vertex shader and then use surface shader - it doesn't work.
    Its saying
    Code (CSharp):
    1. Shader error in '...': Unexpected identifier "StructuredBuffer". Expected one of: typedef const void inline uniform nointerpolation extern shared static volatile row_major column_major struct or a user-defined type at line 31
     
    Last edited: Feb 28, 2017
  2. vladstorm_

    vladstorm_

    Joined:
    Nov 26, 2013
    Posts:
    184
    Ok, I fixed this error (found a solution here) but still can't make StructuredBuffer work with SurfaceShader

    Here's new code. I added SHADER_API_D3D11 to fix the problem
    Code (CSharp):
    1. Shader "Custom/kek" {
    2.  
    3.    Properties {
    4.       _MainTex ("Texture", 2D) = "white" {}
    5.    }
    6.  
    7.    SubShader {
    8.  
    9.       Tags { "RenderType" = "Opaque" }            
    10.            
    11.  
    12.       CGPROGRAM
    13.  
    14.       // #include "UnityCG.cginc"
    15.       #pragma target 5.0
    16.       #pragma vertex vert
    17.       #pragma surface surf Lambert
    18.  
    19.       sampler2D _MainTex;
    20.       float4 _MainTex_ST;
    21.          
    22.       struct Point{
    23.          float3 vertex;
    24.          float3 normal;
    25.          float4 tangent;
    26.          float2 uv;
    27.       };  
    28.  
    29.  
    30.       #ifdef SHADER_API_D3D11
    31.          StructuredBuffer<Point> points;
    32.       #endif
    33.  
    34.       struct v2f {
    35.          float4 pos : SV_POSITION;
    36.          float4 col : COLOR;
    37.          float2 uv : TEXCOORD0;
    38.       };
    39.  
    40.       v2f vert (uint id : SV_VertexID) { //, uint inst : SV_InstanceID
    41.  
    42.          float4 vertex_position =  float4(points[id].vertex,1.0f);
    43.          float4 vertex_normal = float4(points[id].normal, 1.0f);      
    44.          v2f o;
    45.          //....
    46.          return o;
    47.       }
    48.  
    49.       struct Input {
    50.           float4 color : COLOR;
    51.       };
    52.       void surf (Input IN, inout SurfaceOutput o) {
    53.          o.Albedo = fixed4(1f,0f,0f,1f);
    54.       }
    55.  
    56.       ENDCG
    57.  
    58.    }
    59. }
    The problem now is that StructuredBuffer needs
    uint id : SV_VertexID as vertex shader input
    but SurfaceShader needs
    inout appdata_full v as vertex shader input

    So I have this conflict and error message
    Code (CSharp):
    1. Shader error in '...': Surface shader vertex function 'vert' #0 parameter has wrong modifier; has no modifier but needs 'inout' at 'uint id' at line 12
    How can I solve it ?
     
  3. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    appdata_full is just one of the helper input structs. You can define your own.
     
  4. vladstorm_

    vladstorm_

    Joined:
    Nov 26, 2013
    Posts:
    184
    ok, but how can i combine uint id : SV_VertexID with appdata_custom?
    what's the right way to define vertex shader params? that I have SV_VertexID as an input and appdata_custom as an output?
     
  5. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Well, you can combine it by making that uint part of the struct. I honestly don't know whether it will work, but that would be the first thing to try. The input and output of a vertex and fragment shader is commonly a combination of values combined into a struct. So, just add the uint to the input struct.
     
  6. vladstorm_

    vladstorm_

    Joined:
    Nov 26, 2013
    Posts:
    184
    Just tried it. Didn't work

    Code (CSharp):
    1. Shader "Custom/kek"{ //StructuredBuffer+SurfaceShader
    2.  
    3.    // Properties {}
    4.    SubShader {
    5.  
    6.          CGPROGRAM
    7.  
    8.          #include "UnityCG.cginc"
    9.          #pragma target 5.0
    10.          #pragma surface surf Lambert vertex:vert
    11.  
    12.          struct Point{
    13.             float3 vertex;
    14.             float3 normal;
    15.             float4 tangent;
    16.             float2 uv;
    17.          };    
    18.  
    19.          #ifdef SHADER_API_D3D11
    20.             StructuredBuffer<Point> points;
    21.          #endif
    22.  
    23.  
    24.          struct appdata{
    25.             float4 vertex : SV_POSITION;
    26.             float3 normal : NORMAL;
    27.             float4 texcoord : TEXCOORD0;
    28.  
    29.             uint id : SV_VertexID;
    30.             uint inst : SV_InstanceID;
    31.          };
    32.  
    33.          struct Input {
    34.             float4 color : COLOR;
    35.          };
    36.  
    37.          void vert (inout appdata v) {
    38.  
    39.             v.vertex =  float4(points[id].vertex,1.0f);
    40.             v.normal =  float4(normalize(points[id].normal), 1.0f);
    41.             v.texcoord = points[id].uv;
    42.  
    43.          }
    44.  
    45.  
    46.          void surf (Input IN, inout SurfaceOutput o) {
    47.             o.Albedo = fixed4(1f,0f,0f,1f);
    48.          }
    49.  
    50.          ENDCG
    51.  
    52.    }
    53. }
    54.  
    Now it's giving me this error
    Code (CSharp):
    1. Shader error in '...': undeclared identifier 'id' at line 39 (on d3d11)
    So, obviously id isn't set. Please, unity people, help!
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Because it's part of the appdata struct, which is being passed to the vert function via the v variable.

    points[v.id]
     
  8. vladstorm_

    vladstorm_

    Joined:
    Nov 26, 2013
    Posts:
    184
    yeah! now it works.
    dude u always appear out of nowhere and fix stuff. unity wizard. thank you.
     
    scarletslavi likes this.