mirror of
https://github.com/flutter/samples.git
synced 2025-11-10 23:08:59 +00:00
Next Gen UI demo (#1778)
First pass at a Next Generation UI demo app. The UI needs work, feedback gratefully accepted. ## Pre-launch Checklist - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I read the [Contributors Guide]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-devrel channel on [Discord]. <!-- Links --> [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/wiki/Chat [Contributors Guide]: https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
This commit is contained in:
16
next_gen_ui_demo/assets/shaders/common/common.glsl
Normal file
16
next_gen_ui_demo/assets/shaders/common/common.glsl
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#define M_PI 3.14159265
|
||||
#define M_INVPI 0.31830989
|
||||
|
||||
float hash_1d(float v) {
|
||||
float u = 50.0 * sin(v * 3000.0);
|
||||
return 2.0 * fract(2.0 * u * u) - 1.0;
|
||||
}
|
||||
|
||||
float hash_2d(vec2 pos) {
|
||||
vec2 uv = 50.0 * fract(pos * M_INVPI);
|
||||
return 2.0 * fract(uv.x * uv.y * (uv.x + uv.y)) - 1.0;
|
||||
}
|
||||
332
next_gen_ui_demo/assets/shaders/orb_shader.frag
Normal file
332
next_gen_ui_demo/assets/shaders/orb_shader.frag
Normal file
@@ -0,0 +1,332 @@
|
||||
// Copyright 2023 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#version 460 core
|
||||
|
||||
#include "common/common.glsl"
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
#define RAY_STEPS 30
|
||||
|
||||
uniform vec2 uResolution;
|
||||
uniform vec4 uPackedData;
|
||||
float uTime = uPackedData[0];
|
||||
float uExposure = uPackedData[1];
|
||||
float uFov = uPackedData[2];
|
||||
float uRoughness = uPackedData[3];
|
||||
uniform float uMetalness;
|
||||
uniform vec3 uLightDir;
|
||||
uniform float uLightR;
|
||||
uniform vec3 uLightLumP;
|
||||
uniform vec3 uAlbedo;
|
||||
uniform float uIor;
|
||||
uniform float uLightQuadAtt;
|
||||
uniform vec3 uAmbientLight;
|
||||
uniform float uAmbientLightDepthFactor;
|
||||
uniform float uEnergy;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
float noise_2d(vec2 pos) {
|
||||
vec2 g = floor(pos);
|
||||
float a = hash_2d(g);
|
||||
float b = hash_2d(g + vec2(1.0, 0.0));
|
||||
float c = hash_2d(g + vec2(0.0, 1.0));
|
||||
float d = hash_2d(g + vec2(1.0, 1.0));
|
||||
|
||||
vec2 fp = pos - g;
|
||||
vec2 sfp = smoothstep(vec2(0.0), vec2(1.0), fp);
|
||||
|
||||
return a + (b - a) * sfp.x + (c - a) * sfp.y +
|
||||
(a - b - c + d) * sfp.x * sfp.y;
|
||||
}
|
||||
|
||||
vec3 closest_point_on_disc(vec3 center, vec3 normal, float radius, vec3 p) {
|
||||
vec3 r = p - center;
|
||||
vec3 pr = r - dot(r, normal) * normal;
|
||||
return center + normalize(pr) * min(length(pr), radius);
|
||||
}
|
||||
|
||||
// Compute area light illuminance from: Moving Frostbite to Physically Based
|
||||
// Rendering 3.0, Siggraph 2014
|
||||
float illuminanceSphereOrDisk(float cosTheta, float sinSigmaSqr) {
|
||||
float cosThetaSqr = cosTheta * cosTheta;
|
||||
float sinTheta = sqrt(1.0 - cosThetaSqr);
|
||||
|
||||
float illuminance = 0.0;
|
||||
if (cosThetaSqr > sinSigmaSqr) {
|
||||
illuminance = M_PI * sinSigmaSqr * clamp(cosTheta, 0.0, 1.0);
|
||||
} else {
|
||||
float x = sqrt(1.0 / sinSigmaSqr - 1.0);
|
||||
float y = -x * (cosTheta / sinTheta);
|
||||
float sinThetaSqrtY = sinTheta * sqrt(1.0 - y * y);
|
||||
illuminance = (cosTheta * acos(y) - x * sinThetaSqrtY) * sinSigmaSqr +
|
||||
atan(sinThetaSqrtY / x);
|
||||
}
|
||||
|
||||
return max(illuminance, 0.0);
|
||||
}
|
||||
|
||||
float evalIlluminanceDisk(vec3 N, vec3 L, vec3 lightN, float lightRadius,
|
||||
float lightDistSqr) {
|
||||
float cosTheta = dot(N, L);
|
||||
float lightRSqr = lightRadius * lightRadius;
|
||||
|
||||
float sinSigmaSqr = lightRSqr / (lightRSqr + max(lightRSqr, lightDistSqr));
|
||||
|
||||
float illuminance = illuminanceSphereOrDisk(cosTheta, sinSigmaSqr) *
|
||||
clamp(dot(lightN, -L), 0.0, 1.0);
|
||||
|
||||
return illuminance;
|
||||
}
|
||||
|
||||
float distribution_ggx(vec3 N, vec3 H, float roughness) {
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
|
||||
float nom = a2;
|
||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||
denom = M_PI * denom * denom;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float geometry_schlick_ggx(float NdotV, float roughness) {
|
||||
float r = (roughness + 1.0);
|
||||
float k = (r * r) / 8.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float geometry_smith(vec3 N, vec3 V, float cosTheta, float roughness) {
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
|
||||
float ggx2 = geometry_schlick_ggx(NdotV, roughness);
|
||||
float ggx1 = geometry_schlick_ggx(cosTheta, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
vec3 fresnel_schlick(float cosTheta, vec3 F0) {
|
||||
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
vec3 brdf_eval(vec3 N, vec3 L, vec3 H, vec3 V, vec3 albedo, float roughness,
|
||||
float metalness, vec3 Li) {
|
||||
roughness = max(0.2, roughness);
|
||||
|
||||
float cosTheta = max(dot(N, L), 0.0);
|
||||
|
||||
// Diffuse color
|
||||
vec3 F0 = vec3(0.04);
|
||||
F0 = mix(F0, albedo, metalness);
|
||||
|
||||
float NDF = distribution_ggx(N, H, roughness);
|
||||
float G = geometry_smith(N, V, cosTheta, roughness);
|
||||
vec3 F = fresnel_schlick(max(dot(H, V), 0.0), F0);
|
||||
|
||||
vec3 num = NDF * G * F;
|
||||
float denom = 4.0 * max(dot(N, V), 0.0) * cosTheta;
|
||||
vec3 spec = num / max(denom, 0.001);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = 1.0 - kS;
|
||||
kD *= (1.0 - metalness);
|
||||
|
||||
vec3 Lo = (kD * albedo / M_PI + spec) * Li * cosTheta;
|
||||
|
||||
return Lo;
|
||||
}
|
||||
|
||||
vec3 btdf_eval(vec3 N, vec3 L, vec3 albedo, vec3 Li) {
|
||||
vec3 Lo = albedo * Li * max(dot(N, L), 0.0);
|
||||
return Lo;
|
||||
}
|
||||
|
||||
vec2 oct_encode(vec3 d) {
|
||||
vec3 octant = sign(d);
|
||||
|
||||
// Compute l1-norm version of the direction vector
|
||||
float sum = dot(d, octant);
|
||||
vec3 octahedron = d / sum;
|
||||
|
||||
if (octahedron.z < 0.0) {
|
||||
vec3 a = abs(octahedron);
|
||||
octahedron.xy = octant.xy * (vec2(1.0) - a.yx);
|
||||
}
|
||||
|
||||
return octahedron.xy * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
const mat2 octM0 = mat2(1.0, 0.0, 0.0, 1.0);
|
||||
const mat2 octM1 = mat2(0.809017, 0.587785, -0.587785, 0.809017);
|
||||
const mat2 octM2 = mat2(0.309017, 0.951057, -0.951057, 0.309017);
|
||||
const mat2 octM3 = mat2(-0.309017, 0.951057, -0.951057, -0.309017);
|
||||
|
||||
float fbm(vec2 pos) {
|
||||
float sum = 0.0;
|
||||
|
||||
sum += noise_2d(octM0 * pos);
|
||||
sum += 0.5 * noise_2d(2.0 * octM1 * pos);
|
||||
sum += 0.25 * noise_2d(4.0 * octM2 * pos);
|
||||
sum += 0.125 * noise_2d(8.0 * octM3 * pos);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
vec2 fbm_sphere_sdf(vec3 center, float radius, vec3 pos) {
|
||||
vec3 toP = pos - center;
|
||||
radius = radius * mix(0.5, 1.0, uEnergy);
|
||||
float d = length(toP);
|
||||
vec2 uv = oct_encode(toP);
|
||||
|
||||
float amp = mix(0.1, 0.6, uEnergy);
|
||||
float dd = fbm(uv * 15.0 + uTime * vec2(1.0, -0.4)) * amp;
|
||||
|
||||
return vec2(d + dd - radius,
|
||||
mix(0.4, 1.0, float(d - (radius + 1.0 * amp) > 0.0)));
|
||||
}
|
||||
|
||||
vec2 sample_scene(vec3 pos) {
|
||||
return fbm_sphere_sdf(vec3(0.0, 0.0, -10.0), 2.0, pos);
|
||||
}
|
||||
|
||||
const float sampleScale = 1.0 / sqrt(3.0) * 0.0005;
|
||||
|
||||
vec3 sample_normal(vec3 pos) {
|
||||
|
||||
#define NORMAL_SDF_SAMPLE_COUNT 4
|
||||
vec3 normalSampleOffsets[NORMAL_SDF_SAMPLE_COUNT];
|
||||
normalSampleOffsets[0] = vec3(1.0, -1.0, -1.0);
|
||||
normalSampleOffsets[1] = vec3(-1.0, -1.0, 1.0);
|
||||
normalSampleOffsets[2] = vec3(-1.0, 1.0, -1.0);
|
||||
normalSampleOffsets[3] = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
vec3 result = vec3(0.0);
|
||||
for (int i = 0; i < NORMAL_SDF_SAMPLE_COUNT; ++i) {
|
||||
result += normalSampleOffsets[i] * sampleScale *
|
||||
sample_scene(pos + normalSampleOffsets[i]).x;
|
||||
}
|
||||
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
float raymarch(vec3 start, vec3 dir) {
|
||||
float tMin = 8.0;
|
||||
float tMax = 15.0;
|
||||
|
||||
float t = tMin;
|
||||
|
||||
float result = -1.0;
|
||||
|
||||
for (int i = 0; i < RAY_STEPS; ++i) {
|
||||
if (t >= tMax)
|
||||
break;
|
||||
vec2 d = sample_scene(start + dir * t);
|
||||
if (d.x < 0.0002) {
|
||||
result = t;
|
||||
break;
|
||||
}
|
||||
t += d.x * d.y;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void look_at(out mat3 cam, in vec3 eye, in vec3 center, in vec3 up) {
|
||||
// Construct an ortho-normal basis for the camera
|
||||
vec3 forward = normalize(center - eye);
|
||||
vec3 right = cross(forward, up);
|
||||
up = cross(right, forward);
|
||||
|
||||
cam = mat3(right, up, forward);
|
||||
}
|
||||
|
||||
void sample_camera_ray(out vec3 origin, out vec3 direction, in mat3 cam,
|
||||
vec3 eye, vec2 uv) {
|
||||
|
||||
uv *= 2.0;
|
||||
uv -= 1.0;
|
||||
uv.y *= -1.0;
|
||||
|
||||
float aspectRatio = uResolution.y / uResolution.x;
|
||||
float vWidth = tan(uFov / 2.0);
|
||||
float vHeight = vWidth * aspectRatio;
|
||||
|
||||
vec3 forward = cam * vec3(0.0, 0.0, 1.0);
|
||||
vec3 rayDir = cam * vec3(uv.x * vWidth, uv.y * vHeight, 1.0);
|
||||
|
||||
origin = eye;
|
||||
direction = normalize(rayDir);
|
||||
}
|
||||
|
||||
vec3 sample_disk_light(out vec3 L, vec3 P, vec3 N, vec3 lightP, vec3 lightN,
|
||||
float lightR, vec3 lightAtt, vec3 lightLumP) {
|
||||
vec3 toL = closest_point_on_disc(lightP, lightN, lightR, P) - P;
|
||||
L = normalize(toL);
|
||||
toL *= lightAtt.x;
|
||||
float illuminance = evalIlluminanceDisk(N, L, lightN, lightR, dot(toL, toL));
|
||||
vec3 Li = lightLumP * illuminance;
|
||||
return Li;
|
||||
}
|
||||
|
||||
vec4 pixel_color(vec3 o, vec3 d, vec3 lightP, vec3 lightN, float lightR,
|
||||
vec3 lightAtt, vec3 lightLumP) {
|
||||
float t = raymarch(o, d);
|
||||
|
||||
vec4 result = vec4(0.0);
|
||||
|
||||
if (t >= 0.0) {
|
||||
vec3 P = o + d * t;
|
||||
vec3 N = sample_normal(P);
|
||||
vec3 V = -d;
|
||||
vec3 R = refract(-V, N, uIor);
|
||||
|
||||
float z = dot(vec3(0.0, 0.0, -1.0), P);
|
||||
float zd = smoothstep(mix(0.0, 11.0, uAmbientLightDepthFactor), 14.0, z);
|
||||
vec3 Lo = vec3(0.0);
|
||||
vec3 L, Li;
|
||||
|
||||
vec3 S = fresnel_schlick(max(dot(N, V), 0.0), vec3(0.02));
|
||||
|
||||
Li =
|
||||
sample_disk_light(L, P, R, lightP, lightN, lightR, lightAtt, lightLumP);
|
||||
Lo += (1.0 - S) * brdf_eval(-N, L, normalize(L + R), R, uAlbedo, uRoughness,
|
||||
uMetalness, Li);
|
||||
|
||||
Lo += zd * uAlbedo * uAmbientLight;
|
||||
|
||||
result = vec4(Lo, 1.0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = vec2(FlutterFragCoord().xy) / uResolution;
|
||||
|
||||
vec3 lightN = normalize(-uLightDir);
|
||||
vec3 lightP = vec3(0.0, 0.0, -10.0) + uLightDir;
|
||||
vec3 lightAtt = vec3(uLightQuadAtt, 0.0, 1.0);
|
||||
|
||||
vec3 eye = vec3(0.0, 0.0, 1.0);
|
||||
vec3 center = vec3(0.0, 0.0, 0.0);
|
||||
vec3 up = vec3(0.0, 1.0, 0.0);
|
||||
|
||||
mat3 cam;
|
||||
look_at(cam, eye, center, up);
|
||||
vec3 o, d;
|
||||
|
||||
sample_camera_ray(o, d, cam, eye, uv);
|
||||
vec4 hdrColor =
|
||||
abs(pixel_color(o, d, lightP, lightN, uLightR, lightAtt, uLightLumP));
|
||||
|
||||
vec3 ldrColor = vec3(1.0) - exp(min(-(hdrColor.rgb) * uExposure, 0.0));
|
||||
oColor = vec4(ldrColor, hdrColor.a);
|
||||
}
|
||||
68
next_gen_ui_demo/assets/shaders/ui_glitch.frag
Normal file
68
next_gen_ui_demo/assets/shaders/ui_glitch.frag
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2023 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#version 460 core
|
||||
|
||||
#include "common/common.glsl"
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
uniform vec2 uResolution;
|
||||
uniform float uTime;
|
||||
uniform sampler2D uTex;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
float cubicPulse(float c, float w, float x) {
|
||||
x = abs(x - c);
|
||||
if (x > w)
|
||||
return 0.0;
|
||||
x /= w;
|
||||
return 1.0 - x*x*(3.0 - 2.0*x);
|
||||
}
|
||||
|
||||
float twoSin(float x) {
|
||||
x = 6.49*x - 0.65;
|
||||
float t = -0.7*sin(6.8*x) + 1.4*sin(2.9*x);
|
||||
t = t/4.1 + 0.5;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 uv = vec2(FlutterFragCoord().xy) / uResolution;
|
||||
|
||||
float t_2 = cubicPulse(.5, .05, fract(uTime / 4.0));
|
||||
float t_1 = twoSin(fract(uTime / 5.0));
|
||||
float glitchScale = mix(0.0, 8.0, t_1 + t_2);
|
||||
float aberrationSize = mix(0.0, 5.0, t_1 + t_2);
|
||||
|
||||
float h = hash_1d(uv.y);
|
||||
float hs = sign(h);
|
||||
h = max(h, 0.0);
|
||||
h = h * h;
|
||||
h = round(h) * hs;
|
||||
|
||||
uv += vec2(h * glitchScale, 0.0) / uResolution;
|
||||
|
||||
vec2 redOffset = vec2(aberrationSize, 0.0) / uResolution;
|
||||
vec2 greenOffset = vec2(0.0, 0.0) / uResolution;
|
||||
vec2 blueOffset = vec2(-aberrationSize, 0.0) / uResolution;
|
||||
|
||||
vec2 redUv = uv + redOffset;
|
||||
vec2 greenUv = uv + greenOffset;
|
||||
vec2 blueUv = uv + blueOffset;
|
||||
|
||||
vec2 ra = texture(uTex, redUv).ra;
|
||||
vec2 ga = texture(uTex, greenUv).ga;
|
||||
vec2 ba = texture(uTex, blueUv).ba;
|
||||
|
||||
// Convert from pre-multiplied alpha
|
||||
ra.x /= ra.y;
|
||||
ga.x /= ga.y;
|
||||
ba.x /= ba.y;
|
||||
|
||||
float alpha = max(ra.y, max(ga.y, ba.y));
|
||||
oColor = vec4(ra.x, ga.x, ba.x, 1.0) * alpha;
|
||||
}
|
||||
Reference in New Issue
Block a user