Super outil mais ça ne dispense pas de connaitre le codage d'un shader pour le maitriser!
héhéh l'univers du Shader voila une montagne de plus a gravir!! bah du coup je continue...
Super outil mais ça ne dispense pas de connaitre le codage d'un shader pour le maitriser!
Code : Tout sélectionner
Shader "Custom/tuto test grass3" {
Properties {
_Color ("Color", Color) = (1, 1, 1, 1)
//_ShadowColor ("_ShadowColor", Color) = (0, 0, 0, 1)
_grass ("Base (RGB) Trans (A)", 2D) = "white" {}
_ground ("ground", 2D) = "white" {}
_ground_offsetY ("ground offset Y", Range (-0.01, 0.1)) =0
_windnoise ("windnoise", 2D) = "white" {}
_Wind ("Wind", Range (0.0, 0.3)) =0.00
_offset ("offset", Range (-4.0, 4)) =0
_density("density", Range (1, 55)) =28
//_xoffset("x offset", Range (0, 1)) =0.5
//_yoffset("y offset", Range (0, 1)) =0.5
_Cutoff ("Base Alpha cutoff", Range (0,.9)) = .1
}
SubShader
{
Pass {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "LightMode" = "ForwardBase"}
Cull off
Lighting On
ZWrite On // don't occlude other objects
ZTest Less
Blend SrcAlpha OneMinusSrcAlpha
LOD 400
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 5.0
#include "UnityCG.cginc"
//#pragma multi_compile_fwdadd_fullshadows
//#include "AutoLight.cginc"
//#include "Lighting.cginc"
uniform float4 _Color;
uniform float4 _ShadowColor;
uniform sampler2D _grass;
uniform sampler2D _ground;
uniform sampler2D _windnoise;
uniform float _Wind;
uniform float _offset;
uniform float _density;
uniform float _xoffset;
uniform float _yoffset;
uniform float _Cutoff;
uniform float _ground_offsetY;
struct VertData
{
float4 pos : POSITION;
float3 norm : NORMAL;
float2 texCoord : TEXCOORD0;
float2 texCoord2 : TEXCOORD1;
float3 tang : TANGENT;
float4 vertColor : COLOR;
};
struct FragData
{
float4 oVertColor : COLOR;
float2 oTexCoord : TEXCOORD0;
float2 oTexCoord2 : TEXCOORD1;
float4 oPosition : POSITION;
float3 oEyeDirTan : TEXCOORD2;
float4 oPositionViewProj: TEXCOORD3;
//LIGHTING_COORDS(4,5)
};
struct Fragout
{
float4 color : COLOR;
float depth : DEPTH;
};
//-----------------------------------------------------------------------------
// Vertex
//-----------------------------------------------------------------------------
FragData vert( VertData IN )
{
FragData vOUT;
vOUT.oPosition = mul(UNITY_MATRIX_MVP, IN.pos); //oPosition must be output to satisy pipeline.
vOUT.oPositionViewProj = vOUT.oPosition;
vOUT.oTexCoord = IN.texCoord;
vOUT.oTexCoord2 = float2((IN.texCoord2.x+_Time.y*_Wind)/2,(IN.texCoord2.y+_Time.y*_Wind)/2); // offset second texture coordinate
// according to time for wind texture
vOUT.oVertColor = IN.vertColor;
float3 eyeDirO = -(_WorldSpaceCameraPos.xyz-IN.pos.xyz) ; //eye vector in object space
float3 binormal = cross(IN.tang,IN.norm);
float3x3 TBNMatrix = float3x3(IN.tang,binormal,IN.norm);
vOUT.oEyeDirTan = normalize(mul(TBNMatrix,eyeDirO)); // eye vector in tangent space
//TRANSFER_VERTEX_TO_FRAGMENT(vOUT);
return vOUT;
}
//Set everything which is constant in the fragment shader, the values used are for the moderate height data set.
#define MAX_RAYDEPTH 4 //Number of iterations.
#define PLANE_NUM _density //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 +_ground_offsetY //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.
//#define AVERAGE_COLOR float4(0.32156,0.513725,0.0941176,1.0) //Used to fill remaining opacity, can be replaced by a texture lookup.
//#define AVERAGE_COLOR float4(0.32156,0.513725,0.0941176,1.0) //Used to fill remaining opacity, can be replaced by a texture lookup.
//#define AVERAGE_COLOR float4(0.0,0.0,0.0,0.0) //Used to fill remaining opacity, can be replaced by a texture lookup.
//-----------------------------------------------------------------------------
// Fragment
//-----------------------------------------------------------------------------
Fragout frag(FragData IN)
{
Fragout OUT;
//Initialize increments/decrements and per fragment constants
//OUT.color = float4(0.0,0.0,0.0,0.0);
OUT.color = float4(0.0,0.0,0.0,0.0);
float2 plane_offset = float2(0.0,0.0);
float3 rayEntry = float3(IN.oTexCoord.x+_xoffset,IN.oTexCoord.y+_yoffset,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 signe = float2(sign(IN.oEyeDirTan.x),sign(IN.oEyeDirTan.y));
float2 plane_correct = float2((signe.x+1)*GRASS_SLICE_NUM_INV_DIV2,(signe.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((signe.x+1)*PLANE_NUM_INV_DIV2,(signe.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 proof 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(signe.x*plane_offset.x+pre_dir_correct.x , signe.y*plane_offset.y+pre_dir_correct.y);
float2 distance = float2((planemod.x + dir_correct.x - rayEntry.x)/(IN.oEyeDirTan.x) , (planemod.y + dir_correct.y - rayEntry.y)/(IN.oEyeDirTan.y));
float3 rayHitpointX = rayEntry + IN.oEyeDirTan *distance.x;
float3 rayHitpointY = rayEntry + IN.oEyeDirTan *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)/IN.oEyeDirTan.z; // rayEntry.z is 0.0 anyway
float3 rayHitpointZ = rayEntry + IN.oEyeDirTan *distanceZ;
float2 orthoLookupZ = float2(rayHitpointZ.x,rayHitpointZ.y);
OUT.color = (OUT.color)+((1.0-OUT.color.w) * tex2D(_ground,orthoLookupZ));
if(zFlag ==1)
zOffset = distanceZ; // write the distance from rayEntry to intersection
zFlag = 0; //Early exit here if faster.
}
else
{
float2 orthoLookup; //Will contain texture lookup coordinates for grassblades texture.
//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,IN.oTexCoord2+rayHitpointX.xy/TC1_TO_TC2_RATIO)-0.5)/2;
float lookupX = (rayHitpointX.z+(planemod.x+signe.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,IN.oTexCoord2+rayHitpointY.xy/TC1_TO_TC2_RATIO)-0.5)/2;
float lookupY = (rayHitpointY.z+(planemod.y+signe.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;
}
OUT.color += (1-OUT.color.w)*tex2D(_grass,orthoLookup);
//clip(-(OUT.color.w - _Cutoff));
if(OUT.color.w >= 0.49)
{zFlag = 0;} //Early exit here if faster.
}
}
OUT.color += (1.0-OUT.color.w)*_Color;
//Fill remaining transparency in case there is some left. Can be replaced by a texture lookup
//into a fully opaque grass slice using orthoLookup.
OUT.color.xyz *= (IN.oVertColor.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.
IN.oPositionViewProj += mul(IN.oPositionViewProj ,float4(IN.oEyeDirTan.xyz,1.0)*(zOffset*_offset));
//Divide by homogenous part.
OUT.depth = (IN.oPositionViewProj.z)/IN.oPositionViewProj.w;
return OUT;
}
ENDCG
}
}
}