Shadertoy-4D Grid Slice

先上效果图:


shadertoy原始网址:https://www.shadertoy.com/view/Mts3Wl


代码如下:


// Ben Quantock 2015
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// https://creativecommons.org/licenses/by-nc-sa/3.0/

// consts
const float tau = 6.2831853;
const float phi = 1.61803398875;

vec2 Noise( in vec3 x )
{
    vec3 p = floor(x);
    vec3 f = fract(x);
	f = f*f*(3.0-2.0*f);
	vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
	vec4 rg = texture2D( iChannel0, (uv+0.5)/256.0, -100.0 );
	return mix( rg.yw, rg.xz, f.z );
}



vec4 Map( vec3 p3 )
{
    // construct an orthonormal frame for the slice
//	um... there's no 4D cross product, is there? There can't be! Would need 3 inputs. balls.
    vec4 i = vec4(1,0,0,0);
    vec4 j = vec4(0,1,0,0);
    vec4 k = vec4(0,0,1,0);
    
    // rules for rotation should still behave afaik
    float a,c;
    vec2 s;
    a = iGlobalTime*.1;
    c = cos(a); s = vec2(1,-1)*sin(a);
    i.xz = i.xz*c + i.zx*s;
    j.xz = j.xz*c + j.zx*s;
    k.xz = k.xz*c + k.zx*s;
    i.yw = i.yw*c + i.wy*s;
    j.yw = j.yw*c + j.wy*s;
    k.yw = k.yw*c + k.wy*s;
    i.xw = i.xw*c + i.wx*s;
    j.xw = j.xw*c + j.wx*s;
    k.xw = k.xw*c + k.wx*s;
    i.yz = i.yz*c + i.zy*s;
    j.yz = j.yz*c + j.zy*s;
    k.yz = k.yz*c + k.zy*s;
    
    // form a basis perp to vec4(1,1,1,1)
//    actually easier than it sounds, just make it so dot prods sum to 0
/*    vec4 i = vec4(1,1,-1,-1)/2.0;
    vec4 j = vec4(-1,1,-1,1)/2.0;
    vec4 k = vec4(1,-1,-1,1)/2.0;*/
    
    //vec4 p = vec4(p3,0);
    vec4 p = i*p3.x + j*p3.y + k*p3.z;// + vec4(1,1,1,1)*.5*.25;

    return p;
}
    
float DistanceField( vec3 p3 )
{
    vec4 p = Map(p3);
    
    // offset to centre of cell
    float f = 100.0;
    
    // cells
    vec4 o = .5 - abs(fract(p+.5)-.5);
    f = min(f, .2 - min(min(min(o.x, o.y), o.z), o.w ) );
        
	// or grid edges (is this meaningful? - apparently, yes)
    f = min(f, min(min(min(min(min(length(o.xy),length(o.xz)),length(o.xw)),length(o.yz)),length(o.yw)),length(o.zw)) - .03);
    
    p = abs(p);
    return max( f, max(max(max(p.x,p.y),p.z),p.w)-1.53 );
}




vec3 Sky( vec3 ray )
{
	return mix( vec3(.8), vec3(0), exp2(-(1.0/max(ray.y,.01))*vec3(.4,.6,1.0)) );
}


vec3 Shade( vec3 pos, vec3 ray, vec3 normal, vec3 lightDir, vec3 lightCol, float shadowMask, float distance )
{
    vec4 p = Map(pos);

    vec4 c = (p+1.5)/3.0;
    //vec3 albedo = (c.xyz);// + c.www)*.5;//vec3(.25);
//    vec3 albedo = vec3(.75,0,0)*c.x + vec3(.25,.5,0)*c.y + vec3(0,.5,.25)*c.z + vec3(0,0,.75)*c.w;
    
    vec4 o = .5 - abs(fract(p+.5)-.5);
    vec3 albedo = mix( vec3(1,0,0), vec3(1), step(.1,min(min(min(o.x, o.y), o.z), o.w )) );


	// direct light
	float ndotl = max(.0,dot(normal,lightDir));
	float lightCut = smoothstep(.0,.1,ndotl);//pow(ndotl,2.0);
	vec3 light = lightCol*shadowMask*ndotl;


	// ambient light
	vec3 ambient = mix( vec3(.2,.27,.4), vec3(.4), (-normal.y*.5+.5) ); // ambient

	// ambient occlusion, based on my DF Lighting: https://www.shadertoy.com/view/XdBGW3
	float aoRange = distance/20.0;
	float occlusion = max( 0.0, 1.0 - DistanceField( pos + normal*aoRange )/aoRange ); // can be > 1.0
	occlusion = exp2( -2.0*pow(occlusion,2.0) ); // tweak the curve
	ambient *= occlusion;


	// subsurface scattering
	float transmissionRange = 0.1;
	float transmission = DistanceField( pos + lightDir*transmissionRange )/transmissionRange;
	vec3 sslight = lightCol * smoothstep(0.0,1.0,transmission);
	vec3 subsurface = vec3(1,.8,.5) * sslight;


	// specular
	float specPower = 400.0;
	
	vec3 h = normalize(lightDir-ray);
    float specFres = mix( .02, 1.0, pow( 1.0 - dot(h,lightDir), 5.0 ) );
	vec3 specular = lightCol*shadowMask*pow(max(.0,dot(normal,h))*lightCut, specPower)*specFres*(specPower+6.0)/32.0;
	

	// reflections
	vec3 rray = reflect(ray,normal);
	vec3 reflection = Sky( rray );
	
	// reflection occlusion, adjust the divisor for the gradient we expect
	float specOcclusion = max( 0.0, 1.0 - DistanceField( pos + rray*aoRange )/(aoRange*max(.01,dot(rray,normal))) ); // can be > 1.0
	specOcclusion = exp2( -2.0*pow(specOcclusion,2.0) ); // tweak the curve
	
	// prevent sparkles in heavily occluded areas
	specOcclusion *= occlusion;

	reflection *= specOcclusion; // could fire an additional ray for more accurate results
	
	// fresnel
	float fresnel = pow( 1.0+dot(normal,ray), 5.0 );
	fresnel = mix( .02, 1.0, fresnel );
	
	vec3 result = vec3(0);

	
	// Combine all shading stages
	// comment these out to toggle various parts of the effect
	light += ambient;

//	light = mix( light, subsurface, .5 );
	
	result = light*albedo;

//	result = mix( result, reflection, fresnel );
	
	result += specular;

	return result;
}




// Isosurface Renderer
#ifdef FAST
const int traceLimit=40;
const float traceSize=.005;
#else
const int traceLimit=100;
const float traceSize=.001;//before *t: .002;
#endif	

float Trace( vec3 pos, vec3 ray, float traceStart, float traceEnd )
{
	float t = traceStart;
	float h;
	for( int i=0; i < traceLimit; i++ )
	{
		h = DistanceField( pos+t*ray );
		if ( h < traceSize*t || t > traceEnd )
			break;
		t = t+h;
	}
	
	if ( t > traceEnd )//|| h > .001 )
		return 0.0;
	
	return t;
}

float TraceMin( vec3 pos, vec3 ray, float traceStart, float traceEnd )
{
	float Min = traceEnd;
	float t = traceStart;
	float h;
	for( int i=0; i < traceLimit; i++ )
	{
		h = DistanceField( pos+t*ray );
		if ( h < .001 || t > traceEnd )
			break;
		Min = min(h,Min);
		t = t+max(h,.1);
	}
	
	if ( h < .001 )
		return 0.0;
	
	return Min;
}

vec3 Normal( vec3 pos, vec3 ray, float t )
{
	// in theory we should be able to get a good gradient using just 4 points

	float pitch = .2 * t / iResolution.x;
#ifdef FAST
	// don't sample smaller than the interpolation errors in Noise()
	pitch = max( pitch, .005 );
#endif
	
	vec2 d = vec2(-1,1) * pitch;

	vec3 p0 = pos+d.xxx; // tetrahedral offsets
	vec3 p1 = pos+d.xyy;
	vec3 p2 = pos+d.yxy;
	vec3 p3 = pos+d.yyx;
	
	float f0 = DistanceField(p0);
	float f1 = DistanceField(p1);
	float f2 = DistanceField(p2);
	float f3 = DistanceField(p3);
	
	vec3 grad = p0*f0+p1*f1+p2*f2+p3*f3 - pos*(f0+f1+f2+f3);
	
	// prevent normals pointing away from camera (caused by precision errors)
	float gdr = dot ( grad, ray );
	grad -= max(.0,gdr)*ray;
	
	return normalize(grad);
}


// Camera

vec3 Ray( float zoom, vec2 fragCoord )
{
	return vec3( fragCoord.xy-iResolution.xy*.5, iResolution.x*zoom );
}

vec3 Rotate( inout vec3 v, vec2 a )
{
	vec4 cs = vec4( cos(a.x), sin(a.x), cos(a.y), sin(a.y) );
	
	v.yz = v.yz*cs.x+v.zy*cs.y*vec2(-1,1);
	v.xz = v.xz*cs.z+v.zx*cs.w*vec2(1,-1);
	
	vec3 p;
	p.xz = vec2( -cs.w, -cs.z )*cs.x;
	p.y = cs.y;
	
	return p;
}


// Camera Effects

void BarrelDistortion( inout vec3 ray, float degree )
{
	// would love to get some disperson on this, but that means more rays
	ray.z /= degree;
	ray.z = ( ray.z*ray.z - dot(ray.xy,ray.xy) ); // fisheye
	ray.z = degree*sqrt(ray.z);
}

vec3 LensFlare( vec3 ray, vec3 lightCol, vec3 light, float lightVisible, float sky, vec2 fragCoord )
{
	vec2 dirtuv = fragCoord.xy/iResolution.x;
	
	float dirt = 1.0-texture2D( iChannel1, dirtuv ).r;
	
	float l = (dot(light,ray)*.5+.5);
	
	return (
			((pow(l,30.0)+.05)*dirt*.1
			+ 1.0*pow(l,200.0))*lightVisible + sky*1.0*pow(l,5000.0)
		   )*lightCol
		   + 5.0*pow(smoothstep(.9999,1.0,l),20.0) * lightVisible * normalize(lightCol);
}


float SmoothMax( float a, float b, float smoothing )
{
	return a-sqrt(smoothing*smoothing+pow(max(.0,a-b),2.0));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec3 ray = Ray( .7, fragCoord );
	
	BarrelDistortion( ray, .5 );
	
	ray = normalize(ray);
	vec3 localRay = ray;

    vec2 rot = vec2(.2,0.0);
    
	float T = iGlobalTime*.13;
	vec2 mouse = vec2(.2,.5);
	if ( iMouse.z > .0 )
		rot += vec2(1.0,-6.3) * (vec2(.5)-iMouse.yx/iResolution.yx);
    else
        rot -= vec2(0,1)*T;
		
    float dist = 7.0;// * (-sin(iGlobalTime/10.0)+1.0);
	vec3 pos = dist*Rotate( ray, rot );
	//pos += vec3(0,.3,0) + T*vec3(0,0,-1);
	
	vec3 col;

	vec3 lightDir = normalize(vec3(3,1,-2));
	
	vec3 lightCol = vec3(1.1,1,.9)*1.0;
	
	// can adjust these according to the scene, even per-pixel to a bounding volume
	float near = .0;
	float far = 40.0;
	
	float t = Trace( pos, ray, near, far );
	if ( t > .0 )
	{
		vec3 p = pos + ray*t;
		
		// shadow test
		float s = 0.0;
		//s = TraceMin( p, lightDir, .05, far );
        s = Trace( p, lightDir, .01*t, far );
		
		vec3 n = Normal(p, ray, t);
		col = Shade( p, ray, n, lightDir, lightCol,
					//smoothstep( .0, .01, s ),
                    step( s, .001 ),
                    t );
		
		// fog
		float f = 200.0;
		col = mix( vec3(.8), col, exp2(-t*vec3(.4,.6,1.0)/f) );
	}
	else
	{
		col = Sky( ray );
	}
	
	// lens flare
	float s = TraceMin( pos, lightDir, .5, 40.0 );
	col += LensFlare( ray, lightCol, lightDir, smoothstep(.01,.1,s), step(t,.0), fragCoord );
	
	// vignetting:
	col *= smoothstep( 1.0, .0, dot(localRay.xy,localRay.xy) );
	
	// compress bright colours, ( because bloom vanishes in vignette )
	vec3 c = (col-1.0);
	c = sqrt(c*c+.05); // soft abs
	col = mix(col,1.0-c,.48); // .5 = never saturate, .0 = linear
	
	// grain
	vec2 grainuv = fragCoord.xy + floor(iGlobalTime*60.0)*vec2(37,41);
	vec2 filmNoise = texture2D( iChannel0, .5*grainuv/iChannelResolution[0].xy ).rb;
	col *= mix( vec3(1), mix(vec3(1,.5,0),vec3(0,.5,1),filmNoise.x), .1*filmNoise.y );
	
	// compress bright colours
	float l = max(col.x,max(col.y,col.z));//dot(col,normalize(vec3(2,4,1)));
	l = max(l,.01); // prevent div by zero, darker colours will have no curve
	float l2 = SmoothMax(l,1.0,.01);
	col *= l2/l;
	
	fragColor = vec4(pow(col,vec3(1.0/2.2)),1);
}

转换成hlsl后的:
float2 R:TARGETSIZE;
Texture2D tex0 <string uiname="Texture1";>;
Texture2D tex1 <string uiname="Texture2";>;
SamplerState s0  <bool visible=false;string uiname="Sampler";> 
{
<span style="white-space:pre">	</span>Filter=MIN_MAG_MIP_LINEAR;
<span style="white-space:pre">	</span>AddressU=wrap;
<span style="white-space:pre">	</span>AddressV=wrap;
};


cbuffer cbPerDraw:register( b0 )
{
float4x4 tVP:VIEWPROJECTION;<span style="white-space:pre">	</span>
float4x4 tW:WORLD;
float time;
float2 mouse;
float3 lightDir; 
float specPower = 400.0;
};


static float tau = 6.2831853;
static float phi = 1.61803398875;


float2 Noise( in float3 x )
{
    float3 p = floor(x);
    float3 f = frac(x);
<span style="white-space:pre">	</span>f = f*f*(3.0-2.0*f);
<span style="white-space:pre">	</span>float2 uv = (p.xy+float2(37.0,17.0)*p.z) + f.xy;
<span style="white-space:pre">	</span>float4 rg = tex0.Sample( s0, (uv+0.5)/256.0, -100.0 );
<span style="white-space:pre">	</span>return lerp( rg.yw, rg.xz, f.z );
}


float4 Map( float3 p3 )
{
    //construct an orthonormal frame for the slice
<span style="white-space:pre">	</span>//um... there's no 4D cross product, is there? There can't be! Would need 3 inputs. balls.
    float4 i = float4(1,0,0,0);
    float4 j = float4(0,1,0,0);
    float4 k = float4(0,0,1,0);
    
    // rules for rotation should still behave afaik
    float a,c;
    float2 s;
    a = time*.1;
    c = cos(a); s = float2(1,-1)*sin(a);
    i.xz = i.xz*c + i.zx*s;
    j.xz = j.xz*c + j.zx*s;
    k.xz = k.xz*c + k.zx*s;
    i.yw = i.yw*c + i.wy*s;
    j.yw = j.yw*c + j.wy*s;
    k.yw = k.yw*c + k.wy*s;
    i.xw = i.xw*c + i.wx*s;
    j.xw = j.xw*c + j.wx*s;
    k.xw = k.xw*c + k.wx*s;
    i.yz = i.yz*c + i.zy*s;
    j.yz = j.yz*c + j.zy*s;
    k.yz = k.yz*c + k.zy*s;
    
    // form a basis perp to float4(1,1,1,1)
<span style="white-space:pre">	</span>// actually easier than it sounds, just make it so dot prods sum to 0
/*    float4 i = float4(1,1,-1,-1)/2.0;
    float4 j = float4(-1,1,-1,1)/2.0;
    float4 k = float4(1,-1,-1,1)/2.0;*/
    
    //float4 p = float4(p3,0);
    float4 p = i*p3.x + j*p3.y + k*p3.z;// + float4(1,1,1,1)*.5*.25;


    return p;
}
    
float DistanceField( float3 p3 )
{
    float4 p = Map(p3);
    
    // offset to centre of cell
    float f = 100.0;
    
    // cells
    float4 o = .5 - abs(frac(p+.5)-.5);
    f = min(f, .2 - min(min(min(o.x, o.y), o.z), o.w ) );
        
<span style="white-space:pre">	</span>// or grid edges (is this meaningful? - apparently, yes)
    f = min(f, min(min(min(min(min(length(o.xy),length(o.xz)),length(o.xw)),length(o.yz)),length(o.yw)),length(o.zw)) - .03);
    
    p = abs(p);
    return max( f, max(max(max(p.x,p.y),p.z),p.w)-1.53 );
}


float3 Sky( float3 ray )
{
<span style="white-space:pre">	</span>return lerp( float(.8), float(0), exp2(-(1.0/max(-ray.y,.01))*float3(.4,.6,1.0)));
}




float3 Shade( float3 pos, float3 ray, float3 normal, float3 lightCol, float shadowMask, float distance )
{
    float4 p = Map(pos);


    float4 c = (p+1.5)/3.0;
    //float3 albedo = (c.xyz);// + c.www)*.5;//float3(.25);
    //float3 albedo = float3(.75,0,0)*c.x + float3(.25,.5,0)*c.y + float3(0,.5,.25)*c.z + float3(0,0,.75)*c.w;
    
    float4 o = .5 - abs(frac(p+.5)-.5);
    float3 albedo = lerp( float3(1,0,0), float(1), step(.1,min(min(min(o.x, o.y), o.z), o.w )) );




<span style="white-space:pre">	</span>// direct light
<span style="white-space:pre">	</span>float ndotl = max(.0,dot(normal,lightDir));
<span style="white-space:pre">	</span>float lightCut = smoothstep(.0,.1,ndotl);//pow(ndotl,2.0);
<span style="white-space:pre">	</span>float3 light = lightCol*shadowMask*ndotl;




<span style="white-space:pre">	</span>// ambient light
<span style="white-space:pre">	</span>float3 ambient = lerp(  float3(.2,.27,.4), float(.4), (-normal.y*.5+.5) ); // ambient


<span style="white-space:pre">	</span>// ambient occlusion, based on my DF Lighting: https://www.shadertoy.com/view/XdBGW3
<span style="white-space:pre">	</span>float aoRange = distance/20.0;
<span style="white-space:pre">	</span>float occlusion = max( 0.0, 1.0 - DistanceField( pos + normal*aoRange )/aoRange ); // can be > 1.0
<span style="white-space:pre">	</span>occlusion = exp2( -2.0*pow(occlusion,2.0) ); // tweak the curve
<span style="white-space:pre">	</span>ambient *= occlusion;




<span style="white-space:pre">	</span>// subsurface scattering
<span style="white-space:pre">	</span>float transmissionRange = 0.1;
<span style="white-space:pre">	</span>float transmission = DistanceField( pos + lightDir*transmissionRange )/transmissionRange;
<span style="white-space:pre">	</span>float3 sslight = lightCol * smoothstep(0.0,1.0,transmission);
<span style="white-space:pre">	</span>float3 subsurface = float3(1,.8,.5) * sslight;




<span style="white-space:pre">	</span>// specular
<span style="white-space:pre">	</span>float3 h = normalize(lightDir-ray);
    float specFres = lerp( .02, 1.0, pow( 1.0 - dot(h,lightDir), 5.0 ) );
<span style="white-space:pre">	</span>float3 specular = lightCol*shadowMask*pow(max(.0,dot(normal,h))*lightCut, specPower)*specFres*(specPower+6.0)/32.0;
<span style="white-space:pre">	</span>


<span style="white-space:pre">	</span>// reflections
<span style="white-space:pre">	</span>float3 rray = reflect(ray,normal);
<span style="white-space:pre">	</span>float3 reflection = Sky( rray );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// reflection occlusion, adjust the divisor for the gradient we expect
<span style="white-space:pre">	</span>float specOcclusion = max( 0.0, 1.0 - DistanceField( pos + rray*aoRange )/(aoRange*max(.01,dot(rray,normal))) ); // can be > 1.0
<span style="white-space:pre">	</span>specOcclusion = exp2( -2.0*pow(specOcclusion,2.0) ); // tweak the curve
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// prevent sparkles in heavily occluded areas
<span style="white-space:pre">	</span>specOcclusion *= occlusion;


<span style="white-space:pre">	</span>reflection *= specOcclusion; // could fire an additional ray for more accurate results
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// fresnel
<span style="white-space:pre">	</span>float fresnel = pow( 1.0+dot(normal,ray), 5.0 );
<span style="white-space:pre">	</span>fresnel = lerp( .02, 1.0, fresnel );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float3 result = float(0);


<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// Combine all shading stages
<span style="white-space:pre">	</span>// comment these out to toggle various parts of the effect
<span style="white-space:pre">	</span>light += ambient;


//<span style="white-space:pre">	</span>light = mix( light, subsurface, .5 );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>result = light*albedo;


//<span style="white-space:pre">	</span>result = mix( result, reflection, fresnel );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>result += specular;


<span style="white-space:pre">	</span>return result;
}




// Isosurface Renderer
#ifdef FAST
int traceLimit=40;
float traceSize=.005;
#else
int traceLimit=100;
float traceSize=.001;//before *t: .002;
#endif<span style="white-space:pre">	</span>






float Trace( float3 pos, float3 ray, float traceStart, float traceEnd )
{
<span style="white-space:pre">	</span>float t = traceStart;
<span style="white-space:pre">	</span>float h;
<span style="white-space:pre">	</span>for( int i=0; i < traceLimit; i++ )
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>h = DistanceField( pos+t*ray );
<span style="white-space:pre">		</span>if ( h < traceSize*t || t > traceEnd )
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>t = t+h;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>if ( t > traceEnd )//|| h > .001 )
<span style="white-space:pre">		</span>return 0.0;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return t;
}


float TraceMin( float3 pos, float3 ray, float traceStart, float traceEnd )
{
<span style="white-space:pre">	</span>float Min = traceEnd;
<span style="white-space:pre">	</span>float t = traceStart;
<span style="white-space:pre">	</span>float h;
<span style="white-space:pre">	</span>for( int i=0; i < traceLimit; i++ )
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>h = DistanceField( pos+t*ray );
<span style="white-space:pre">		</span>if ( h < .001 || t > traceEnd )
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>Min = min(h,Min);
<span style="white-space:pre">		</span>t = t+max(h,.1);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>if ( h < .001 )
<span style="white-space:pre">		</span>return 0.0;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return Min;
}


float3 Normal( float3 pos, float3 ray, float t )
{
<span style="white-space:pre">	</span>// in theory we should be able to get a good gradient using just 4 points


<span style="white-space:pre">	</span>float pitch = .2 * t / R.x;
#ifdef FAST
<span style="white-space:pre">	</span>// don't sample smaller than the interpolation errors in Noise()
<span style="white-space:pre">	</span>pitch = max( pitch, .005 );
#endif
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float2 d = float2(-1,1) * pitch;


<span style="white-space:pre">	</span>float3 p0 = pos+d.xxx; // tetrahedral offsets
<span style="white-space:pre">	</span>float3 p1 = pos+d.xyy;
<span style="white-space:pre">	</span>float3 p2 = pos+d.yxy;
<span style="white-space:pre">	</span>float3 p3 = pos+d.yyx;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float f0 = DistanceField(p0);
<span style="white-space:pre">	</span>float f1 = DistanceField(p1);
<span style="white-space:pre">	</span>float f2 = DistanceField(p2);
<span style="white-space:pre">	</span>float f3 = DistanceField(p3);
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float3 grad = p0*f0+p1*f1+p2*f2+p3*f3 - pos*(f0+f1+f2+f3);
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// prevent normals pointing away from camera (caused by precision errors)
<span style="white-space:pre">	</span>float gdr = dot ( grad, ray );
<span style="white-space:pre">	</span>grad -= max(.0,gdr)*ray;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return normalize(grad);
}




// Camera


float3 Ray( float zoom, float4 fragCoord )
{
<span style="white-space:pre">	</span>return float3( fragCoord.xy-R.xy*.5, R.x*zoom );
}


float3 Rotate( inout float3 v, float2 a )
{
<span style="white-space:pre">	</span>float4 cs = float4( cos(a.x), sin(a.x), cos(a.y), sin(a.y) );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>v.yz = v.yz*cs.x+v.zy*cs.y*float2(-1,1);
<span style="white-space:pre">	</span>v.xz = v.xz*cs.z+v.zx*cs.w*float2(1,-1);
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float3 p;
<span style="white-space:pre">	</span>p.xz = float2( -cs.w, -cs.z )*cs.x;
<span style="white-space:pre">	</span>p.y = cs.y;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return p;
}




// Camera Effects


void BarrelDistortion( inout float3 ray, float degree )
{
<span style="white-space:pre">	</span>// would love to get some disperson on this, but that means more rays
<span style="white-space:pre">	</span>ray.z /= degree;
<span style="white-space:pre">	</span>ray.z = ( ray.z*ray.z - dot(ray.xy,ray.xy) ); // fisheye
<span style="white-space:pre">	</span>ray.z = degree*sqrt(ray.z);
}


float3 LensFlare( float3 ray, float3 lightCol, float3 light, float lightVisible, float sky, float4 fragCoord )
{
<span style="white-space:pre">	</span>float2 dirtuv = fragCoord.xy/R.x;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float dirt = 1.0-tex1.Sample( s0, dirtuv ).r;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float l = (dot(light,ray)*.5+.5);
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return (
<span style="white-space:pre">			</span>((pow(abs(l),30.0)+.05)*dirt*.1
<span style="white-space:pre">			</span>+ 1.0*pow(abs(l),200.0))*lightVisible + sky*1.0*pow(abs(l),5000.0)
<span style="white-space:pre">		</span>   )*lightCol
<span style="white-space:pre">		</span>   + 5.0*pow(smoothstep(.9999,1.0,l),20.0) * lightVisible * normalize(lightCol);
}




float SmoothMax( float a, float b, float smoothing )
{
<span style="white-space:pre">	</span>return a-sqrt(smoothing*smoothing+pow(max(.0,a-b),2.0));
}


struct VS_IN
{
<span style="white-space:pre">	</span>float4 PosO:POSITION;
<span style="white-space:pre">	</span>float4 TexCd:TEXCOORD0;
};


struct vs2ps
{
    float4 PosWVP:SV_POSITION;
    float4 TexCd:TEXCOORD0;
};


vs2ps VS(VS_IN input)
{
    vs2ps output;
    output.PosWVP  = mul(input.PosO,tW); //mul(input.PosO,mul(tW,tVP));
    output.TexCd = input.TexCd;
    return output;
}


float4 PS(vs2ps In) : SV_Target
{
  
  float3 ray = Ray( .7, In.PosWVP );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>BarrelDistortion( ray, .5 );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>ray = normalize(ray);
<span style="white-space:pre">	</span>float3 localRay = ray;


    float2 rot = float2(.2,0.0);
    
<span style="white-space:pre">	</span>float T = time*.13;
<span style="white-space:pre">	</span>float3 mouse = float3(.2,.5,0);
<span style="white-space:pre">	</span>if ( mouse.z > .0 )
<span style="white-space:pre">		</span>rot += float2(1.0,-6.3) * (float(.5)-mouse.yx/R.yx);
    else
        rot -= float2(0,1)*T;
<span style="white-space:pre">		</span>
    float dist = 7.0;// * (-sin(iGlobalTime/10.0)+1.0);
<span style="white-space:pre">	</span>float3 pos = dist*Rotate( ray, rot );
<span style="white-space:pre">	</span>//pos += float3(0,.3,0) + T*float3(0,0,-1);
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float3 col;


<span style="white-space:pre">	</span>float3 lightDir = normalize(float3(3,1,-2));
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float3 lightCol = float3(1.1,1,.9)*1.0;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// can adjust these according to the scene, even per-pixel to a bounding volume
<span style="white-space:pre">	</span>float near = .0;
<span style="white-space:pre">	</span>float far = 40.0;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>float t = Trace( pos, ray, near, far );
<span style="white-space:pre">	</span>if ( t > .0 )
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>float3 p = pos + ray*t;
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>// shadow test
<span style="white-space:pre">		</span>float s = 0.0;
<span style="white-space:pre">		</span>//s = TraceMin( p, lightDir, .05, far );
        s = Trace( p, lightDir, .01*t, far );
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>float3 n = Normal(p, ray, t);
<span style="white-space:pre">		</span>col = Shade( p, ray, n,  lightCol,
<span style="white-space:pre">					</span>//smoothstep( .0, .01, s ),
                    step( s, .001 ),
                    t );
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>// fog
<span style="white-space:pre">		</span>float f = 200.0;
<span style="white-space:pre">		</span>col = lerp( float(.8), col, exp2(-t*float3(.4,.6,1.0)/f) );
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>else
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>col = Sky( ray );
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// lens flare
<span style="white-space:pre">	</span>float s = TraceMin( pos, lightDir, .5, 40.0 );
<span style="white-space:pre">	</span>col += LensFlare( ray, lightCol, lightDir, smoothstep(.01,.1,s), step(t,.0),In.TexCd );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// vignetting:
<span style="white-space:pre">	</span>col *= smoothstep( 1.0, .0, dot(localRay.xy,localRay.xy) );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// compress bright colours, ( because bloom vanishes in vignette )
<span style="white-space:pre">	</span>float3 c = (col-1.0);
<span style="white-space:pre">	</span>c = sqrt(c*c+.05); // soft abs
<span style="white-space:pre">	</span>col = lerp(col,1.0-c,.48); // .5 = never saturate, .0 = linear
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// grain
<span style="white-space:pre">	</span>float2 grainuv = In.TexCd.xy + floor(time*60.0)*float2(37,41);
<span style="white-space:pre">	</span>float2 filmNoise = tex0.Sample( s0, .5*grainuv/R.xy ).rb;
<span style="white-space:pre">	</span>col *= lerp( float(1), lerp(float3(1,.5,0),float3(0,.5,1),filmNoise.x), .1*filmNoise.y );
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// compress bright colours
<span style="white-space:pre">	</span>float l = max(col.x,max(col.y,col.z));//dot(col,normalize(float3(2,4,1)));
<span style="white-space:pre">	</span>l = max(l,.01); // prevent div by zero, darker colours will have no curve
<span style="white-space:pre">	</span>float l2 = SmoothMax(l,1.0,.01);
<span style="white-space:pre">	</span>col *= l2/l;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return float4(pow(abs(col),float(1.0/2.2)),1);
}




technique10 _4DGridSlice
{
<span style="white-space:pre">	</span>pass P0
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>SetVertexShader(CompileShader(vs_4_0,VS()));
<span style="white-space:pre">		</span>SetPixelShader(CompileShader(ps_4_0,PS()));
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>}
}


以上!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值