• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Lewinio · 6 days ago · shadershadersuniversalvertex shader

URP Height Map Shader Problem,URP Custom Shader: Cannot access the UVs of the object

Hello, I am trying to add a height map to a grass shader. Unfortunately I can't access the Uvs of the object to get the coordinate at the texture. What could be the reason for this? Unfortunately I am still quite new to shaders. Thanks for your help

Here the Shader:

 Shader "Unlit/GeoGrass" {
         Properties {
             _Color("Colour", Color) = (1,1,1,1)
             _Color2("Colour2", Color) = (1,1,1,1)
             _Width("Width", Float) = 1
             _RandomWidth("Random Width", Float) = 1
             _Height("Height", Float) = 1
             _RandomHeight("Random Height", Float) = 1
             _WindStrength("Wind Strength", Float) = 0.1
             [Space]
             _TessellationUniform("Tessellation Uniform", Range(1, 64)) = 1
             _GrassMap("GrassVisibilityMap", 2D) = "white" {}
             _GrassThreshold("Grass Visibility Threshold", Range(-0.1, 1)) = 0.5
         }
 
         SubShader {
             Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
             LOD 300
 
             Cull Off
 
             Pass {
                 Name "ForwardLit"
                 Tags {"LightMode" = "UniversalForward"}
 
                 HLSLPROGRAM
                 // Required to compile gles 2.0 with standard srp library
                 #pragma prefer_hlslcc gles
                 #pragma exclude_renderers d3d11_9x gles
                 #pragma target 4.5
 
                 #pragma require geometry
 
                 #pragma vertex vert
                 #pragma geometry geom
                 #pragma fragment frag
                 #pragma hull hull
                 #pragma domain domain
 
                 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
                 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
                 #pragma multi_compile _ _SHADOWS_SOFT
 
                 // Defines
 
                 #define BLADE_SEGMENTS 1
 
                 // Includes
 
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
                 #include "grass_structs.hlsl"
                 #include "CustomTessellation.hlsl"
                 #include "grass.hlsl"
 
                 // Fragment
 
                 float4 frag(GeometryOutput input) : SV_Target {
                     #if SHADOWS_SCREEN
                         float4 clipPos = TransformWorldToHClip(input.positionWS);
                         float4 shadowCoord = ComputeScreenPos(clipPos);
                     #else
                         float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS);
                     #endif
 
                     Light mainLight = GetMainLight(shadowCoord);
 
                     return lerp(_Color, _Color2, input.uv.y) * mainLight.shadowAttenuation;
                 }
 
                 ENDHLSL
             }
         }
 }

And here are the other classes:

grass.hlsl

 float rand(float3 seed) {
     return frac(sin(dot(seed.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
 }
 
 // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
 float3x3 AngleAxis3x3(float angle, float3 axis) {
     float c, s;
     sincos(angle, s, c);
 
     float t = 1 - c;
     float x = axis.x;
     float y = axis.y;
     float z = axis.z;
 
     return float3x3(
         t * x * x + c, t * x * y - s * z, t * x * z + s * y,
         t * x * y + s * z, t * y * y + c, t * y * z - s * x,
         t * x * z - s * y, t * y * z + s * x, t * z * z + c
     );
 }
 
 float3 _LightDirection;
 
 float4 GetShadowPositionHClip(float3 positionWS, float3 normalWS) {
     float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
 
 #if UNITY_REVERSED_Z
     positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
 #else
     positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
 #endif
 
     return positionCS;
 }
 
 float4 WorldToHClip(float3 positionWS, float3 normalWS) {
 #ifdef SHADOW
     return GetShadowPositionHClip(positionWS, normalWS);
 #else
     return TransformWorldToHClip(positionWS);
 #endif
 }
 
 // Variables
 CBUFFER_START(UnityPerMaterial) // Required to be compatible with SRP Batcher
 float4 _Color;
 float4 _Color2;
 float _Width;
 float _RandomWidth;
 float _WindStrength;
 float _Height;
 float _RandomHeight;
 
 sampler2D _GrassMap;
 float4 _GrassMap_ST;
 float  _GrassThreshold;
 CBUFFER_END
 
 // Vertex, Geometry & Fragment Shaders
 
 Varyings vert(Attributes input) {
     Varyings output = (Varyings)0;
 
     VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
     // Seems like GetVertexPositionInputs doesn't work with SRP Batcher inside geom function?
     // Had to move it here, in order to obtain positionWS and pass it through the Varyings output.
 
     output.positionOS = input.positionOS; //vertexInput.positionCS; //
     output.positionWS = vertexInput.positionWS;
     output.normal = input.normal;
     output.tangent = input.tangent;
     return output;
 }
 
 [maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
 void geom(uint primitiveID : SV_PrimitiveID, triangle Varyings input[3], inout TriangleStream<GeometryOutput> triStream) {
     GeometryOutput output = (GeometryOutput)0;
 
     float grassVisibility = tex2Dlod(_GrassMap, float4(input[0].uv, 0, 0)).r;
 
     if(grassVisibility >= _GrassThreshold) {
         // Construct World -> Tangent Matrix (for aligning grass with mesh normals)
         float3 normal = input[0].normal;
         float4 tangent = input[0].tangent;
         float3 binormal = cross(normal, tangent) * tangent.w;
 
         float3x3 tangentToLocal = float3x3(
             tangent.x, binormal.x, normal.x,
             tangent.y, binormal.y, normal.y,
             tangent.z, binormal.z, normal.z
             );
 
         float3 positionWS = input[0].positionWS;
 
         float r = rand(positionWS.xyz);
         float3x3 randRotation = AngleAxis3x3(r * TWO_PI, float3(0, 0, 1));
 
         // Wind (based on sin / cos, aka a circular motion, but strength of 0.1 * sine)
         float2 wind = float2(sin(_Time.y + positionWS.x * 0.5), cos(_Time.y + positionWS.z * 0.5)) * _WindStrength * sin(_Time.y + r);
         float3x3 windMatrix = AngleAxis3x3((wind * PI).y, normalize(float3(wind.x, wind.y, 0)));
 
         float3x3 transformMatrix = mul(tangentToLocal, randRotation);
         float3x3 transformMatrixWithWind = mul(mul(tangentToLocal, windMatrix), randRotation);
 
         float bend = rand(positionWS.xyz) - 0.5;
         float width = _Width + _RandomWidth * (rand(positionWS.zyx) - 0.5);
         float height = _Height + _RandomHeight * (rand(positionWS.yxz) - 0.5);
 
         float3 normalWS = mul(transformMatrix, float3(0, 1, 0)); //?
 
         // Handle Geometry
 
         // Base 2 vertices
         output.positionWS = positionWS + mul(transformMatrix, float3(width, 0, 0));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 0);
         triStream.Append(output);
 
         output.positionWS = positionWS + mul(transformMatrix, float3(-width, 0, 0));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 0);
         triStream.Append(output);
 
         // Final vertex at top of blade
         output.positionWS = positionWS + mul(transformMatrixWithWind, float3(0, bend, height));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 1);
         triStream.Append(output);
 
         triStream.RestartStrip();
     }
 }

And here the structs: grass_struct.hlsl

 struct Attributes {
     float4 positionOS   : POSITION;
     float3 normal        : NORMAL;
     float4 tangent        : TANGENT;
     float2 uv             : TEXCOORD0;
 };
 
 struct Varyings {
     float4 positionOS   : SV_POSITION;
     float3 positionWS    : TEXCOORD1;
     float2 uv            : TEXCOORD0;
     float3 normal        : NORMAL;
     float4 tangent        : TANGENT;
 };
 
 struct GeometryOutput {
     float4 positionCS    : SV_POSITION;
     float3 positionWS    : TEXCOORD1;
     float2 uv            : TEXCOORD0;
 };

In the grass.hlsl file I try to achieve the effect with these lines:

 float grassVisibility = tex2Dlod(_GrassMap, float4(input[0].uv, 0, 0)).r;
 
     if(grassVisibility >= _GrassThreshold) {
 ...
 }

The input[0].uv does not return the appropriate values

,Hello, I am trying to add a Height Map in a Grass Shader in URP. However, I am not quite getting anywhere. I know that I have to check the UVs and which value is there on the texture. But my problem is that I can't get the UVs from the object and query them. Does anyone have any ideas? It would help me a lot. Thanks

Here is the Grass Shader:

 Shader "Unlit/GeoGrass" {
         Properties {
             _Color("Colour", Color) = (1,1,1,1)
             _Color2("Colour2", Color) = (1,1,1,1)
             _Width("Width", Float) = 1
             _RandomWidth("Random Width", Float) = 1
             _Height("Height", Float) = 1
             _RandomHeight("Random Height", Float) = 1
             _WindStrength("Wind Strength", Float) = 0.1
             [Space]
             _TessellationUniform("Tessellation Uniform", Range(1, 64)) = 1
             _GrassMap("GrassVisibilityMap", 2D) = "white" {}
             _GrassThreshold("Grass Visibility Threshold", Range(-0.1, 1)) = 0.5
         }
 
         SubShader {
             Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
             LOD 300
 
             Cull Off
 
             Pass {
                 Name "ForwardLit"
                 Tags {"LightMode" = "UniversalForward"}
 
                 HLSLPROGRAM
                 // Required to compile gles 2.0 with standard srp library
                 #pragma prefer_hlslcc gles
                 #pragma exclude_renderers d3d11_9x gles
                 #pragma target 4.5
 
                 #pragma require geometry
 
                 #pragma vertex vert
                 #pragma geometry geom
                 #pragma fragment frag
                 #pragma hull hull
                 #pragma domain domain
 
                 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
                 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
                 #pragma multi_compile _ _SHADOWS_SOFT
 
                 // Defines
 
                 #define BLADE_SEGMENTS 1
 
                 // Includes
 
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
                 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
                 #include "grass_structs.hlsl"
                 #include "CustomTessellation.hlsl"
                 #include "grass.hlsl"
 
                 // Fragment
 
                 float4 frag(GeometryOutput input) : SV_Target {
                     #if SHADOWS_SCREEN
                         float4 clipPos = TransformWorldToHClip(input.positionWS);
                         float4 shadowCoord = ComputeScreenPos(clipPos);
                     #else
                         float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS);
                     #endif
 
                     Light mainLight = GetMainLight(shadowCoord);
 
                     return lerp(_Color, _Color2, input.uv.y) * mainLight.shadowAttenuation;
                 }
 
                 ENDHLSL
             }
         }
 }

Here is the code that is accessed

grass_struct.hlsl

 struct Attributes {
     float4 positionOS   : POSITION;
     float3 normal        : NORMAL;
     float4 tangent        : TANGENT;
     float2 uv             : TEXCOORD0;
 };
 
 struct Varyings {
     float4 positionOS   : SV_POSITION;
     float3 positionWS    : TEXCOORD1;
     float2 uv            : TEXCOORD0;
     float3 normal        : NORMAL;
     float4 tangent        : TANGENT;
 };
 
 struct GeometryOutput {
     float4 positionCS    : SV_POSITION;
     float3 positionWS    : TEXCOORD1;
     float2 uv            : TEXCOORD0;
 };

grass.hlsl

 float rand(float3 seed) {
     return frac(sin(dot(seed.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
 }
 
 // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
 float3x3 AngleAxis3x3(float angle, float3 axis) {
     float c, s;
     sincos(angle, s, c);
 
     float t = 1 - c;
     float x = axis.x;
     float y = axis.y;
     float z = axis.z;
 
     return float3x3(
         t * x * x + c, t * x * y - s * z, t * x * z + s * y,
         t * x * y + s * z, t * y * y + c, t * y * z - s * x,
         t * x * z - s * y, t * y * z + s * x, t * z * z + c
     );
 }
 
 float3 _LightDirection;
 
 float4 GetShadowPositionHClip(float3 positionWS, float3 normalWS) {
     float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
 
 #if UNITY_REVERSED_Z
     positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
 #else
     positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
 #endif
 
     return positionCS;
 }
 
 float4 WorldToHClip(float3 positionWS, float3 normalWS) {
 #ifdef SHADOW
     return GetShadowPositionHClip(positionWS, normalWS);
 #else
     return TransformWorldToHClip(positionWS);
 #endif
 }
 
 // Variables
 CBUFFER_START(UnityPerMaterial) // Required to be compatible with SRP Batcher
 float4 _Color;
 float4 _Color2;
 float _Width;
 float _RandomWidth;
 float _WindStrength;
 float _Height;
 float _RandomHeight;
 
 sampler2D _GrassMap;
 float4 _GrassMap_ST;
 float  _GrassThreshold;
 CBUFFER_END
 
 // Vertex, Geometry & Fragment Shaders
 
 Varyings vert(Attributes input) {
     Varyings output = (Varyings)0;
 
     VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
     // Seems like GetVertexPositionInputs doesn't work with SRP Batcher inside geom function?
     // Had to move it here, in order to obtain positionWS and pass it through the Varyings output.
 
     output.positionOS = input.positionOS; //vertexInput.positionCS; //
     output.positionWS = vertexInput.positionWS;
     output.normal = input.normal;
     output.tangent = input.tangent;
     return output;
 }
 
 [maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
 void geom(uint primitiveID : SV_PrimitiveID, triangle Varyings input[3], inout TriangleStream<GeometryOutput> triStream) {
     GeometryOutput output = (GeometryOutput)0;
 
     float grassVisibility = tex2Dlod(_GrassMap, float4(input[0].uv, 0, 0)).r;
 
     if(grassVisibility >= _GrassThreshold) {
         // Construct World -> Tangent Matrix (for aligning grass with mesh normals)
         float3 normal = input[0].normal;
         float4 tangent = input[0].tangent;
         float3 binormal = cross(normal, tangent) * tangent.w;
 
         float3x3 tangentToLocal = float3x3(
             tangent.x, binormal.x, normal.x,
             tangent.y, binormal.y, normal.y,
             tangent.z, binormal.z, normal.z
             );
 
         float3 positionWS = input[0].positionWS;
 
         float r = rand(positionWS.xyz);
         float3x3 randRotation = AngleAxis3x3(r * TWO_PI, float3(0, 0, 1));
 
         // Wind (based on sin / cos, aka a circular motion, but strength of 0.1 * sine)
         float2 wind = float2(sin(_Time.y + positionWS.x * 0.5), cos(_Time.y + positionWS.z * 0.5)) * _WindStrength * sin(_Time.y + r);
         float3x3 windMatrix = AngleAxis3x3((wind * PI).y, normalize(float3(wind.x, wind.y, 0)));
 
         float3x3 transformMatrix = mul(tangentToLocal, randRotation);
         float3x3 transformMatrixWithWind = mul(mul(tangentToLocal, windMatrix), randRotation);
 
         float bend = rand(positionWS.xyz) - 0.5;
         float width = _Width + _RandomWidth * (rand(positionWS.zyx) - 0.5);
         float height = _Height + _RandomHeight * (rand(positionWS.yxz) - 0.5);
 
         float3 normalWS = mul(transformMatrix, float3(0, 1, 0)); //?
 
         // Handle Geometry
 
         // Base 2 vertices
         output.positionWS = positionWS + mul(transformMatrix, float3(width, 0, 0));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 0);
         triStream.Append(output);
 
         output.positionWS = positionWS + mul(transformMatrix, float3(-width, 0, 0));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 0);
         triStream.Append(output);
 
         // Final vertex at top of blade
         output.positionWS = positionWS + mul(transformMatrixWithWind, float3(0, bend, height));
         output.positionCS = WorldToHClip(output.positionWS, normalWS);
         output.uv = float2(0, 1);
         triStream.Append(output);
 
         triStream.RestartStrip();
     }
 }

With grass.hlsl I try to achieve the effect with these lines:

 float grassVisibility = tex2Dlod(_GrassMap, float4(input[0].uv, 0, 0)).r;
     
 if(grassVisibility >= _GrassThreshold) {
 ...
 }
 
 


Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

229 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Quad vertex color shader 0 Answers

Mobile performance of splat map shader with distance blending 0 Answers

What is the meaning of a vertex shader for a post-processing shader? 1 Answer

Need to get lighting to work on bending vertex shader... 1 Answer

'vert': output parameter 'o' not completely initialized 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges