- Home /
Fragment Shader pixel gets overwritten
UPDATE: Ive figured out that i need to have a default-material object rendered to the main camera. Whilst this is not fixed i have working reflections now. What i do is i spawn a Primitive Cube with 0 in scale. I then move the cube so it is allways in center focus of the main camera. I do beliave this to be a bug. Because i see no reason for this to occure.
UPDATE 2: Now i need to use Nature/Terrain-Diffuse. Im not shure what i changed but since this shouldnt happen in the first place im not surprised it changed.
As you se enabeling bigger objects like theese cubes cause the reflection to appear even when the smaller ones (i spawn in) are still seen by the camera. Walking away from the larger objects makes the reflection dissapear again.
I am at lost for words at to what can cause this.
I am rendering my reflection camera to color and depth target buffers set as global shader textures:
Camera this_camera = GetComponent<Camera>();
RenderTexture render_texture_target = new RenderTexture(400, 225, 0, RenderTextureFormat.Default);
render_texture_target.filterMode = FilterMode.Point;
RenderTexture render_texture_target_depth = new RenderTexture(400, 225, 24, RenderTextureFormat.Depth);
render_texture_target_depth.filterMode = FilterMode.Point;
Shader.SetGlobalTexture("_WaterReflectionTexture", render_texture_target);
Shader.SetGlobalTexture("_WaterReflectionTextureDepth", render_texture_target_depth);
Camera reflection_camera = NormalsReplacementShader.CopyCamera(this_camera, transform.parent, "ReflectionCamera", 1);
reflection_camera.SetTargetBuffers(render_texture_target.colorBuffer, render_texture_target_depth.depthBuffer);
And grab them in the shader sampeling the texture like this:
// Relfection uv.
float2 screen_uv_reflection = float2(screen_uv.x, 1-screen_uv.y) + distort_value;
//return float4(screen_uv_reflection,1,1);
// Sample reflection camera color and depth value.
float4 waterReflection = float4(tex2D(_WaterReflectionTexture, screen_uv_reflection).xyz, _WaterReflectionAmount);
float depth_reflection_value = tex2D(_WaterReflectionTextureDepth, screen_uv_reflection).x;
// if current pixel is under water
if (depthDifference > 0)
{
float4 under_color = tex2D(_GrabTexture, screen_uv_distort);
waterColor = alphaBlend(waterColor, under_color);
}
// If the camera saw somthing.
if (depth_reflection_value != 0)
{
waterReflection = alphaBlend(_WaterReflectionColor, waterReflection);
waterColor = alphaBlend(waterReflection, waterColor);
}
return alphaBlend(surfaceNoiseColor, waterColor);
Returning waterReflection nomatter the depth shows correct results: Returning depth_reflection_value shows correct results:
So blending of theese does not work in my code? How should i blend them so that waterReflection only gets drawn when depth_reflection_value != 0?
Answer by abbsimoga · Sep 04, 2021 at 11:23 AM
With further testing i noticed that previous returns gets overwritten. WHY?
if (depth_reflection_value != 0)
{
return float4(1,0,0,1);
}
return 1;
The reflection in red shows that this if statement is sufficient for showing where reflections should be placed.
Yet if i were to return my water color instead of white the if statement gets overwritten:
if (depth_reflection_value != 0)
{
return float4(1,0,0,1);
}
return waterColor;
This is all of my shader. Its in a alpha stage rn so might be difficult to follow.
Shader "Custom/Water Shader"
{
Properties
{
// What color the water will sample when the surface below is shallow.
_DepthGradientShallow("Depth Gradient Shallow", Color) = (0.325, 0.807, 0.971, 0.725)
// What color the water will sample when the surface below is at its deepest.
_DepthGradientDeep("Depth Gradient Deep", Color) = (0.086, 0.407, 1, 0.749)
// Maximum distance the surface below the water will affect the color gradient.
_DepthMaxDistance("Depth Maximum Distance", Float) = 1
// Color to render the foam generated by objects intersecting the surface.
_FoamColor("Foam Color", Color) = (1,1,1,1)
// Noise texture used to generate waves.
_SurfaceNoise("Surface Noise", 2D) = "white" {}
// Speed, in UVs per second the noise will scroll. Only the xy components are used.
_SurfaceNoiseScroll("Surface Noise Scroll Amount", Vector) = (0.03, 0.03, 0, 0)
// Values in the noise texture above this cutoff are rendered on the surface.
_SurfaceNoiseCutoff("Surface Noise Cutoff", Range(0, 1)) = 0.777
// Red and green channels of this texture are used to offset the noise texture to create distortion in the waves.
_SurfaceDistortion("Surface Distortion", 2D) = "white" {}
// Multiplies the distortion by this value.
_SurfaceDistortionAmount("Surface Distortion Amount", Range(0, 1)) = 0.27
// Control the distance that surfaces below the water will contribute to foam being rendered.
_FoamMaxDistance("Foam Maximum Distance", Float) = 0.4
_FoamMinDistance("Foam Minimum Distance", Float) = 0.04
// Alpha value of water reflection.
_WaterReflectionAmount("Water Reflection Amount", Range(0, 1)) = 0.35
// Color blend of water reflection. // NOT SHURE IF I SHOULD USE
_WaterReflectionColor("Water Reflection Color", Color) = (1, 1, 1, 1)
// Speed, in UVs per second the noise will scroll. Only the xy components are used.
_UnderWaterDistortSpeed("Under Water Noise Speed", Vector) = (0.03, 0.03, 0, 0)
// Speed, in UVs per second the noise will scroll. Only the xy components are used.
_UnderWaterDistortAmount("Under Water Noise Amount", Vector) = (0.03, 0.03, 0, 0)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
}
GrabPass { "_GrabTexture" }
Pass
{
// Transparent "normal" blending.
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
CGPROGRAM
//#define SMOOTHSTEP_AA 0.01
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// Blends two colors using the same algorithm that our shader is using
// to blend with the screen. This is usually called "normal blending",
// and is similar to how software like Photoshop blends two layers.
float4 alphaBlend(float4 top, float4 bottom)
{
float3 color = (top.rgb * top.a) + (bottom.rgb * (1 - top.a));
float alpha = top.a + bottom.a * (1 - top.a);
return float4(color, alpha);
}
struct appdata
{
float4 vertex : POSITION;
float4 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 noiseUV : TEXCOORD0;
float2 distortUV : TEXCOORD1;
float4 screenPosition : TEXCOORD2;
float3 viewNormal : NORMAL;
};
sampler2D _SurfaceNoise;
float4 _SurfaceNoise_ST;
sampler2D _SurfaceDistortion;
float4 _SurfaceDistortion_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.screenPosition = ComputeScreenPos(o.vertex);
o.distortUV = TRANSFORM_TEX(v.uv, _SurfaceDistortion);
o.noiseUV = TRANSFORM_TEX(v.uv, _SurfaceNoise);
o.viewNormal = COMPUTE_VIEW_NORMAL;
return o;
}
float4 _DepthGradientShallow;
float4 _DepthGradientDeep;
float4 _FoamColor;
float _DepthMaxDistance;
float _FoamMaxDistance;
float _FoamMinDistance;
float _SurfaceNoiseCutoff;
float _SurfaceDistortionAmount;
float2 _SurfaceNoiseScroll;
sampler2D _CameraDepthTexture;
sampler2D _CameraNormalsTexture;
sampler2D _GrabTexture;
float _WaterReflectionAmount;
float4 _WaterReflectionColor;
float2 _UnderWaterDistortSpeed;
float2 _UnderWaterDistortAmount;
uniform float4 _CameraOffset;
sampler2D _WaterReflectionTexture;
sampler2D _WaterReflectionTextureDepth;
float4 frag (v2f i) : SV_Target
{
// Retrieve the current linear depth value of the surface behind the pixel we are currently rendering.
float rawDepth = tex2D(_CameraDepthTexture, i.screenPosition).r;
// Flip orthographic projection.
float orthoLinearDepth = _ProjectionParams.x > 0 ? rawDepth : 1 - rawDepth;
// Recast surface 01-linear depth value to unity units.
float orthoEyeDepth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoLinearDepth);
// Retrieve depth value to shader plane.
float orthoPlainLinearDepth = 1 - i.screenPosition.z;
// Recast to unity units.
float orthoPlainDepth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoPlainLinearDepth);
// Water depth for current pixel in unity units.
float depthDifference = orthoEyeDepth - orthoPlainDepth;
// Calculate the color of the water based on the depth using our two gradient colors.
float waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
float4 waterColor = lerp(_DepthGradientShallow, _DepthGradientDeep, waterDepthDifference01);
// Retrieve the view-space normal of the surface behind the
// pixel we are currently rendering.
float3 existingNormal = tex2Dproj(_CameraNormalsTexture, UNITY_PROJ_COORD(i.screenPosition));
// Modulate the amount of foam we display based on the difference
// between the normals of our water surface and the object behind it.
// Larger differences allow for extra foam to attempt to keep the overall
// amount consistent.
float3 normalDot = saturate(dot(existingNormal, i.viewNormal));
float foamDistance = lerp(_FoamMaxDistance, _FoamMinDistance, normalDot);
float foamDepthDifference01 = saturate(depthDifference / foamDistance);
float surfaceNoiseCutoff = foamDepthDifference01 * _SurfaceNoiseCutoff;
float2 distortTex = (tex2D(_SurfaceDistortion, i.distortUV).xy * 2 - 1);
float2 distortSample = distortTex * _SurfaceDistortionAmount;
// Distort the noise UV based off the RG channels (using xy here) of the distortion texture.
// Also offset it by time, scaled by the scroll speed.
float2 noiseUV = float2((i.noiseUV.x + _Time.y * _SurfaceNoiseScroll.x) + distortSample.x,
(i.noiseUV.y + _Time.y * _SurfaceNoiseScroll.y) + distortSample.y);
float surfaceNoiseSample = tex2D(_SurfaceNoise, noiseUV).r;
// Use smoothstep to ensure we get some anti-aliasing in the transition from foam to surface.
// Uncomment the line below to see how it looks without AA.
float surfaceNoise = surfaceNoiseSample > surfaceNoiseCutoff ? 1 : 0;
// float surfaceNoise = smoothstep(surfaceNoiseCutoff - SMOOTHSTEP_AA, surfaceNoiseCutoff + SMOOTHSTEP_AA, surfaceNoiseSample);
float4 surfaceNoiseColor = _FoamColor;
surfaceNoiseColor.a = surfaceNoise;
// Get pixel perfect distort value for water.
float2 under_water_distort_time = _Time.yy * _UnderWaterDistortSpeed.xy;
float2 under_water_distort = (tex2D(_SurfaceDistortion, i.distortUV + under_water_distort_time).xy * 2 - 1) * _UnderWaterDistortAmount.xy;
float2 px = float2(384, 216);
float2 distort_value = round(px * under_water_distort) / px;
// Screen uv coords for under water pixel.
float2 screen_uv = i.screenPosition.xy;
float2 screen_uv_distort = screen_uv + distort_value;
// Get raw depth for new uv.
rawDepth = tex2D(_CameraDepthTexture, screen_uv_distort).r;
// Flip orthographic projection.
orthoLinearDepth = _ProjectionParams.x > 0 ? rawDepth : 1 - rawDepth;
// Recast surface 01-linear depth value to unity units.
orthoEyeDepth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoLinearDepth);
// Retrieve depth value to shader plane.
orthoPlainLinearDepth = 1 - i.screenPosition.z;
// Recast to unity units.
orthoPlainDepth = lerp(_ProjectionParams.y, _ProjectionParams.z, orthoPlainLinearDepth);
// Water depth for current pixel in unity units.
depthDifference = orthoEyeDepth - orthoPlainDepth;
// If we are under water.
//if (depthDifference > 0)
//{
// float4 under_color = tex2D(_GrabTexture, screen_uv_distort);
// waterColor = alphaBlend(waterColor, under_color);
//}
// Relfection uv.
float2 screen_uv_reflection = float2(screen_uv.x, 1-screen_uv.y) + distort_value;
// Sample reflection camera color and depth value.
float4 waterReflection = float4(tex2D(_WaterReflectionTexture, screen_uv_reflection).xyz, _WaterReflectionAmount);
float depth_reflection_value = tex2D(_WaterReflectionTextureDepth, screen_uv_reflection).x;
if (depthDifference > 0)
{
float4 under_color = tex2D(_GrabTexture, screen_uv_distort);
waterColor = alphaBlend(waterColor, under_color);
}
// If the camera saw somthing.
if (depth_reflection_value != 0)
{
waterReflection = alphaBlend(_WaterReflectionColor, waterReflection);
waterColor = alphaBlend(waterReflection, waterColor);
}
return alphaBlend(surfaceNoiseColor, waterColor);
}
ENDCG
}
}
}
I thought it might have been culling everything but it shows in camera preview that everything gets rendered. Sooooo..... WHY does it only occasionally render???
I am also crashing randomly am i using SetTargetBuffers wrong?
Your answer
Follow this Question
Related Questions
Reflective sphere for HDRI 0 Answers
Bullet keeps rotating after ricochet off of wall 0 Answers
How can I render light reflected off moving objects? 0 Answers
Depth buffer and deferred rendering 0 Answers
Use camera depth texture to find distance from camera 0 Answers