- Home /
How to get texture UV tiling and offset in a Surface Shader?
I am trying to obtain the UV tiling and offset in a surface shader. I'm referring to the standard variables you see in the material inspector when you add a texture property to your shader: _MainTex("Base (RGB) Gloss (A)", 2D) = "white" {}
I have seen plenty of examples and discussion about how to use _MainTex_ST and the TRANSFORM_TEX macro, but that seems to only be useful in vertex and fragment shaders, not Unity's magic Surface Shaders. You can declare UV coordinates as input to the Surface Shader, but that only seems to include UV, not tiling and offset. I looked at the complied code from the surface shader, and it seems to pack the UVs into the xy and the bump map UVs into the zw of a "pack" variable, with no tiling or offset.
I have also seen suggestions to create your own uv adjustment variable, and modify the UVs via that. I'm sure that works, but it bypasses the tiling and offset variables that are visible in the inspector.
Any suggestions as to how I can obtain the tiling and offset variables from the material inspector in a surface shader?
Answer by Glurth · Nov 01, 2016 at 04:25 PM
You mentioned you know about this:
"Materials often have Tiling and Offset fields for their texture properties. This information is passed into shaders in a float4 {TextureName}_ST property
....
For example, if a shader contains texture named _MainTex, the tiling information will be in a _MainTex_ST vector."
from: https://docs.unity3d.com/Manual/SL-PropertiesInPrograms.html
But I 'm not sure I understand what you mean about passing this in as a parameter to a surface shader. Though the UV coordinates WILL change from texel to texel, the offsets and tiling values should remain constant: Therefore I see no need to pass them as a parameters. Accessing them from the builtin variable mentioned above should be sufficient.
Here is an example using those variables in a surface shader. My usual method when figuring stuff out, or debugging shaders, is to use the output colors to represent the data I want to look at. Once this sample shader is attached to a material, and that to an object; you can change the material titling and offset, and watch color of objects follow the change, to show your data. (clearly, it does not use the actual texture to render.):
Shader "Custom/NewSurfaceShader" {
Properties {
_tex0 ("Texture1", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Transparent" }
LOD 200
CGPROGRAM
#pragma surface surf Standard alpha
#pragma target 3.0
float4 _tex0_ST;
struct Input {
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
o.Albedo.r = _tex0_ST.x;
o.Albedo.g = _tex0_ST.y;
o.Albedo.b = _tex0_ST.z;
o.Alpha = _tex0_ST.w;
}
ENDCG
}
FallBack "Diffuse"
}
Note that the shader properties you linked above are under the "Writing vertex and fragment shaders" section of the documentation, not the "Writing surface shaders" section. I have not been able to find any examples nor succeeded through trial and error of accessing the _xxx_ST variable in the surface function of a surface shader. If you could provide a code snippet of how that would work it would be greatly appreciated.
I do have a need to know the tiling and offset in the surface shader where I do a texture lookup.
"nor succeeded through trial and error of accessing the _xxx_ST variable in the surface function of a surface shader."
Oh! $$anonymous$$y bad then, I don't write many surface shaders. Still, I'll poke around the couple I've done to see if I used any ST variables.
Well that sample code definitely works. The problem is that when I add in code to sample the texture, I get a compile error. There seems to be some conflict in the auto-generated code that results from adding a sampler2D and tex2D call.
Here is your original code, plus the addition of a sampler2D, float2 texture coordinates in the Input structure, and the texture lookup. This results in a compilation error:
Shader "Custom/SurfTiling" {
Properties{
_tex0("Texture1", 2D) = "white" {}
}
SubShader{
Tags{"RenderType" = "Transparent"}
LOD 200
CGPROGRA$$anonymous$$
#pragma surface surf Standard alpha
#pragma target 3.0
sampler2D _tex0;
float4 _tex0_ST;
struct Input {
float2 uv_tex0;
};
fixed4 _Color;
void surf(Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
//o.Albedo.r = _tex0_ST.x;
//o.Albedo.g = _tex0_ST.y;
//o.Albedo.b = _tex0_ST.z;
//o.Alpha = _tex0_ST.w;
fixed4 tex = tex2D(_tex0, IN.uv_tex0);
o.Albedo = tex.rgb;
}
ENDCG
}
FallBack "Diffuse"
}
Shader compiler error: Shader error in 'Custom/SurfTiling': redefinition of '_tex0_ST' at line 67 (on d3d11)
Edit: I originally pasted the wrong compiler error, just updated to the redefinition error.
I remarked out the float4 _tex0_ST; and references to it, and got it to compile. I then looked at the generated compiler code, and sure enough, it stuck it's own version of float4 _tex0_ST;
somewhere in there with the generated stuff.
I have no idea how to deal with that. I tried saving and modifying the generate code, to no avail.
Well I sure do appreciate you taking the time to look into it. I am going to leave it for now, and add my own property in the shader for tiling. That workaround works fine, but now there is redundancy, and if someone uses the tiling variable they are used to using, it won't work as expected.
Unity is The Pareto Principle in full effect.
Answer by oukenshu · Apr 15, 2019 at 12:22 PM
I tried to fix it. @PsyDev
Shader "Custom/NewSurfaceShader" {
Properties {
_tex0 ("Texture1", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Transparent" }
LOD 200
CGPROGRAM
#pragma surface surf Standard alpha
#pragma target 3.0
struct Input {
float3 viewDir;
float4 _tex0_ST;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
o.Albedo.r = IN._tex0_ST.x;
o.Albedo.g = IN._tex0_ST.y;
o.Albedo.b = IN._tex0_ST.z;
o.Alpha = IN._tex0_ST.w;
}
ENDCG
}
FallBack "Diffuse"
}
Your answer
Follow this Question
Related Questions
Normalizing mesh UVS? 1 Answer
Sprite animation on quad with UV-coordinates 1 Answer
How do I generate a Sphere with proper UVs? 1 Answer
Split a mesh while using same UVs and texture position. 0 Answers
Distorted/Warped Textures On Character Model After Bundling For Tabletop Simulator/In A Build 1 Answer