How to implement a simple height map to an Unity Shader - c#

Let me start off by saying I know very little about shader programming. A lot of what I have here is stitched together from online resources and existing assets. I just need to know how to correctly integrate a height map into a unity shader. It doesn't have to be more complex than the standard Unity shader's. I can't use the Standard shader because I need a shader that tiles together multiple textures, which is probably why I haven't found a solution to this problem yet.
I've mixed and moved around the code, deleted some variables, renamed some variables, and looked online for anyone who had a similar problem.
Shader "Unlit/TRUE_EARTH"
{
Properties
{
_TexA1 ("Tex A1", 2D) = "white" {}
_TexA2 ("Tex A2", 2D) = "white" {}
_TexB1 ("Tex B1", 2D) = "white" {}
_TexB2 ("Tex B2", 2D) = "white" {}
_TexC1 ("Tex C1", 2D) = "white" {}
_TexC2 ("Tex C2", 2D) = "white" {}
_TexD1 ("Tex D1", 2D) = "white" {}
_TexD2 ("Tex D2", 2D) = "white" {}
_BumpScale("Scale", Float) = 1.0
[Normal] _BumpMap("Normal Map", 2D) = "bump" {}
_Height("Height Scale", Range(0.005, 0.08)) = 0.02
_HeightMap("Height Map", 2D) = "black" {}
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
_OcclusionMap("Occlusion", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
Lighting Off
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
sampler2D _TexA1;
sampler2D _TexA2;
sampler2D _TexB1;
sampler2D _TexB2;
sampler2D _TexC1;
sampler2D _TexC2;
sampler2D _TexD1;
sampler2D _TexD2;
sampler2D _NormalMap;
sampler2D _HeightMap;
half _BumpAmount;
half _Height;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
half3 normal: TEXCOORD1;
#if WPM_BUMPMAP_ENABLED
half3 tspace0 : TEXCOORD2; // tangent.x, bitangent.x, normal.x
half3 tspace1 : TEXCOORD3; // tangent.y, bitangent.y, normal.y
half3 tspace2 : TEXCOORD4; // tangent.z, bitangent.z, normal.z
#endif
};
v2f vert (float4 vertex : POSITION, half3 normal : NORMAL, half4 tangent : TANGENT, float2 uv : TEXCOORD5, appdata_full v) {
v2f o;
float4 heightMap = tex2Dlod(_HeightMap, float4(v.texcoord.xy, 0, 0));
vertex.z += heightMap.b * _Height;
o.pos = UnityObjectToClipPos (vertex);
o.uv = uv;
half3 wNormal = UnityObjectToWorldNormal(normal);
o.normal = wNormal;
#if WPM_BUMPMAP_ENABLED
half3 wTangent = UnityObjectToWorldDir(tangent.xyz);
half tangentSign = tangent.w * unity_WorldTransformParams.w;
half3 wBitangent = cross(wNormal, wTangent) * tangentSign;
//output the tangent space matrix
o.tspace0 = half3(wTangent.x, wBitangent.x, wNormal.x);
o.tspace1 = half3(wTangent.y, wBitangent.y, wNormal.y);
o.tspace2 = half3(wTangent.z, wBitangent.z, wNormal.z);
#endif
return o;
}
half4 frag (v2f i) : SV_Target
{
// compute Earth pixel color
half4 color;
// compute Earth pixel color
if (i.uv.x<0.25)
{
if (i.uv.y>0.4999)
{
color = tex2Dlod(_TexA1, float4(i.uv.x * 4.0, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexA2, float4(i.uv.x * 4.0, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 0.5)
{
if (i.uv.y>0.4999)
{
color = tex2Dlod(_TexB1, float4((i.uv.x - 0.25) * 4.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexB2, float4((i.uv.x - 0.25) * 4.0f, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 0.75)
{
if (i.uv.y>0.4999)
{
color = tex2Dlod(_TexC1, float4((i.uv.x - 0.50) * 4.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexC2, float4((i.uv.x - 0.50) * 4.0f, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 1.01)
{
if (i.uv.y>0.4999)
{
color = tex2Dlod(_TexD1, float4((i.uv.x - 0.75) * 4.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexD2, float4((i.uv.x - 0.75) * 4.0f, i.uv.y * 2.0, 0, 0));
}
}
// sphere normal (without bump-map)
half3 snormal = normalize(i.normal);
// transform normal from tangent to world space
#if WPM_BUMPMAP_ENABLED
half3 tnormal = UnpackNormal(tex2D(_NormalMap, i.uv));
half3 worldNormal;
worldNormal.x = dot(i.tspace0, tnormal);
worldNormal.y = dot(i.tspace1, tnormal);
worldNormal.z = dot(i.tspace2, tnormal);
half3 normal = normalize(lerp(snormal, worldNormal, _BumpAmount));
#else
half3 normal = snormal;
#endif
return color;
}
ENDCG
}
}
}
The texture comes out fine, but there is no semblance of heightmapping. It's all flat.

There were 3 parts that needed to change.
Make sure your properties match up with your variables:
_Height("Height Scale", Range(0.005, 0.08)) = 0.02
_HeightMap("Height Map", 2D) = "black" {}
....
sampler2D _HeightMap;
half _Height;
Make modifications to the vertex before it gets stored in o
Modify the y component of the vertex instead of the z:
float4 heightMap = tex2Dlod(_HeightMap, float4(v.texcoord.xy, 0, 0));
vertex.y += heightMap.b * _Height;
o.pos = UnityObjectToClipPos (vertex);

Related

Using custom shader results in black image

I use unity 2018.3.5f1. I would like to overlay a custom shader while rendering an image. Following is my onRenderImage Function.
void OnRenderImage(RenderTexture src, RenderTexture dest) {
// shaderMaterial renders the image with Barrel distortion and disparity effect
Graphics.Blit(camTextureHolder.mainTexture, nullRenderTexture, shaderMaterial);
// measure average frames per second
m_FpsAccumulator++;
if (Time.realtimeSinceStartup > m_FpsNextPeriod) {
m_CurrentFps = (int)(m_FpsAccumulator / fpsMeasurePeriod);
m_FpsAccumulator = 0;
m_FpsNextPeriod += fpsMeasurePeriod;
}
}
The issue is that the entire screen appears to be black while I'm trying to do so. May I know how do I fix this issue?
Update:
This is the code for the shader that I'm using
Shader "Custom/FakeAR"
{
Properties{
_MainTex("", 2D) = "white" {}
[HideInInspector]_FOV("FOV", Range(1, 2)) = 1.6
[HideInInspector]_Disparity("Disparity", Range(0, 0.3)) = 0.1
[HideInInspector]_Alpha("Alpha", Range(0, 2.0)) = 1.0
}
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
// Default Vertex Shader
v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord.xy);
return o;
}
// Parameters
sampler2D _MainTex;
float _FOV;
// Alpha is the ratio of pixel density: width to height
float _Alpha;
// Disparity is the portion to separate
// larger disparity cause closer stereovision
float _Disparity;
// Fragment Shader: Remap the texture coordinates to combine
// barrel distortion and disparity video display
fixed4 frag(v2f i) : COLOR {
float2 uv1, uv2, uv3;
float t1, t2;
float offset;
// uv1 is the remap of left and right screen to a full screen
uv1 = i.uv - 0.5;
uv1.x = uv1.x * 2 - 0.5 + sign(i.uv.x < 0.5);
t1 = sqrt(1.0 - uv1.x * uv1.x - uv1.y * uv1.y);
t2 = 1.0 / (t1 * tan(_FOV * 0.5));
// uv2 is the remap of side screen with barrel distortion
uv2 = uv1 * t2 + 0.5;
// black color for out-of-range pixels
if (uv2.x >= 1 || uv2.y >= 1 || uv2.x <= 0 || uv2.y <= 0) {
return fixed4(0, 0, 0, 1);
}
else {
offset = 0.5 - _Alpha * 0.5 + _Disparity * 0.5 - _Disparity * sign(i.uv.x < 0.5);
// uv3 is the remap of image texture
uv3 = uv2;
uv3.x = uv2.x * _Alpha + offset;
return tex2D(_MainTex, uv3);
}
}
ENDCG
}
}
FallBack "Diffuse"
}
Is it because of the shader?
Well I think it's working it's just that the shader has nothing to render meaning it goes for black. You might want the shader to use the excisting camera texture. So maybe this?
void OnRenderImage(RenderTexture src, RenderTexture dest) {
// shaderMaterial renders the image with Barrel distortion and disparity effect
Graphics.Blit(src, dst, shaderMaterial);
// measure average frames per second
m_FpsAccumulator++;
if (Time.realtimeSinceStartup > m_FpsNextPeriod) {
m_CurrentFps = (int)(m_FpsAccumulator / fpsMeasurePeriod);
m_FpsAccumulator = 0;
m_FpsNextPeriod += fpsMeasurePeriod;
}
}
Try making the shader really default and see if it renders something. So try a shader that looks like this:
Shader "Examples/ExampleDisplacement"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}

Having trouble projecting a ShadowMap on to a surface

So I am having trouble rendering a shadow map in a shader I'm kind of new to shader coding(roughly 3 months), I'll talk you through what I am doing(well what I think I am doing).
So to start off by creating a script(ShadowCopy.cs) which copies the shadow map then passes it to a global variable(_MyShadowMap). Now the shader(ShadowMapping.shader), then I create getShadowCoord which calculates the shadowMap then applies the getCascadeWeights() to the shadow Coordinates(for Optimal reasons).
Then I create computeCameraSpacePosFromDepthAndInvProjMat() which computes the camera space position based from depth and inverse projection matrix. Now the frag function which renders the pixels
making it visible in the Application, but overall its just Screen-Space-Shadows.
So the problem I am facing are the Projection Values which I honestly don't know how to fix. You can see the Problem in the picture.
enter image description here
The Material Settings for ShadowMapping.shader.
enter image description here
ShadowCopy.cs
using UnityEngine;
using UnityEngine.Rendering;
public class ShadowCopy : MonoBehaviour
{
public Light m_Light;
RenderTexture m_ShadowmapCopy;
public int TextureSize = 512;
void Start()
{
RenderTargetIdentifier shadowmap = BuiltinRenderTextureType.CurrentActive;
m_ShadowmapCopy = new RenderTexture(TextureSize, TextureSize, 16, RenderTextureFormat.ARGB32);
m_ShadowmapCopy.filterMode = FilterMode.Point;
CommandBuffer cb = new CommandBuffer();
cb.SetShadowSamplingMode(shadowmap, ShadowSamplingMode.RawDepth);
cb.Blit(shadowmap, new RenderTargetIdentifier(m_ShadowmapCopy));
cb.SetGlobalTexture("_MyShadowMap", shadowmap);
m_Light.AddCommandBuffer(LightEvent.AfterShadowMap, cb);
}
void OnGUI()
{
if (m_ShadowmapCopy != null)
{
GUI.DrawTextureWithTexCoords(new Rect(0, 20, 150, 150), m_ShadowmapCopy, new Rect(0, 0, 1, 1), false);
}
}
ShadowMapping.shader
Shader "Custom/ShadowMapping" {
Properties {
_Color("Main Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGBA)", 2D) = "white" {}
}
SubShader {
Pass {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
#include "AutoLight.cginc"
uniform float4 _Color;
uniform sampler2D _MyShadowMap;
//UNITY_DECLARE_SHADOWMAP(_MyShadowMap);
uniform sampler2D _MainTex;
float4 LowResDepth_TexelSize;
float4 _ShadowMapTexture_TexelSize;
#define SHADOWMAPSAMPLER_AND_TEXELSIZE_DEFINED
#define UNITY_USE_CASCADE_BLENDING 0
#define UNITY_CASCADE_BLEND_DISTANCE 0.1
struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
#ifdef UNITY_STEREO_INSTANCING_ENABLED
float3 ray0 : TEXCOORD1;
float3 ray1 : TEXCOORD2;
#else
float3 ray : TEXCOORD1;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float4 pos : SV_POSITION;
// xy uv / zw screenpos
float4 uv : TEXCOORD0;
// View space ray, for perspective case
float3 ray : TEXCOORD1;
// Orthographic view space positions (need xy as well for oblique matrices)
float3 orthoPosNear : TEXCOORD2;
float3 orthoPosFar : TEXCOORD3;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
float4 clipPos = UnityObjectToClipPos(v.vertex);
o.pos = clipPos;
o.uv.xy = v.texcoord;
o.uv.zw = ComputeNonStereoScreenPos(clipPos);
clipPos.y *= _ProjectionParams.x;
float3 orthoPosNear = mul(unity_CameraInvProjection, float4(clipPos.x,clipPos.y,-1,1)).xyz;
float3 orthoPosFar = mul(unity_CameraInvProjection, float4(clipPos.x,clipPos.y, 1,1)).xyz;
orthoPosNear.z *= -1;
orthoPosFar.z *= -1;
o.orthoPosNear = orthoPosNear;
o.orthoPosFar = orthoPosFar;
return o;
}
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
inline fixed4 getCascadeWeights(float3 wpos, float z)
{
fixed4 zNear = float4( z >= _LightSplitsNear );
fixed4 zFar = float4( z < _LightSplitsFar );
fixed4 weights = zNear * zFar;
return weights;
}
inline float4 getShadowCoord( float4 wpos, fixed4 cascadeWeights )
{
float3 sc0 = mul (unity_WorldToShadow[0], wpos).xyz;
float3 sc1 = mul (unity_WorldToShadow[1], wpos).xyz;
float3 sc2 = mul (unity_WorldToShadow[2], wpos).xyz;
float3 sc3 = mul (unity_WorldToShadow[3], wpos).xyz;
float4 shadowMapCoordinate = float4(sc0 * cascadeWeights[0] + sc1 * cascadeWeights[1] + sc2 * cascadeWeights[2] + sc3 * cascadeWeights[3], 1);
#if defined(UNITY_REVERSED_Z)
float noCascadeWeights = 1 - dot(cascadeWeights, float4(1, 1, 1, 1));
shadowMapCoordinate.z += noCascadeWeights;
#endif
return shadowMapCoordinate;
}
inline float3 computeCameraSpacePosFromDepthAndInvProjMat(v2f i)
{
float zdepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv.xy);
#if defined(UNITY_REVERSED_Z)
zdepth = 1 - zdepth;
#endif
float4 clipPos = float4(i.uv.zw, zdepth, 1.0);
clipPos.xyz = 2.0f * clipPos.xyz - 1.0f;
float4 camPos = mul(unity_CameraInvProjection, clipPos);
camPos.xyz /= camPos.w;
camPos.z *= -1;
return camPos.xyz;
}
half4 frag(v2f i) : COLOR
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float3 vpos = computeCameraSpacePosFromDepthAndInvProjMat(i);
float4 wpos = mul (unity_CameraToWorld, float4(vpos,1));
fixed4 cascadeWeights = getCascadeWeights (wpos, vpos.z);
float4 shadowCoord = getShadowCoord(wpos, cascadeWeights);
float shadow = tex2D(_MyShadowMap, shadowCoord);
shadow = lerp(_LightShadowData.r, 1.0, shadow);
fixed4 res = shadow;
return shadow * tex2D(_MainTex, i.uv) * _Color;
}
ENDCG
}
}
}
A few items that jump out at me:
Change: cb.SetGlobalTexture("_MyShadowMap", shadowmap); to cb.SetGlobalTexture("_MyShadowMap", m_ShadowmapCopy);
Change: uniform sampler2D _MyShadowMap; to UNITY_DECLARE_SHADOWMAP(_MyShadowMap);
Change float shadow = tex2D(_MyShadowMap, shadowCoord); to float shadow = UNITY_SAMPLE_SHADOW(_MyShadowMap, shadowCoord);

Why i don't see the Shield around my spaceship?

I'm using unity version 5.6.1f1 Personal.
I'm trying to use this shader code and csharp script from wiki page:
Shield
In the editor i did: Assets > Create > Shader > Standrad Surface Shader
The double click on the created shader opened it in visual studio and added this code:
Shader "Custom/NewSurfaceShader" {
Properties
{
_Color("_Color", Color) = (0.0,1.0,0.0,1.0)
_Inside("_Inside", Range(0.0,2.0)) = 0.0
_Rim("_Rim", Range(0.0,1.0)) = 1.2
_Texture("_Texture", 2D) = "white" {}
_Speed("_Speed", Range(0.5,5.0)) = 0.5
_Tile("_Tile", Range(1.0,10.0)) = 5.0
_Strength("_Strength", Range(0.0,5.0)) = 1.5
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Cull Back
ZWrite On
ZTest LEqual
CGPROGRAM
#pragma surface surf BlinnPhongEditor alpha vertex:vert
//#pragma target 3.0
fixed4 _Color;
sampler2D _CameraDepthTexture;
fixed _Inside;
fixed _Rim;
sampler2D _Texture;
fixed _Speed;
fixed _Tile;
fixed _Strength;
struct EditorSurfaceOutput
{
half3 Albedo;
half3 Normal;
half3 Emission;
half3 Gloss;
half Specular;
half Alpha;
};
inline half4 LightingBlinnPhongEditor_PrePass(EditorSurfaceOutput s, half4 light)
{
half3 spec = light.a * s.Gloss;
half4 c;
c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
c.a = s.Alpha + Luminance(spec);
return c;
}
inline half4 LightingBlinnPhongEditor(EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
viewDir = normalize(viewDir);
half3 h = normalize(lightDir + viewDir);
half diff = max(0, dot(s.Normal, lightDir));
float nh = max(0, dot(s.Normal, h));
float3 spec = pow(nh, s.Specular*128.0) * s.Gloss;
half4 res;
res.rgb = _LightColor0.rgb * (diff * atten * 2.0);
res.w = spec * Luminance(_LightColor0.rgb);
return LightingBlinnPhongEditor_PrePass(s, res);
}
struct Input
{
float4 screenPos;
float3 viewDir;
float2 uv_Texture;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input,o);
}
void surf(Input IN, inout EditorSurfaceOutput o)
{
o.Albedo = fixed3(0.0,0.0,0.0);
o.Normal = fixed3(0.0,0.0,1.0);
o.Emission = 0.0;
o.Gloss = 0.0;
o.Specular = 0.0;
o.Alpha = 1.0;
float4 ScreenDepthDiff0 = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)).r) - IN.screenPos.z;
float4 Saturate0 = fixed4(0.3,0.3,0.3,1.0);//
float4 Fresnel0_1_NoInput = fixed4(0,0,1,1);
float dNorm = 1.0 - dot(normalize(float4(IN.viewDir, 1.0).xyz), normalize(Fresnel0_1_NoInput.xyz));
float4 Fresnel0 = float4(dNorm,dNorm,dNorm,dNorm);
float4 Step0 = step(Fresnel0,float4(1.0, 1.0, 1.0, 1.0));
float4 Clamp0 = clamp(Step0,_Inside.xxxx,float4(1.0, 1.0, 1.0, 1.0));
float4 Pow0 = pow(Fresnel0,(_Rim).xxxx);
float4 Multiply5 = _Time * _Speed.xxxx;
float4 UV_Pan0 = float4((IN.uv_Texture.xyxy).x,(IN.uv_Texture.xyxy).y + Multiply5.x,(IN.uv_Texture.xyxy).z,(IN.uv_Texture.xyxy).w);
float4 Multiply1 = UV_Pan0 * _Tile.xxxx;
float4 Tex2D0 = tex2D(_Texture,Multiply1.xy);
float4 Multiply2 = Tex2D0 * _Strength.xxxx;
float4 Multiply0 = Pow0 * Multiply2;
float4 Multiply3 = Clamp0 * Multiply0;
float4 Multiply4 = Saturate0 * Multiply3;
o.Emission = Multiply3.xyz * _Color.rgb;
o.Alpha = Multiply3.w * _Color.a;
}
ENDCG
}
Fallback "Diffuse"
}
Then created a csharp script file:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShieldUvAnimation : MonoBehaviour {
public GameObject iShield;
public float iSpeed;
private Material mMaterial;
private float mTime;
// Use this for initialization
void Start()
{
mMaterial = iShield.GetComponent<Renderer>().material;
mTime = 0.0f;
}
// Update is called once per frame
void Update()
{
mTime += Time.deltaTime * iSpeed;
mMaterial.SetFloat("_Offset", Mathf.Repeat(mTime, 1.0f));
}
}
Then i created a material new material and dragged the shader to the material.
Then created a new empty GameObject.
Then attached the csharp script to the new empty GameObject.
Now the first problem i had is that i could not drag the new material to the empty GameObject. So i changed the csharp script i changed the line:
private Material mMaterial;
To be public
public Material mMaterial;
And removed the line in the Start:
mMaterial = iShield.GetComponent<Renderer>().material;
Then i dragged the new material to the public mMaterial.
Last i dragged my spaceship object to the iShield.
I changed the iSpeed to 1.
Running the game i'm not getting any errors or exceptions but i don't see any shield.
Your shader doesn't have property "_Offset".
Script "ShieldUvAnimation" will work with "ShaderLab - ForceField.shader".
Your link shield

Unable to animate or change color in custom shader in Unity?

Ok, I am new to shaders but I cant find a way to animate or even change a color value in my custom shader that is attached to a material.
Im using the material for my skybox and it is a gradient w/ 3 properties declared like this:
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
}
I looked at Unitys docs and and am trying to change the bottom color (eventually lerping so it is animated, although I don't know how to do this) like this:
skybox.SetColor ("_Color3", afterColor);
where the material was a public var. I have tried writing "Bottom Color" as the parameter as well, but when it runs nothing happens. I don't understand why.
How can I change the color in my custom shader? Moreover, how can I animate this change once I do?
EDIT: #Programmer The shader is a .shader file attached to a material object. Shader code ( I did not write it as Im new to shaders):
Shader "Custom/Horizontal Skybox"
{
Properties
{
_Color1 ("Top Color", Color) = (1, 1, 1, 0)
_Color2 ("Horizon Color", Color) = (1, 1, 1, 0)
_Color3 ("Bottom Color", Color) = (1, 1, 1, 0)
_Exponent1 ("Exponent Factor for Top Half", Float) = 1.0
_Exponent2 ("Exponent Factor for Bottom Half", Float) = 1.0
_Intensity ("Intensity Amplifier", Float) = 1.0
}
CGINCLUDE
#include "UnityCG.cginc"
struct appdata
{
float4 position : POSITION;
float3 texcoord : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
half4 _Color1;
half4 _Color2;
half4 _Color3;
half _Intensity;
half _Exponent1;
half _Exponent2;
v2f vert (appdata v)
{
v2f o;
o.position = mul (UNITY_MATRIX_MVP, v.position);
o.texcoord = v.texcoord;
return o;
}
half4 frag (v2f i) : COLOR
{
float p = normalize (i.texcoord).y;
float p1 = 1.0f - pow (min (1.0f, 1.0f - p), _Exponent1);
float p3 = 1.0f - pow (min (1.0f, 1.0f + p), _Exponent2);
float p2 = 1.0f - p1 - p3;
return (_Color1 * p1 + _Color2 * p2 + _Color3 * p3) * _Intensity;
}
ENDCG
SubShader
{
Tags { "RenderType"="Background" "Queue"="Background" }
Pass
{
ZWrite Off
Cull Off
Fog { Mode Off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
Trying to change this with public variables like this from a script within an empty:
public Material skybox;
public Color afterColor;
void Start () {
chars = GameObject.FindGameObjectsWithTag("BeginChar");
balls = GameObject.FindGameObjectsWithTag ("Ball");
StartCoroutine (waitForTheRun ());
skybox.SetColor ("_Color3", afterColor); //here
}
Don't see anything wrong with your code.
Things to try:
1.You must plug your skybox3 material to the skybox slot. After that you can change the Material. This ensures that you are modifying the right material.
2.Direct SkyBox change
You don't have to do #1 with this. It will modify whatever material is attached to the SkyBox.
public Material skybox;
public Color afterColor = Color.white;
// Use this for initialization
public void Start()
{
skybox = RenderSettings.skybox;
skybox.SetColor("_Color3", afterColor); //here
}

Problems with my unity shader

I have began to create some shaders for my university group project however I have ran into a bit of a snag with my water shader. I am trying to create one which utilises two overlapping normal maps.
Whilst everything looks okay in the editor, when I then publish to the webplayer, the scene looks like its unlit.
Heres my code for the shader:
//
// Filename : WaterShader.shader
// Version : 2.0
// Date : 1st March 2014
//
Shader "Flight/WaterShader/2.0"
{
// Set up variables so we can access them in inspector mode
Properties
{
// Variable to control the colour tint
_Color ("Base Color", Color) = (1, 1, 1, 1)
// Variables for specular
_SpecularColor ("Specular Color", Color) = (1, 1, 1, 1)
_SpecularAmount ("Shininess", Float) = 10
// Variable for setting the base texture
_MainTex ("Water Texture", 2D) = "white" { }
// Variables to set the normal map 1
_BumpMapA ("Normal Map", 2D) = "bump" { }
_BumpDepthA ("Depth", Range(0.25, 10.0)) = 1
// Variables to set the normal map 2
_BumpMapB ("Normal Map", 2D) = "bump" { }
_BumpDepthB ("Depth", Range(0.25, 10.0)) = 1
}
SubShader
{
pass
{
Tags { "RenderType" = "Opaque" }
Lighting On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers flash
// Variables
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMapA;
float4 _BumpMapA_ST;
float _BumpDepthA;
sampler2D _BumpMapB;
float4 _BumpMapB_ST;
float _BumpDepthB;
float4 _Color;
float4 _SpecularColor;
float _SpecularAmount;
float4 _LightColor0;
struct vertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
};
struct vertexOutput
{
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float4 posWorld : TEXCOORD1;
float3 normalWorld : TEXCOORD2;
float3 tangentWorld : TEXCOORD3;
float3 binormalWorld : TEXCOORD4;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.tex = input.texcoord;
output.posWorld = mul(_Object2World, input.vertex);
output.normalWorld = normalize( mul( float4( input.normal, 0.0f ), _World2Object ).xyz );
output.tangentWorld = normalize( mul( _Object2World, input.tangent ).xyz );
output.binormalWorld = normalize( cross( output.normalWorld, output.tangentWorld) * input.tangent.w );
return output;
}
float4 frag(vertexOutput input) : COLOR
{
// Set up variables
float3 viewDirection;
float3 lightDirection;
float3 normalDirection;
float lightIntensity;
float4 normalColorA;
float4 normalColorB;
float4 normalColor;
float3 normalLocalA;
float3 normalLocalB;
float3 normalLocal;
float3x3 normalWorld;
float4 textureColor;
float3 diffuseColor;
float3 specularColor;
float3 lightColor;
float4 finalColor;
// Begin calculations
// Calculate the angle we are looking at the pixel
viewDirection = normalize(_WorldSpaceCameraPos.xyz - input.posWorld.xyz );
if(_WorldSpaceLightPos0.w == 0.0)
{
lightIntensity = 1.0;
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else
{
float3 fragmentToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(fragmentToLightSource);
lightIntensity = 1.0 / distance;
lightDirection = normalize(fragmentToLightSource);
}
// Sample the textures
textureColor = tex2D(_MainTex, input.tex.xy * _MainTex_ST.xy + _MainTex_ST.zw);
normalColorA = tex2D(_BumpMapA, input.tex.xy * _BumpMapA_ST.xy + _BumpMapA_ST.zw);
normalColorB = tex2D(_BumpMapB, input.tex.xy * _BumpMapB_ST.xy + _BumpMapB_ST.zw);
// Expand the normals and set the intensity of the normal map
normalLocalA = float3(2.0 * normalColorA.ag - float2(1.0, 1.0), 0.0);
normalLocalA.z = _BumpDepthA;
normalLocalB = float3(2.0 * normalColorB.ag - float2(1.0, 1.0), 0.0);
normalLocalB.z = _BumpDepthB;
// Combine the two normals
normalLocal = normalize(normalLocalA + normalLocalB);
// Calculate the normal in the world
normalWorld = float3x3( input.tangentWorld, input.binormalWorld, input.normalWorld );
normalDirection = normalize( mul( normalLocal, normalWorld ) );
// Calculate lighting
diffuseColor = lightIntensity * _LightColor0.xyz * saturate( dot(normalDirection, lightDirection) );
specularColor = diffuseColor * _SpecularColor.xyz * pow( saturate( dot( reflect(-lightDirection, normalDirection), viewDirection) ), _SpecularAmount );
// Combine lighting
lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseColor + specularColor;
// Apply lighting to the texture color
textureColor = float4( textureColor.xyz * lightColor * _Color.xyz, 1.0);
return textureColor;
}
ENDCG
}
}
FallBack "Specular"
}
In the editor it looks like this:
Where as in the webplayer it looks like this:
Anyone able to help me see where I have gone wrong? :)
You need a separate pass of pixel light in the scene for the web player. Replace your current SubShader Parameters with
SubShader
{
Tags {"RenderType" = "Opaque"}
Pass
{
Tags {"LightMode" = "ForwardAdd"}
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers flash

Categories

Resources