Hey, it seems like my previous comment has been blocked for some unknown reason, so I will repost it.
I don’t want you to feel force to have a look at my shader, but if you offer to help i’m not refusing
It has evolved a bit since earlier. I added cube map reflections as suggested in this tutorial : Unity - Manual: Surface Shader examples (I’m using Unity 5.6.3).
(some edits at the end)
For some reason, I still get weird reflections. They seem to stretch and repeat, just like in the image I attached in a previous comment of mine. I’m sure I’m really close to get something that looks cool. There must be a tiny mistake somewhere that messes all up, but I can’t find what.
Here is the latest code of my shader, but it’s totally okay if you don’t have time to help me, you’re not here to code my game for me :
Shader "WaterVertexShader"
{
Properties
{
_Speed ("Speed", Float) = 0.5
_Scale ("Scale", Float) = 0.5
_Height ("Height", Float) = 0.2
_Color("Color", Color) = (0,0,0.5,1)
_Specular("Specular", Color) = (1,1,1,1)
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Cube ("Cubemap", CUBE) = "" {}
}
SubShader
{
Tags { "RenderType" = "Transprent" }
CGPROGRAM
#pragma target 5.0
#pragma surface surf StandardSpecular vertex:VSMain //fragment:FSMain
//#pragma fragment FSMain
//#pragma multi_compile_fog
#include "UnityCG.cginc"
#include "Assets/SimplexNoise/noiseSimplex.cginc"
struct VertexToFragment
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_Position;
};
sampler2D _MainTex;
float4 _MainTex_ST;
uniform half _Glossiness;
uniform fixed4 _Color;
uniform fixed3 _Specular;
uniform samplerCUBE _Cube;
uniform float _Speed;
uniform float _Scale;
uniform float _Height;
uniform float _NormalSmoothing;
uniform float4 localDirections[400];
static const uint xResolution = 20;
static const uint zResolution = 20;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 color : COLOR;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
uint id : SV_VertexID;
};
inline uint IndexFromXZ(uint x, uint z)
{
return z * xResolution + x;
}
inline uint XFromIndex(uint index)
{
return index % xResolution;
}
inline uint ZFromIndex(uint index)
{
return index / xResolution;
}
float4 GetUpdatedVertexRecomputeWorldPosition(float4 localBasePoint, uint index)
{
float3 worldBasePoint = mul(unity_ObjectToWorld, localBasePoint).xyz;
float3 localDirection = localDirections[index];
float3 time3 = _Time.xyz * _Speed;
float height = snoise(worldBasePoint * _Scale + time3) * _Height;
float3 updatedVertex = localBasePoint + localDirection * height;
return float4(updatedVertex.xyz, localBasePoint.b);
}
inline bool IsEdgeVertex(uint x, uint z)
{
return x == 0 || x == xResolution - 1 || z == 0 || z == zResolution - 1;
}
struct Input
{
float2 uv_MainTex;
float4 vertex : POSITION;
float4 color : COLOR;
float3 worldRefl;
};
VertexToFragment VSMain(inout appdata v, out Input inp)
{
UNITY_INITIALIZE_OUTPUT(Input,inp);
uint index = v.id;
uint x = XFromIndex(index);
uint z = ZFromIndex(index);
float4 currentXZVertex = GetUpdatedVertexRecomputeWorldPosition(v.vertex, index);
float3 normal;
if (IsEdgeVertex(x, z))
{
normal = float3(0, 1, 0);
}
else
{
float xStep = 1 / (xResolution - 1);
float zStep = 1 / (zResolution - 1);
float4 prevXVertexOriginal = v.vertex + float4(-xStep, 0, 0, 0);
float4 nextXVertexOriginal = v.vertex + float4(+xStep, 0, 0, 0);
float4 prevZVertexOriginal = v.vertex + float4(0, 0, -zStep, 0);
float4 nextZVertexOriginal = v.vertex + float4(0, 0, +zStep, 0);
float4 prevXVertex = GetUpdatedVertexRecomputeWorldPosition(prevXVertexOriginal, index);
float4 nextXVertex = GetUpdatedVertexRecomputeWorldPosition(nextXVertexOriginal, index);
float4 prevZVertex = GetUpdatedVertexRecomputeWorldPosition(prevZVertexOriginal, index);
float4 nextZVertex = GetUpdatedVertexRecomputeWorldPosition(nextZVertexOriginal, index);
//normal = normalize(cross(prevXVertex - nextXVertex, prevZVertex - nextZVertex));
normal = float3(0, 1, 0);
}
v.vertex = float4(currentXZVertex.xyz, v.vertex.b);
v.normal = normal;
VertexToFragment o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
//UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_CBUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_CBUFFER_END
void surf (Input IN, inout SurfaceOutputStandardSpecular o)
{
o.Albedo = _Color.rgb;
o.Alpha = _Color.a;
o.Smoothness = _Glossiness;
o.Specular = _Specular;
o.Emission = texCUBE(_Cube, IN.worldRefl).rgb * 0.5;
}
ENDCG
}
}
EDIT : If I comment the line where I update the vertex in the inout structure of the vertex shader, i.e : v.vertex = float4(currentXZVertex.xyz, v.vertex.b);
then my reflection problem is gone. But then I get a flat surface of course…
EDIT : Ok it seems like I fixed my weird reflection issues by modifying things rather randomly
I used this line : v.vertex = float4(currentXZVertex.xyz, 1);
instead of this line v.vertex = float4(currentXZVertex.xyz, v.vertex.b);
and it seems to work. Now all I have to do is fix my normals.