0
ich diese Shader https://www.shadertoy.com/view/MsB3WR zu Three.js zu portieren versucht und es ist eigentlich fast da, aber ich habe ein Problem mit UV-Mapping, so mittlerweile so etwas wie diese:Porting ShaderToy Ausgabe Three.js
SHADER Code:
vertexShader:
void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }
fragmentShader:
//mouse.z - left click
//mouse.w - right click
//texture A > iChannel0 > assets/textureA.png
//texture B > iChannel1 > assets/textureB.png
//texture C > iChannel2 > assets/textureC.png
#define BUMPFACTOR 0.1
#define EPSILON 0.1
#define BUMPDISTANCE 60.
//(iGlobalTime + 285.)
uniform float time;
uniform sampler2D textureA;
uniform sampler2D textureB;
uniform sampler2D textureC;
uniform vec2 resolution;
uniform vec3 mouse;
mat2 rot(const in float a) { return mat2(cos(a), sin(a), -sin(a), cos(a)); }
const mat2 m2 = mat2(0.60, -0.80, 0.80, 0.60);
const mat3 m3 = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
float noise(const in vec2 x) {
vec2 p = floor(x);
vec2 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
vec2 uv = (p.xy) + f.xy;
return texture2D(textureA, (uv + 0.5)/256.0, 0.0).x;
}
float noise(const 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;
vec2 rg = texture2D(textureA, (uv + 0.5)/256.0, 0.0).yx;
return mix(rg.x, rg.y, f.z);
}
float fbm(in vec3 p) {
float f = 0.0;
f += 0.5000 * noise(p); p = m3 * p * 2.02;
f += 0.2500 * noise(p); p = m3 * p * 2.03;
f += 0.1250 * noise(p); p = m3 * p * 2.01;
f += 0.0625 * noise(p);
return f/0.9375;
}
float hash(in float n) { return fract(sin(n) * 43758.5453); }
//INTERSECTION FUNCTION
bool intersectPlane(const in vec3 ro, const in vec3 rd, const in float height, inout float dist) {
if (rd.y == 0.0) { return false; }
float d = -(ro.y - height)/rd.y;
d = min(100000.0, d);
if(d > 0. && d < dist) {
dist = d;
return true;
}
return false;
}
//LIGHT DIRECTION
vec3 lig = normalize(vec3(0.3, 0.5, 0.6));
vec3 bgColor(const in vec3 rd) {
float sun = clamp(dot(lig, rd), 0.0, 1.0);
vec3 col = vec3(0.5, 0.52, 0.55) - rd.y * 0.2 * vec3(1.0, 0.8, 1.0) + 0.15 * 0.75;
col += vec3(1.0, 0.6, 0.1) * pow(sun, 8.0);
col *= 0.95;
return col;
}
//CLOUDS
#define CLOUDSCALE (500./(64. * 0.03))
float cloudMap(const in vec3 p, const in float ani) {
vec3 r = p/CLOUDSCALE;
float den = -1.8 + cos(r.y * 5.-4.3);
float f;
vec3 q = 2.5 * r * vec3(0.75, 1.0, 0.75) + vec3(1.0, 1.0, 15.0) * ani * 0.15;
f = 0.50000 * noise(q); q = q * 2.02 - vec3(-1.0,1.0,-1.0) * ani * 0.15;
f += 0.25000 * noise(q); q = q * 2.03 + vec3(1.0, -1.0, 1.0) * ani * 0.15;
f += 0.12500 * noise(q); q = q * 2.01 - vec3(1.0, 1.0, -1.0) * ani * 0.15;
f += 0.06250 * noise(q); q = q * 2.02 + vec3(1.0, 1.0, 1.0) * ani * 0.15;
f += 0.03125 * noise(q);
return 0.065 * clamp(den + 4.4 * f, 0.0, 1.0);
}
vec3 raymarchClouds(const in vec3 ro, const in vec3 rd, const in vec3 bgc, const in vec3 fgc, const in float startdist, const in float maxdist, const in float ani) {
float t = startdist + CLOUDSCALE * 0.02 * hash(rd.x + 35.6987221 * rd.y + time);
vec4 sum = vec4(0.0);
for(int i=0; i<64; i++) {
if(sum.a > 0.99 || t > maxdist) continue;
vec3 pos = ro + t*rd;
float a = cloudMap(pos, ani);
float dif = clamp(0.1 + 0.8*(a - cloudMap(pos + lig*0.15*CLOUDSCALE, ani)), 0., 0.5);
vec4 col = vec4((1.+dif)*fgc, a);
col.rgb *= col.a;
sum = sum + col*(1.0 - sum.a);
t += (0.03*CLOUDSCALE)+t*0.012;
}
sum.xyz = mix(bgc, sum.xyz/(sum.w+0.0001), sum.w);
return clamp(sum.xyz, 0.0, 1.0);
}
//TERRAIN
float terrainMap(const in vec3 p) {
return (texture2D(textureB, (-p.zx*m2)*0.000046, 0.).x*600.) * smoothstep(820., 1000., length(p.xz)) - 2. + noise(p.xz*0.5)*15.;
}
vec3 raymarchTerrain(const in vec3 ro, const in vec3 rd, const in vec3 bgc, const in float startdist, inout float dist) {
float t = startdist;
vec4 sum = vec4(0.0);
bool hit = false;
vec3 col = bgc;
for(int i=0; i<80; i++) {
if(hit) break;
t += 8. + t/300.;
vec3 pos = ro + t*rd;
if(pos.y < terrainMap(pos)) {
hit = true;
}
}
if(hit) {
float dt = 4.+t/400.;
t -= dt;
vec3 pos = ro + t*rd;
t += (0.5 - step(pos.y , terrainMap(pos))) * dt;
for(int j=0; j<2; j++) {
pos = ro + t*rd;
dt *= 0.5;
t += (0.5 - step(pos.y , terrainMap(pos))) * dt;
}
pos = ro + t*rd;
vec3 dx = vec3(100.*EPSILON, 0., 0.);
vec3 dz = vec3(0., 0., 100.*EPSILON);
vec3 normal = vec3(0., 0., 0.);
normal.x = (terrainMap(pos + dx) - terrainMap(pos-dx))/(200. * EPSILON);
normal.z = (terrainMap(pos + dz) - terrainMap(pos-dz))/(200. * EPSILON);
normal.y = 1.;
normal = normalize(normal);
col = vec3(0.2) + 0.7 * texture2D(textureC , pos.xz * 0.01).xyz *
vec3(1.0, 0.9, 0.6);
float veg = 0.3*fbm(pos*0.2)+normal.y;
if(veg > 0.75) {
col = vec3(0.45, 0.6, 0.3)*(0.5+0.5*fbm(pos*0.5))*0.6;
} else
if(veg > 0.66) {
col = col*0.6+vec3(0.4, 0.5, 0.3)*(0.5+0.5*fbm(pos*0.25))*0.3;
}
col *= vec3(0.5, 0.52, 0.65)*vec3(1.,.9,0.8);
vec3 brdf = col;
float diff = clamp(dot(normal, -lig), 0., 1.);
col = brdf*diff*vec3(1.0,.6,0.1);
col += brdf*clamp(dot(normal, lig), 0., 1.)*vec3(0.8,.6,0.5)*0.8;
col += brdf*clamp(dot(normal, vec3(0.,1.,0.)), 0., 1.)*vec3(0.8,.8,1.)*0.2;
dist = t;
t -= pos.y*3.5;
col = mix(col, bgc, 1.0-exp(-0.0000005*t*t));
}
return col;
}
float waterMap(vec2 pos) { vec2 posm = pos * m2; return abs(fbm(vec3(8. * posm, time))-0.5) * 0.1; }
void main(void)
{
vec2 q = gl_FragCoord.xy/resolution.xy;
vec2 p = -1.0 + 2.0 * q;
p.x *= resolution.x/resolution.y;
vec3 ro = vec3(0.0, 0.5, 0.0);
vec3 ta = vec3(0.0, 0.45,1.0);
if (mouse.z >= 1.0) { ta.xz *= rot((mouse.x/resolution.x - 0.5) * 7.0); }
ta.xz *= rot(mod(time * 0.05, 6.2831852));
vec3 ww = normalize(ta - ro);
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
vec3 vv = normalize(cross(ww,uu));
vec3 rd = normalize(p.x*uu + p.y*vv + 2.5*ww);
float fresnel, refldist = 5000., maxdist = 5000.;
bool reflected = false;
vec3 normal, col = bgColor(rd);
vec3 roo = ro, rdo = rd, bgc = col;
if(intersectPlane(ro, rd, 0., refldist) && refldist < 200.) {
ro += refldist*rd;
vec2 coord = ro.xz;
float bumpfactor = BUMPFACTOR * (1. - smoothstep(0., BUMPDISTANCE, refldist));
vec2 dx = vec2(EPSILON, 0.);
vec2 dz = vec2(0., EPSILON);
normal = vec3(0., 1., 0.);
normal.x = -bumpfactor * (waterMap(coord + dx) - waterMap(coord-dx))/(2. * EPSILON);
normal.z = -bumpfactor * (waterMap(coord + dz) - waterMap(coord-dz))/(2. * EPSILON);
normal = normalize(normal);
float ndotr = dot(normal,rd);
fresnel = pow(1.0-abs(ndotr),5.);
rd = reflect(rd, normal);
reflected = true;
bgc = col = bgColor(rd);
}
col = raymarchTerrain(ro, rd, col, reflected?(800.-refldist):800., maxdist);
col = raymarchClouds(ro, rd, col, bgc, reflected?max(0.,min(150.,(150.-refldist))):150., maxdist, time*0.05);
if(reflected) {
col = mix(col.xyz, bgc, 1.0-exp(-0.0000005 *refldist * refldist));
col *= fresnel * 0.9;
vec3 refr = refract(rdo, normal, 1./1.3330);
intersectPlane(ro, refr, -2., refldist);
col += mix(texture2D(textureC, (roo+refldist*refr).xz*1.3).xyz * vec3(1.0, 0.9, 0.6), vec3(1.0, 0.9, 0.8)*0.5, clamp(refldist/3.0, 0.0, 1.0)) * (1.-fresnel)*0.125;
}
col = pow(col, vec3(0.7));
col = col * col * (3.0-2.0 * col);
col = mix(col, vec3(dot(col,vec3(0.33))), -0.5);
col *= 0.25 + 0.75*pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1);
//vec4 color = texture2D(textureA, vUv);
gl_FragColor = vec4(col, 1.0);
}
Und JavaScript [Initialisierung]:
clock = new THREE.Clock();
mouse = new THREE.Vector4();
var loaderA = new THREE.TextureLoader();
var bitmapA = loaderA.load("assets/textureA.png");
var loaderB = new THREE.TextureLoader();
var bitmapB = loaderB.load("assets/textureB.png");
var loaderC = new THREE.TextureLoader();
var bitmapC = loaderC.load("assets/textureC.png");
var uniforms = {
textureA: { type: 't', value: bitmapA },
textureB: { type: 't', value: bitmapB },
textureC: { type: 't', value: bitmapC },
time: {
type: 'f',
value: clock.getDelta() + 285.
},
resolution: {
type: 'v2',
value: new THREE.Vector2(window.innerWidth, window.innerHeight)
},
mouse: {
type: 'v4',
value: new THREE.Vector4(window.innerWidth/2, window.innerHeight/2, 0.0, 0.0)
}
};
var glslMat = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById("vertexShader").textContent,
fragmentShader: document.getElementById("fragmentShader").textContent
});
var geometry = new THREE.PlaneGeometry(window.innerWidth * 4 , window.innerHeight * 4, 1, 1);
var plane = new THREE.Mesh(geometry, glslMat);
Irgendwelche Vorschläge?