Question by
EMClick · Feb 09, 2016 at 02:15 PM ·
textureshadersskyboxuv mappingvertex shader
How add texture to skybox procedural shader
hi guys! i'm modifing the Skybox Procedural Shader to allow nithg sky, and i have the following code at this time and work fine, but MY PROBLEM: is that i don't know how calculate the UV for de tex2D parameter, could someone explain me how to do this?
Shader "Skybox/EMSDK/Procedural" {
Properties {
_SunSize ("Sun Size", Range(0,1)) = 0.04
_SunBrightness("Sun Brightness", Float) = 20
_MoonColor("Moon Color", Color) = (1,1,1,1)
_MoonTex("Moon Texture", 2D) = "white" {}
_MoonSize("Moon Size", Range(0,1)) = 0.06
_MoonBrightness("Moon Brightness", Float) = 10
_MoonPos("Moon Position", Vector) = (0.5,0.5,1)
_AtmosphereThickness("Atmoshpere Thickness", Range(0,5)) = 1.0
_SkyTint("Sky Tint", Color) = (.5, .5, .5, 1)
_GroundColor("Ground", Color) = (.369, .349, .341, 1)
_kDefaultScatteringWavelength("Default Scattering Wavelength", Color) = (.65, .57, .475)
_kVariableRangeForScatteringWavelength("Variable Range For ScatteringWavelength", Color) = (.15, .15, .15)
_Exposure("Exposure", Range(0, 8)) = 1.3
_hour("Hour", Range(0,23.99)) = 0
}
SubShader{
Tags { "Queue" = "Background" "RenderType" = "Background" "PreviewType" = "Skybox" }
Cull Off ZWrite Off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#pragma multi_compile __ UNITY_COLORSPACE_GAMMA
#pragma multi_compile _SUNDISK_NONE _SUNDISK_SIMPLE _SUNDISK_HIGH_QUALITY
uniform half _hour;
uniform half _Exposure; // HDR exposure
uniform half3 _GroundColor;
uniform half _SunSize;
uniform fixed4 _MoonColor;
sampler2D _MoonTex;
uniform float4 _MoonTex_ST;
uniform half _SunBrightness;
uniform half _MoonBrightness;
uniform half _MoonSize;
uniform half3 _SkyTint;
uniform fixed4 _kDefaultScatteringWavelength;
uniform fixed4 _kVariableRangeForScatteringWavelength;
uniform half4 _MoonPos;
uniform half _AtmosphereThickness;
#if defined(UNITY_COLORSPACE_GAMMA)
#define GAMMA 2
#define COLOR_2_GAMMA(color) color
#define COLOR_2_LINEAR(color) color*color
#define LINEAR_2_OUTPUT(color) sqrt(color)
#else
#define GAMMA 2.2
// HACK: to get gfx-tests in Gamma mode to agree until UNITY_ACTIVE_COLORSPACE_IS_GAMMA is working properly
#define COLOR_2_GAMMA(color) ((unity_ColorSpaceDouble.r>2.0) ? pow(color,1.0/GAMMA) : color)
#define COLOR_2_LINEAR(color) color
#define LINEAR_2_LINEAR(color) color
#endif
// RGB wavelengths
// .35 (.62=158), .43 (.68=174), .525 (.75=190)
static float3 kDefaultScatteringWavelength = _kDefaultScatteringWavelength;
static float3 kVariableRangeForScatteringWavelength = _kVariableRangeForScatteringWavelength;
#define OUTER_RADIUS 1.025
static const float kOuterRadius = OUTER_RADIUS;
static const float kOuterRadius2 = OUTER_RADIUS*OUTER_RADIUS;
static const float kInnerRadius = 1.0;
static const float kInnerRadius2 = 1.0;
static const float kCameraHeight = 0.0001;
#define kRAYLEIGH (lerp(0, 0.0025, pow(_AtmosphereThickness,2.5))) // Rayleigh constant
#define kMOONRAYLEIGH (lerp(0, 0.0001, pow(_AtmosphereThickness,2.5))) // Rayleigh constant
#define kMIE 0.0010 // Mie constant
#define kMAX_SCATTER 50.0 // Maximum scattering value, to prevent math overflows on Adrenos
static half kSunScale = 400.0 * _SunBrightness;
static half kMoonScale = 400.0 * _MoonBrightness;
static float kKmESun = kMIE * _SunBrightness;
static float kKmEMoon = kMIE * _MoonBrightness;
static const float kKm4PI = kMIE * 4.0 * 3.14159265;
static const float kMoonKm4PI = kMIE * 4.0 * 3.14159265;
static const float kScale = 1.0 / (OUTER_RADIUS - 1.0);
static const float kScaleDepth = 0.25;
static const float kScaleOverScaleDepth = (1.0 / (OUTER_RADIUS - 1.0)) / 0.25;
static const float kSamples = 2.0; // THIS IS UNROLLED MANUALLY, DON'T TOUCH
#define MIE_G (-0.990)
#define MIE_G2 0.9801
#define SKY_GROUND_THRESHOLD 0.02
#ifndef SKYBOX_COLOR_IN_TARGET_COLOR_SPACE
#if defined(SHADER_API_MOBILE)
#define SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 1
#else
#define SKYBOX_COLOR_IN_TARGET_COLOR_SPACE 0
#endif
#endif
// Calculates the Rayleigh phase function
half getRayleighPhase(half eyeCos2)
{
return 0.75 + 0.75*eyeCos2;
}
half getRayleighPhase(half3 light, half3 ray)
{
half eyeCos = dot(light, ray);
return getRayleighPhase(eyeCos * eyeCos);
}
struct appdata_t
{
float4 vertex : POSITION;
float2 moonUV : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
half3 vertex : TEXCOORD0;
float2 moonUV : TEXCOORD1;
// calculate sky colors in vprog
half3 groundColor : TEXCOORD2;
half3 skyColor : TEXCOORD3;
half3 sunColor : TEXCOORD4;
half4 moonColor : TEXCOORD5;
};
float scale(float inCos)
{
float x = 1.0 - inCos;
#if defined(SHADER_API_N3DS)
// The polynomial expansion here generates too many swizzle instructions for the 3DS vertex assembler
// Approximate by removing x^1 and x^2
return 0.25 * exp(-0.00287 + x*x*x*(-6.80 + x*5.25));
#else
return 0.25 * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
#endif
}
v2f getOutputColors(half3 lightPos, float3 eyeRay, float3 cameraPos, float3 kInvWavelength, float kKr4PI, float kKrE, float kKmE)
{
v2f OUT;
half3 cIn, cOut;
float far = 0.0;
if (eyeRay.y >= 0.0)
{
// Sky
// Calculate the length of the "atmosphere"
far = sqrt(kOuterRadius2 + kInnerRadius2 * eyeRay.y * eyeRay.y - kInnerRadius2) - kInnerRadius * eyeRay.y;
float3 pos = cameraPos + far * eyeRay;
// Calculate the ray's starting position, then calculate its scattering offset
float height = kInnerRadius + kCameraHeight;
float depth = exp(kScaleOverScaleDepth * (-kCameraHeight));
float startAngle = dot(eyeRay, cameraPos) / height;
float startOffset = depth*scale(startAngle);
// Initialize the scattering loop variables
float sampleLength = far / kSamples;
float scaledLength = sampleLength * kScale;
float3 sampleRay = eyeRay * sampleLength;
float3 samplePoint = cameraPos + sampleRay * 0.5;
// Now loop through the sample rays
float3 frontColor = float3(0.0, 0.0, 0.0);
// Weird workaround: WP8 and desktop FL_9_1 do not like the for loop here
// (but an almost identical loop is perfectly fine in the ground calculations below)
// Just unrolling this manually seems to make everything fine again.
// for(int i=0; i<int(kSamples); i++)
{
float height = length(samplePoint);
float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height));
float lightAngle = dot(lightPos.xyz, samplePoint) / height;
float cameraAngle = dot(eyeRay, samplePoint) / height;
float scatter = (startOffset + depth*(scale(lightAngle) - scale(cameraAngle)));
float3 attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI));
frontColor += attenuate * (depth * scaledLength);
samplePoint += sampleRay;
}
{
float height = length(samplePoint);
float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height));
float lightAngle = dot(lightPos.xyz, samplePoint) / height;
float cameraAngle = dot(eyeRay, samplePoint) / height;
float scatter = (startOffset + depth*(scale(lightAngle) - scale(cameraAngle)));
float3 attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI));
frontColor += attenuate * (depth * scaledLength);
samplePoint += sampleRay;
}
cIn = frontColor * (kInvWavelength * kKrE);
cOut = frontColor * kKmE;
}
else
{
// Ground
far = (-kCameraHeight) / (min(-0.001, eyeRay.y));
float3 pos = cameraPos + far * eyeRay;
// Calculate the ray's starting position, then calculate its scattering offset
float depth = exp((-kCameraHeight) * (1.0 / kScaleDepth));
float cameraAngle = dot(-eyeRay, pos);
float lightAngle = dot(lightPos.xyz, pos);
float cameraScale = scale(cameraAngle);
float lightScale = scale(lightAngle);
float cameraOffset = depth*cameraScale;
float temp = (lightScale + cameraScale);
// Initialize the scattering loop variables
float sampleLength = far / kSamples;
float scaledLength = sampleLength * kScale;
float3 sampleRay = eyeRay * sampleLength;
float3 samplePoint = cameraPos + sampleRay * 0.5;
// Now loop through the sample rays
float3 frontColor = float3(0.0, 0.0, 0.0);
float3 attenuate;
// for(int i=0; i<int(kSamples); i++) // Loop removed because we kept hitting SM2.0 temp variable limits. Doesn't affect the image too much.
{
float height = length(samplePoint);
float depth = exp(kScaleOverScaleDepth * (kInnerRadius - height));
float scatter = depth*temp - cameraOffset;
attenuate = exp(-clamp(scatter, 0.0, kMAX_SCATTER) * (kInvWavelength * kKr4PI + kKm4PI));
frontColor += attenuate * (depth * scaledLength);
samplePoint += sampleRay;
}
cIn = frontColor * (kInvWavelength * kKrE + kKmE);
cOut = clamp(attenuate, 0.0, 1.0);
}
OUT.groundColor = _Exposure * (cIn + COLOR_2_LINEAR(_GroundColor) * cOut);
OUT.skyColor = _Exposure * (cIn * getRayleighPhase(lightPos.xyz, -eyeRay));
OUT.sunColor = _Exposure * (cOut * _LightColor0.xyz);
half3 _moonCol = _Exposure * (cOut * _MoonColor.xyz);
OUT.moonColor = half4(_moonCol, 1.0);
return OUT;
}
v2f vert (appdata_t v)
{
v2f OUT;
OUT.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 kSkyTintInGammaSpace = COLOR_2_GAMMA(_SkyTint); // convert tint from Linear back to Gamma
float3 kScatteringWavelength = lerp (
kDefaultScatteringWavelength-kVariableRangeForScatteringWavelength,
kDefaultScatteringWavelength+kVariableRangeForScatteringWavelength,
half3(1,1,1) - kSkyTintInGammaSpace); // using Tint in sRGB gamma allows for more visually linear interpolation and to keep (.5) at (128, gray in sRGB) point
float3 kInvWavelength = 1.0 / pow(kScatteringWavelength, 4);
float kKrESun = kRAYLEIGH * _SunBrightness;
float kKrEMoon = kMOONRAYLEIGH * _MoonBrightness;
float kKr4PI = kRAYLEIGH * 4.0 * 3.14159265;
float kMoonKr4PI = kMOONRAYLEIGH * 4.0 * 3.14159265;
float3 cameraPos = float3(0,kInnerRadius + kCameraHeight,0); // The camera's current position
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
float3 eyeRay = normalize(mul((float3x3)_Object2World, v.vertex.xyz));
//float3 moon_eyeRay = normalize(mul((float3x3)_Object2World, v.vertex.xyz));
v2f SUN_OUT = getOutputColors(_WorldSpaceLightPos0, eyeRay, cameraPos, kInvWavelength, kKr4PI, kKrESun, kKmESun);
v2f MOON_OUT = getOutputColors(_MoonPos, eyeRay, cameraPos, kInvWavelength, kMoonKr4PI, kKrEMoon, kKmEMoon);
OUT.vertex = -v.vertex;
OUT.moonUV = v.moonUV;
// if we want to calculate color in vprog:
// 1. in case of linear: multiply by _Exposure in here (even in case of lerp it will be common multiplier, so we can skip mul in fshader)
// 2. in case of gamma and SKYBOX_COLOR_IN_TARGET_COLOR_SPACE: do sqrt right away instead of doing that in fshader
OUT.groundColor = SUN_OUT.groundColor;
OUT.skyColor = SUN_OUT.skyColor;
OUT.sunColor = SUN_OUT.sunColor;
OUT.moonColor = MOON_OUT.moonColor;
#if defined(UNITY_COLORSPACE_GAMMA) && SKYBOX_COLOR_IN_TARGET_COLOR_SPACE
OUT.groundColor = sqrt(OUT.groundColor);
OUT.skyColor = sqrt(OUT.skyColor);
OUT.sunColor = sqrt(OUT.sunColor);
OUT.moonColor= sqrt(OUT.moonColor);
#endif
return OUT;
}
// Calculates the Mie phase function
half getMiePhase(half eyeCos, half eyeCos2, half size)
{
half temp = 1.0 + MIE_G2 - 2.0 * MIE_G * eyeCos;
temp = pow(temp, pow(size,0.65) * 10);
temp = max(temp,1.0e-4); // prevent division by zero, esp. in half precision
temp = 1.5 * ((1.0 - MIE_G2) / (2.0 + MIE_G2)) * (1.0 + eyeCos2) / temp;
#if defined(UNITY_COLORSPACE_GAMMA) && SKYBOX_COLOR_IN_TARGET_COLOR_SPACE
temp = pow(temp, .454545);
#endif
return temp;
}
half calcSpot(half3 vec1, half3 vec2, half size)
{
half3 delta = vec1 - vec2;
half dist = length(delta);
half spot = 1.0 - smoothstep(0.0, size, dist);
return kScale * spot * spot;
}
float2 changeSize(float2 coord, float size)
{
float2 h = coord.xy - float2(0.5, 0.5);
float r2 = h.x * h.x + h.y * h.y;
float f = 1.0 + r2; // *(_distortion * sqrt(r2));
return f * size * h + 0.5;
}
half4 frag (v2f IN) : SV_Target
{
half3 col = half3(0.0, 0.0, 0.0);
half3 ray = normalize(mul((float3x3)_Object2World, IN.vertex));
half y = ray.y / SKY_GROUND_THRESHOLD;
// if we did precalculate color in vprog: just do lerp between them
col = lerp(IN.skyColor, IN.groundColor, saturate(y));
if (y < 0.0)
{
// sun
half eyeCos = dot(_WorldSpaceLightPos0.xyz, ray);
half eyeCos2 = eyeCos * eyeCos;
half mie = getMiePhase(eyeCos, eyeCos2, _SunSize);
col += mie * IN.sunColor;
// moon
half moonEyeCos = dot(_MoonPos.xyz, ray);
half moonEyeCos2 = moonEyeCos * moonEyeCos;
half moonMie = getMiePhase(moonEyeCos, moonEyeCos2, _MoonSize);
// TODO: apply texture
//fixed moonTex = tex2D(_MoonTex, uv);
col += moonMie * IN.moonColor;
}
#if defined(UNITY_COLORSPACE_GAMMA) && !SKYBOX_COLOR_IN_TARGET_COLOR_SPACE
col = LINEAR_2_OUTPUT(col);
#endif
return half4(col,1.0);
}
ENDCG
}
}
Fallback Off
}
image-06021454798194-180633.jpg
(374.0 kB)
Comment
Your answer
Follow this Question
Related Questions
A question about UVW. 0 Answers
Noise left on texture when cleared (fog of war, Shader) 0 Answers
Tiling a noise texture 1:1 over each triangle without creating extra vertices 1 Answer
Combining 2 shaders 1 Answer
cannot combine shader of two objects 0 Answers