Working on translating the grass shader from: Instant Animated Grass | TU Wien – Research Unit of Computer Graphics into Unity4 and coming across some errors that are very vague:
Shader "Hidden/TerrainEngine/Splatmap/Lightmap-FirstPass"
{
Properties
{
_Control ("Control (RGBA)", 2D) = "red" {}
_Splat3 ("Layer 3 (A)", 2D) = "white" {}
_Splat2 ("Layer 2 (B)", 2D) = "white" {}
_Splat1 ("Layer 1 (G)", 2D) = "white" {}
_Splat0 ("Layer 0 (R)", 2D) = "white" {}
// used in fallback on old cards
_MainTex ("BaseMap (RGB)", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
}
SubShader
{
Tags
{
"SplatCount" = "4"
"Queue" = "Geometry-100"
"RenderType" = "Opaque"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#pragma exclude_renderers d3d11_9x d3d11
#include "UnityCG.cginc"
struct v2f
{
float4 position : POSITION;
float4 color : COLOR; // vertex color, per vertex lightmap?
float2 texcoord : TEXCOORD0;
float2 texcoord1 : TEXCOORD1;
float3 eyeDirTan : TEXCOORD2;
//float4 positionViewProj : TEXCOORD3;
};
float4 _EyePosition;
float _WindTime; // runs from 0 to 10 per second
sampler2D _GrassTex;
sampler2D _GrassTex1;
sampler2D _GrassBlades;
sampler2D _WindNoise;
sampler2D _ColorMap;
float4 _GrassTex_ST;
float4 _GrassTex1_ST;
v2f vert (inout appdata_full v)
{
// Supply the shader with tangents for the terrain
//float3 normal = v.normal;
//float3 binormal = cross(float3(1, 0, 1), normal);
//float3 tangent = normalize(cross(normal, binormal));
//
// set tangent
//v.tangent.xyz = tangent.xyz;
//if (dot(cross(normal, tangent), binormal) < 0)
//{
// v.tangent.w = -1.0f;
//}
//else
//{
// v.tangent.w = 1.0f;
//}
//float3x3 TangentBinormalNormalMatrix = float3x3(tangent, binormal, normal);
float3x3 TangentBinormalNormalMatrix = float3x3(float3(0,0,0), float3(0,0,0), float3(0,0,0));
v2f output;
output.position = mul(UNITY_MATRIX_MVP, v.vertex);
//output.positionViewProj = output.position;
output.texcoord = TRANSFORM_TEX(v.texcoord, _GrassTex);
output.texcoord1 = TRANSFORM_TEX(v.texcoord1, _GrassTex1);
output.texcoord1 = float2((output.texcoord1.x + _WindTime * 0.2) / 2,
(output.texcoord1.y + _WindTime * 0.2) / 2); // coordinate offset by time from wind texture
output.color = v.color;
float4 eyeDir = -(_EyePosition - output.position);
output.eyeDirTan = normalize(mul(TangentBinormalNormalMatrix, eyeDir.xyz));
return output;
}
// Set everything which is constant in the fragment shader, the values used are for the moderate height data set.
#define MAX_RAYDEPTH 5 // Number of iterations.
#define PLANE_NUM 16.0 // Number of grass slice grid planes per unit in tangent space.
#define PLANE_NUM_INV (1.0 / PLANE_NUM)
#define PLANE_NUM_INV_DIV2 (PLANE_NUM_INV / 2)
#define GRASS_SLICE_NUM 8 // Number of grass slices in texture grassblades.
#define GRASS_SLICE_NUM_INV (1.0 / GRASS_SLICE_NUM)
#define GRASS_SLICE_NUM_INV_DIV2 (GRASS_SLICE_NUM_INV / 2)
#define GRASSDEPTH GRASS_SLICE_NUM_INV // Depth set to inverse of number of grass slices so no stretching occurs.
#define TC1_TO_TC2_RATIO 8 // Ratio of texture coordinate set 1 to texture coordinate set 2, used for the animation lookup.
#define PREMULT (GRASS_SLICE_NUM_INV*PLANE_NUM) // Saves a multiply in the shader.
void frag(v2f input)
{
//Initialize increments/decrements and per fragment constants
float2 orthoLookup; // Will contain texture lookup coordinates for grassblades texture.
float4 color = float4(0.0, 0.0, 0.0, 0.0);
float2 plane_offset = float2(0.0, 0.0);
float3 rayEntry = float3(input.texcoord.xy, 0.0);
float zOffset = 0.0;
bool zFlag = 1;
//The signs of eyeDirTan determines if we increment or decrement along the tangent space axis
//plane_correct, planemod and pre_dir_correct are used to avoid unneccessary if-conditions.
float2 dirSign = float2(sign(input.eyeDirTan.x), sign(input.eyeDirTan.y));
float2 plane_correct = float2((dirSign.x + 1) * GRASS_SLICE_NUM_INV_DIV2,
(dirSign.y + 1) * GRASS_SLICE_NUM_INV_DIV2);
float2 planemod = float2(floor(rayEntry.x * PLANE_NUM) / PLANE_NUM,
floor(rayEntry.y * PLANE_NUM) / PLANE_NUM);
float2 pre_dir_correct = float2((dirSign.x + 1) * PLANE_NUM_INV_DIV2,
(dirSign.y + 1) * PLANE_NUM_INV_DIV2);
int hitcount;
for (hitcount = 0; hitcount < MAX_RAYDEPTH % (MAX_RAYDEPTH + 1); hitcount++) // %([MAX_RAYDEPTH] + 1) speeds up compilation.
// It may prove to be faster to early exit this loop
// depending on the hardware used.
{
//Calculate positions of the intersections with the next grid planes on the u, v tangent space axis independently.
float2 dir_correct = float2(dirSign.x * plane_offset.x + pre_dir_correct.x,
dirSign.y * plane_offset.y + pre_dir_correct.y);
float2 distance = float2((planemod.x + dir_correct.x - rayEntry.x) / (input.eyeDirTan.x),
(planemod.y + dir_correct.y - rayEntry.y) / (input.eyeDirTan.y));
float3 rayHitpointX = rayEntry + input.eyeDirTan * distance.x;
float3 rayHitpointY = rayEntry + input.eyeDirTan * distance.y;
//Check if we hit the ground. If so, calculate the intersection and look up the ground texture and blend colors.
if ((rayHitpointX.z <= -GRASSDEPTH) (rayHitpointY.z <= -GRASSDEPTH))
{
float distanceZ = (-GRASSDEPTH) / input.eyeDirTan.z; // rayEntry.z is 0.0 anyway
float3 rayHitpointZ = rayEntry + input.eyeDirTan * distanceZ;
float2 orthoLookupZ = float2(rayHitpointZ.x, rayHitpointZ.y);
color += (1.0 - color.w) * tex2D(_ColorMap, orthoLookupZ);
if (zFlag == 1)
{
zOffset = distanceZ; // write the distance from rayEntry to intersection
}
zFlag = 0; //Early exit here if faster.
}
else
{
//check if we hit a u or v plane, calculate lookup accordingly with wind shear displacement.
if(distance.x <= distance.y)
{
float4 windX = (tex2D(_WindNoise, input.texcoord1 + rayHitpointX.xy / TC1_TO_TC2_RATIO) - 0.5) / 2;
float lookupX = -(rayHitpointX.z + (planemod.x + dirSign.x * plane_offset.x) * PREMULT) - plane_correct.x;
orthoLookup = float2(rayHitpointX.y + windX.x * (GRASSDEPTH + rayHitpointX.z), lookupX);
plane_offset.x += PLANE_NUM_INV; // increment/decrement to next grid plane on u axis
if (zFlag==1)
{
zOffset = distance.x;
}
}
else
{
float4 windY = (tex2D(_WindNoise, input.texcoord1 + rayHitpointY.xy / TC1_TO_TC2_RATIO) -0.5) / 2;
float lookupY = -(rayHitpointY.z + (planemod.y + dirSign.y * plane_offset.y) * PREMULT) - plane_correct.y;
orthoLookup = float2(rayHitpointY.x + windY.y * (GRASSDEPTH + rayHitpointY.z), lookupY);
plane_offset.y += PLANE_NUM_INV; // increment/decrement to next grid plane on v axis
if (zFlag==1)
{
zOffset = distance.y;
}
}
color += (1.0 - color.w) * tex2D(_GrassBlades, orthoLookup);
if (color.w >= 0.49)
{
zFlag = 0;
} //Early exit here if faster.
}
}
color += (1.0 - color.w) * tex2D(_ColorMap, orthoLookup); //Fill remaining transparency in case there is some left. Can be replaced by a texture lookup
//into a fully opaque grass slice using orthoLookup.
color.xyz *= (input.color.xyz); //Modulate with per vertex lightmap,as an alternative, modulate with N*L for dynamic lighting.
//zOffset is along eye direction, transform and add to vertex position to get correct z-value.
//input.positionViewProj += mul(UNITY_MATRIX_MVP, input.eyeDirTan.xzy * zOffset);
//Divide by homogenous part.
//input.depth = positionView.z/positionView.w;
}
ENDCG
}
// Fallback to Diffuse
Fallback "Diffuse"
}
You’ll notice that there were some variables defined: “normal”, “binormal”, “tangent”. I worried that these might be naming conflicts so I first commented them out (as in the above code) and replaced their dependencies. This unfortunately had no affect. I have also renamed them and deleted them completely and still get the same error messages.
What am I doing wrong? ![]()