Thanks for your Reply.
- The SHader is just a Mixture of a base Shader Used as layer of the Skyshop: Self illumination Ibl.
You got here the Exerp of the Full code :
Shader "Unity3DLabs/Marmoset/Bumped Specular IBL - 01 - ALPHA BUMP SPEC BLEND" {
Properties {
_Color ("---------- 0º LAYER - 00 - SKYSHOP SELF ILLUMINATED -------------", Range(0,0)) = 0.0
_Color ("Diffuse Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (1,1,1,1)
_SpecInt ("Specular Intensity", Range(-5.0,5.0)) = 1.0
_SpecInt (" ", Float) = 1.0
_Shininess ("Specular Sharpness", Range(2.0,8.0)) = 4.0
_Shininess (" ", Float) = 4.0
_Fresnel ("Fresnel Strength", Range(0.0,1.0)) = 0.0
_Fresnel (" ", Float) = 0.0
_MainTex ("Diffuse(RGB) Alpha(A)", 2D) = "white" {}
_SpecTex ("Specular(RGB) Gloss(A)", 2D) = "white" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
//slots for Emissive lighting
_GlowColor ("Glow Color", Color) = (1,1,1,1)
_GlowStrength("Glow Strength", Float) = 1.0
_EmissionLM ("Diffuse Emission Strength", Float) = 0.0
_Illum ("Glow(RGB) Diffuse Emission(A)", 2D) = "white" {}
//slots for custom lighting cubemaps
_DiffCubeIBL ("Custom Diffuse Cube", Cube) = "black" {}
_SpecCubeIBL ("Custom Specular Cube", Cube) = "black" {}
//slots for custom OVERLAY
_Color1 ("---------- 1º LAYER - 01 - BASE DIFUSE SPECULAR -------------", Range(0,0)) = 0.0
_Color1 ("Main Color", Color) = (1,1,1,1)
_SpecColor1 ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
_Shininess1 ("Shininess", Range(-0.1,0.1)) = 0.05
_Shininess1 (" ", Float) = 0.0001
_MainTex1 ("Base (RGB) TransGloss (A)", 2D) = "white" {}
_BumpMap1 ("Normalmap", 2D) = "bump" {}
}
SubShader {
Tags {
"Queue"="Geometry"
"RenderType"="Opaque"
}
LOD 400
//diffuse LOD 200
//diffuse-spec LOD 250
//bumped-diffuse, spec 350
//bumped-spec 400
//mac stuff
CGPROGRAM
#ifdef SHADER_API_OPENGL
#pragma glsl
#endif
#pragma target 3.0
#pragma surface MarmosetSurf MarmosetDirect
//gamma-correct sampling permutations
#pragma multi_compile MARMO_LINEAR MARMO_GAMMA
#define MARMO_HQ
#define MARMO_SKY_ROTATION
#define MARMO_DIFFUSE_IBL
#define MARMO_SPECULAR_IBL
#define MARMO_DIFFUSE_DIRECT
#define MARMO_SPECULAR_DIRECT
#define MARMO_NORMALMAP
#define MARMO_MIP_GLOSS
#define MARMO_GLOW
#define MARMO_PREMULT_ALPHA
#include "MarmosetMobile.cginc"
#include "MarmosetCore.cginc"
#include "MarmosetInput.cginc"
#include "MarmosetDirect.cginc"
#include "MarmosetSurf.cginc"
ENDCG
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
CGPROGRAM
#pragma surface surf BlinnPhong alpha
sampler2D _MainTex1;
sampler2D _BumpMap1;
fixed4 _Color1;
half _Shininess1;
struct Input {
float2 uv_MainTex1;
float2 uv_BumpMap1;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex1, IN.uv_MainTex1);
o.Albedo = tex.rgb * _Color1.rgb;
o.Gloss = tex.a;
o.Alpha = tex.a * _Color1.a;
o.Specular = _Shininess1;
o.Normal = UnpackNormal(tex2D(_BumpMap1, IN.uv_BumpMap1));
}
ENDCG
}
FallBack "Diffuse"
}
Its nothing fancy as you see …
The Real trick is inside the
#include “MarmosetMobile.cginc”
#include “MarmosetCore.cginc”
#include “MarmosetInput.cginc”
#include “MarmosetDirect.cginc”
#include “MarmosetSurf.cginc”
Wich ( If you own Marmoset ) You can Include in Any Shader Those lines within the CGPROGRAM
And it will pull All the SkyShop magic Into the Shader …
Whatever shader you got …
But Things Start to Become A litle More dificult if You Want to make Complete Custom SHaders …
Its not So dificult to do it on Desktop / you just use extra Passes.
Mobile is Quite Complicated other thing …
Even out of my league / not going even to mention here : )
ANYWAY ! As far as i Availed :
Anyway there are somethings i should point.
- We all can do Custom SHader Programing / OVER SkyShop Shaders .
-
- Its Niçe and NEAT and not everyone knows how to do it … Therefore this New Thread Existance And need …
BUT This SHaders Overlays Only Work for SKYSHOP users .
- They Integrate The Need of a Custom MarmosetCore.cginc / that to Have it you must buy Skyshop .
-
- Without Those extra libraries the shader doesnt work / so you must Own Skyshop For this Custom Shaders to work .
IF YOU THINK ABOUT IT !
BUT Basicaly this IBL tricks Dont Even Need / the SkyShop Shader at all ( in Case you Dont Own Skyshop )
CUBEMAP Refletions is Actualy very Easy code :
Shader "Cg shader with reflection map" {
Properties {
_Cube("Reflection Map", Cube) = "" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// User-specified uniforms
uniform samplerCUBE _Cube;
// The following built-in uniforms are also
// defined in "UnityCG.cginc", which could be #included
uniform float4 unity_Scale; // w = 1/scale; see _World2Object
uniform float3 _WorldSpaceCameraPos;
uniform float4x4 _Object2World; // model matrix
uniform float4x4 _World2Object; // inverse model matrix
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normalDir : TEXCOORD0;
float3 viewDir : TEXCOORD1;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors
output.viewDir = float3(mul(modelMatrix, input.vertex)
- float4(_WorldSpaceCameraPos, 1.0));
output.normalDir = normalize(float3(
mul(float4(input.normal, 0.0), modelMatrixInverse)));
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
float3 reflectedDir =
reflect(input.viewDir, normalize(input.normalDir));
return texCUBE(_Cube, reflectedDir);
}
ENDCG
}
}
}
THE DIFICULT STUFF IS TO ADD “IMAGE BASED LIGHTNING”
- That more than simple “refletion” but cast lightsourçes from the skydome …
SKYSHOP MAKES THINGS EASY/BREEZY and FAST FOR YOU :
- Getting proper High Quality Enviroment Image Based Light casting …
-
- Make Proper Ibl Cubemaps ( a very hard task )
-
- Have Proper Shaders that capture the Light Transmitance …
- But even if you Dont own SKYSHOP / And you are Short on money : You Can ACtualy Code your own IBL Shader …
THE RESULTS WILL NEVER BE AS 10% GOOD as SKYSHOP …
-
- But just For example , if you Want to Add Many light Sourçes Refleting over with image-based lighting, in particular diffuse (irradiance) environment mapping and its implementation with cube maps
-
- This is Codewise very Simple :
As a Example in the code below :
Shader "Cg shader with image-based diffuse lighting" {
Properties {
_OriginalCube ("Environment Map", Cube) = "" {}
_Cube ("Diffuse Environment Map", Cube) = "" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// User-specified uniforms
uniform samplerCUBE _Cube;
// The following built-in uniform is also
// defined in "UnityCG.cginc", which could be #included
uniform float4x4 _World2Object; // inverse model matrix
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normalDir : TEXCOORD0;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors
output.normalDir = normalize(float3(
mul(float4(input.normal, 0.0), modelMatrixInverse)));
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return texCUBE(_Cube, input.normalDir);
}
ENDCG
}
}
}
But you need Aditional COmputation For the Cubemap Generation and Computation of Diffuse Environment Maps
That in c# Script this would be :
using UnityEngine;
using UnityEditor;
using System.Collections;
[ExecuteInEditMode]
public class ComputeDiffuseEnvironmentMap : MonoBehaviour
{
public Cubemap originalCubeMap;
// environment map specified in the shader by the user
//[System.Serializable]
// avoid being deleted by the garbage collector,
// and thus leaking
private Cubemap filteredCubeMap;
// the computed diffuse irradience environment map
private void Update()
{
Cubemap originalTexture = null;
try
{
originalTexture = renderer.sharedMaterial.GetTexture(
"_OriginalCube") as Cubemap;
}
catch (System.Exception)
{
Debug.LogError("'_OriginalCube' not found on shader. "
+ "Are you using the wrong shader?");
return;
}
if (originalTexture == null)
// did the user set "none" for the map?
{
if (originalCubeMap != null)
{
renderer.sharedMaterial.SetTexture("_Cube", null);
originalCubeMap = null;
filteredCubeMap = null;
return;
}
}
else if (originalTexture == originalCubeMap
filteredCubeMap != null
renderer.sharedMaterial.GetTexture("_Cube") == null)
{
renderer.sharedMaterial.SetTexture("_Cube",
filteredCubeMap); // set the computed
// diffuse environment map in the shader
}
else if (originalTexture != originalCubeMap
|| filteredCubeMap
!= renderer.sharedMaterial.GetTexture("_Cube"))
{
if (EditorUtility.DisplayDialog(
"Processing of Environment Map",
"Do you want to process the cube map of face size "
+ originalTexture.width + "x" + originalTexture.width
+ "? (This will take some time.)",
"OK", "Cancel"))
{
if (filteredCubeMap
!= renderer.sharedMaterial.GetTexture("_Cube"))
{
if (renderer.sharedMaterial.GetTexture("_Cube")
!= null)
{
DestroyImmediate(
renderer.sharedMaterial.GetTexture(
"_Cube")); // clean up
}
}
if (filteredCubeMap != null)
{
DestroyImmediate(filteredCubeMap); // clean up
}
originalCubeMap = originalTexture;
filteredCubeMap = computeFilteredCubeMap();
//computes the diffuse environment map
renderer.sharedMaterial.SetTexture("_Cube",
filteredCubeMap); // set the computed
// diffuse environment map in the shader
return;
}
else
{
originalCubeMap = null;
filteredCubeMap = null;
renderer.sharedMaterial.SetTexture("_Cube", null);
renderer.sharedMaterial.SetTexture(
"_OriginalCube", null);
}
}
}
// This function computes a diffuse environment map in
// "filteredCubemap" of the same dimensions as "originalCubemap"
// by integrating -- for each texel of "filteredCubemap" --
// the diffuse illumination from all texels of "originalCubemap"
// for the surface normal vector corresponding to the direction
// of each texel of "filteredCubemap".
private Cubemap computeFilteredCubeMap()
{
Cubemap filteredCubeMap = new Cubemap(originalCubeMap.width,
originalCubeMap.format, true);
int filteredSize = filteredCubeMap.width;
int originalSize = originalCubeMap.width;
// Compute all texels of the diffuse environment cube map
// by itterating over all of them
for (int filteredFace = 0; filteredFace < 6; filteredFace++)
// the six sides of the cube
{
for (int filteredI = 0; filteredI < filteredSize; filteredI++)
{
for (int filteredJ = 0; filteredJ < filteredSize; filteredJ++)
{
Vector3 filteredDirection =
getDirection(filteredFace,
filteredI, filteredJ, filteredSize).normalized;
float totalWeight = 0.0f;
Vector3 originalDirection;
Vector3 originalFaceDirection;
float weight;
Color filteredColor = new Color(0.0f, 0.0f, 0.0f);
// sum (i.e. integrate) the diffuse illumination
// by all texels in the original environment map
for (int originalFace = 0; originalFace < 6; originalFace++)
{
originalFaceDirection = getDirection(
originalFace, 1, 1, 3).normalized;
//the normal vector of the face
for (int originalI = 0; originalI < originalSize; originalI++)
{
for (int originalJ = 0; originalJ < originalSize; originalJ++)
{
originalDirection = getDirection(
originalFace, originalI,
originalJ, originalSize);
// direction to the texel
// (i.e. light source)
weight = 1.0f
/ originalDirection.sqrMagnitude;
// take smaller size of more
// distant texels into account
originalDirection =
originalDirection.normalized;
weight = weight * Vector3.Dot(
originalFaceDirection,
originalDirection);
// take tilt of texel compared
// to face into account
weight = weight * Mathf.Max(0.0f,
Vector3.Dot(filteredDirection,
originalDirection));
// directional filter
// for diffuse illumination
totalWeight = totalWeight + weight;
// instead of analytically
// normalization, we just normalize
// to the potential max illumination
filteredColor = filteredColor + weight
* originalCubeMap.GetPixel(
(CubemapFace)originalFace,
originalI, originalJ); // add the
// illumination by this texel
}
}
}
filteredCubeMap.SetPixel(
(CubemapFace)filteredFace, filteredI,
filteredJ, filteredColor / totalWeight);
// store the diffuse illumination of this texel
}
}
}
// Avoid seams between cube faces: average edge texels
// to the same color on each side of the seam
int maxI = filteredCubeMap.width - 1;
for (int i = 0; i < maxI; i++)
{
setFaceAverage(ref filteredCubeMap,
0, i, 0, 2, maxI, maxI - i);
setFaceAverage(ref filteredCubeMap,
0, 0, i, 4, maxI, i);
setFaceAverage(ref filteredCubeMap,
0, i, maxI, 3, maxI, i);
setFaceAverage(ref filteredCubeMap,
0, maxI, i, 5, 0, i);
setFaceAverage(ref filteredCubeMap,
1, i, 0, 2, 0, i);
setFaceAverage(ref filteredCubeMap,
1, 0, i, 5, maxI, i);
setFaceAverage(ref filteredCubeMap,
1, i, maxI, 3, 0, maxI - i);
setFaceAverage(ref filteredCubeMap,
1, maxI, i, 4, 0, i);
setFaceAverage(ref filteredCubeMap,
2, i, 0, 5, maxI - i, 0);
setFaceAverage(ref filteredCubeMap,
2, i, maxI, 4, i, 0);
setFaceAverage(ref filteredCubeMap,
3, i, 0, 4, i, maxI);
setFaceAverage(ref filteredCubeMap,
3, i, maxI, 5, maxI - i, maxI);
}
// Avoid seams between cube faces:
// average corner texels to the same color
// on all three faces meeting in one corner
setCornerAverage(ref filteredCubeMap,
0, 0, 0, 2, maxI, maxI, 4, maxI, 0);
setCornerAverage(ref filteredCubeMap,
0, maxI, 0, 2, maxI, 0, 5, 0, 0);
setCornerAverage(ref filteredCubeMap,
0, 0, maxI, 3, maxI, 0, 4, maxI, maxI);
setCornerAverage(ref filteredCubeMap,
0, maxI, maxI, 3, maxI, maxI, 5, 0, maxI);
setCornerAverage(ref filteredCubeMap,
1, 0, 0, 2, 0, 0, 5, maxI, 0);
setCornerAverage(ref filteredCubeMap,
1, maxI, 0, 2, 0, maxI, 4, 0, 0);
setCornerAverage(ref filteredCubeMap,
1, 0, maxI, 3, 0, maxI, 5, maxI, maxI);
setCornerAverage(ref filteredCubeMap,
1, maxI, maxI, 3, 0, 0, 4, 0, maxI);
filteredCubeMap.Apply(); //apply all SetPixel(..) commands
return filteredCubeMap;
}
private void setFaceAverage(ref Cubemap filteredCubeMap,
int a, int b, int c, int d, int e, int f)
{
Color average =
(filteredCubeMap.GetPixel((CubemapFace)a, b, c)
+ filteredCubeMap.GetPixel((CubemapFace)d, e, f)) / 2.0f;
filteredCubeMap.SetPixel((CubemapFace)a, b, c, average);
filteredCubeMap.SetPixel((CubemapFace)d, e, f, average);
}
private void setCornerAverage(ref Cubemap filteredCubeMap,
int a, int b, int c, int d, int e, int f, int g, int h, int i)
{
Color average =
(filteredCubeMap.GetPixel((CubemapFace)a, b, c)
+ filteredCubeMap.GetPixel((CubemapFace)d, e, f)
+ filteredCubeMap.GetPixel((CubemapFace)g, h, i)) / 3.0f;
filteredCubeMap.SetPixel((CubemapFace)a, b, c, average);
filteredCubeMap.SetPixel((CubemapFace)d, e, f, average);
filteredCubeMap.SetPixel((CubemapFace)g, h, i, average);
}
private Vector3 getDirection(int face, int i, int j, int size)
{
switch (face)
{
case 0:
return new Vector3(0.5f,
-((j + 0.5f) / size - 0.5f),
-((i + 0.5f) / size - 0.5f));
case 1:
return new Vector3(-0.5f,
-((j + 0.5f) / size - 0.5f),
((i + 0.5f) / size - 0.5f));
case 2:
return new Vector3(((i + 0.5f) / size - 0.5f),
0.5f, ((j + 0.5f) / size - 0.5f));
case 3:
return new Vector3(((i + 0.5f) / size - 0.5f),
-0.5f, -((j + 0.5f) / size - 0.5f));
case 4:
return new Vector3(((i + 0.5f) / size - 0.5f),
-((j + 0.5f) / size - 0.5f), 0.5f);
case 5:
return new Vector3(-((i + 0.5f) / size - 0.5f),
-((j + 0.5f) / size - 0.5f), -0.5f);
default:
return Vector3.zero;
}
}
}
ANYWAY ! THAT SAID ! …
Knoledge is power …
Interact WIth this Thread !
And Open Share your Custom Programed IBL SHaders With us !
More to come from me…
As i Would reaaly love to have a Whole Gamut of Custom Shaders Available for everyone To Share and Do variances of it !

ITS A COOL IDEA !
If you are around Join in here : )
The Chalenge here is to Call People Interested in IMAGE BASED LIGHTNING !
To COntribute Custom Shader OPEN Code !
SO we all can use this PHISICAL BASED / IBL SHADERS …
And Have also some / Greath Library of Diferent IBL Shaders to Work with !
Thats the Purpose of this Whole Thread and of the 3DLABS Project as well…
THANKS FOR PASSING !
Cheers
KYO