Hi,
How can I use Surface Shader with StructuredBuffer input?
Shader "Custom/DirectX 11 Diffuse Mapping" {
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags {"LightMode" = "ForwardBase" }
Pass {
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 5.0
#pragma vertex vertex_shader
#pragma surface surf Lambert vertex:vert
sampler2D _MainTex;
float4 _MainTex_ST;
uniform fixed4 _LightColor0;
struct Point{
float3 vertex;
float3 normal;
float4 tangent;
float2 uv;
};
StructuredBuffer<Point> points;
struct v2f {
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 uv : TEXCOORD0;
};
v2f vertex_shader (uint id : SV_VertexID, uint inst : SV_InstanceID) {
float4 vertex_position = float4(points[id].vertex,1.0f);
float4 vertex_normal = float4(points[id].normal, 1.0f);
v2f o;
// . . .
return o;
}
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = 1; // 1 = (1,1,1,1) = white
}
ENDCG
}
}
}
When I’m trying to get vertices in vertex shader and then use surface shader - it doesn’t work.
Its saying
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
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
Shader "Custom/kek" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
// #include "UnityCG.cginc"
#pragma target 5.0
#pragma vertex vert
#pragma surface surf Lambert
sampler2D _MainTex;
float4 _MainTex_ST;
struct Point{
float3 vertex;
float3 normal;
float4 tangent;
float2 uv;
};
#ifdef SHADER_API_D3D11
StructuredBuffer<Point> points;
#endif
struct v2f {
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 uv : TEXCOORD0;
};
v2f vert (uint id : SV_VertexID) { //, uint inst : SV_InstanceID
float4 vertex_position = float4(points[id].vertex,1.0f);
float4 vertex_normal = float4(points[id].normal, 1.0f);
v2f o;
//....
return o;
}
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = fixed4(1f,0f,0f,1f);
}
ENDCG
}
}
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
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 ?
jvo3dc
February 27, 2017, 12:53pm
3
appdata_full is just one of the helper input structs. You can define your own.
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?
jvo3dc
February 27, 2017, 3:50pm
5
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.
jvo3dc:
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.
Just tried it. Didn’t work
Shader "Custom/kek"{ //StructuredBuffer+SurfaceShader
// Properties {}
SubShader {
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 5.0
#pragma surface surf Lambert vertex:vert
struct Point{
float3 vertex;
float3 normal;
float4 tangent;
float2 uv;
};
#ifdef SHADER_API_D3D11
StructuredBuffer<Point> points;
#endif
struct appdata{
float4 vertex : SV_POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
uint id : SV_VertexID;
uint inst : SV_InstanceID;
};
struct Input {
float4 color : COLOR;
};
void vert (inout appdata v) {
v.vertex = float4(points[id].vertex,1.0f);
v.normal = float4(normalize(points[id].normal), 1.0f);
v.texcoord = points[id].uv;
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = fixed4(1f,0f,0f,1f);
}
ENDCG
}
}
Now it’s giving me this error
Shader error in '...': undeclared identifier 'id' at line 39 (on d3d11)
So, obviously id isn’t set. Please, unity people, help!
bgolus
February 28, 2017, 6:39pm
7
Because it’s part of the appdata struct, which is being passed to the vert function via the v variable.
points[v.id]
4 Likes
yeah! now it works.
dude u always appear out of nowhere and fix stuff. unity wizard. thank you.
1 Like