mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
'Starter Project': port planet fragment shader to impeller tests (flutter/engine#53362)
This is a modified planet shader from the SimonDev's "GLSL Shaders from Scratch" course on teachables. With permission from Simon: > 100% use however you want, with or without credit I choose "with credit". https://github.com/flutter/engine/assets/1924313/47da62b5-6b6d-47c2-ac9f-f3a33f177a86
This commit is contained in:
parent
44b391bfa9
commit
2a344eafcf
@ -32,6 +32,8 @@ impeller_shaders("shader_fixtures") {
|
||||
"instanced_draw.vert",
|
||||
"mipmaps.frag",
|
||||
"mipmaps.vert",
|
||||
"planet.frag",
|
||||
"planet.vert",
|
||||
"sample.comp",
|
||||
"sepia.frag",
|
||||
"sepia.vert",
|
||||
|
||||
486
engine/src/flutter/impeller/fixtures/planet.frag
Normal file
486
engine/src/flutter/impeller/fixtures/planet.frag
Normal file
@ -0,0 +1,486 @@
|
||||
uniform FragInfo {
|
||||
vec2 resolution;
|
||||
float time;
|
||||
float speed;
|
||||
float planet_size;
|
||||
float show_normals;
|
||||
float show_noise;
|
||||
float seed_value;
|
||||
}
|
||||
frag_info;
|
||||
|
||||
in vec2 v_screen_position;
|
||||
out vec4 frag_color;
|
||||
|
||||
float inverseLerp(float v, float min_value, float max_value) {
|
||||
return (v - min_value) / (max_value - min_value);
|
||||
}
|
||||
|
||||
float remap(float v, float in_min, float in_max, float out_min, float out_max) {
|
||||
float t = inverseLerp(v, in_min, in_max);
|
||||
return mix(out_min, out_max, t);
|
||||
}
|
||||
|
||||
float saturate(float x) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Copyright (C) 2011 by Ashima Arts (Simplex noise)
|
||||
// Copyright (C) 2011-2016 by Stefan Gustavson (Classic noise and others)
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions: The above copyright
|
||||
// notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
// THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// https://github.com/ashima/webgl-noise/tree/master/src
|
||||
vec3 mod289(vec3 x) {
|
||||
return x - floor(x / 289.0) * 289.0;
|
||||
}
|
||||
|
||||
vec4 mod289(vec4 x) {
|
||||
return x - floor(x / 289.0) * 289.0;
|
||||
}
|
||||
|
||||
vec4 permute(vec4 x) {
|
||||
return mod289((x * 34.0 + 1.0) * x);
|
||||
}
|
||||
|
||||
vec4 taylorInvSqrt(vec4 r) {
|
||||
return 1.79284291400159 - r * 0.85373472095314;
|
||||
}
|
||||
|
||||
vec4 snoise(vec3 v) {
|
||||
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
|
||||
|
||||
// First corner
|
||||
vec3 i = floor(v + dot(v, vec3(C.y)));
|
||||
vec3 x0 = v - i + dot(i, vec3(C.x));
|
||||
|
||||
// Other corners
|
||||
vec3 g = step(x0.yzx, x0.xyz);
|
||||
vec3 l = 1.0 - g;
|
||||
vec3 i1 = min(g.xyz, l.zxy);
|
||||
vec3 i2 = max(g.xyz, l.zxy);
|
||||
|
||||
vec3 x1 = x0 - i1 + C.x;
|
||||
vec3 x2 = x0 - i2 + C.y;
|
||||
vec3 x3 = x0 - 0.5;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i); // Avoid truncation effects in permutation
|
||||
vec4 p = permute(permute(permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + i.y +
|
||||
vec4(0.0, i1.y, i2.y, 1.0)) +
|
||||
i.x + vec4(0.0, i1.x, i2.x, 1.0));
|
||||
|
||||
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||
vec4 j = p - 49.0 * floor(p / 49.0); // mod(p,7*7)
|
||||
|
||||
vec4 x_ = floor(j / 7.0);
|
||||
vec4 y_ = floor(j - 7.0 * x_);
|
||||
|
||||
vec4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0;
|
||||
vec4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0;
|
||||
|
||||
vec4 h = 1.0 - abs(x) - abs(y);
|
||||
|
||||
vec4 b0 = vec4(x.xy, y.xy);
|
||||
vec4 b1 = vec4(x.zw, y.zw);
|
||||
|
||||
vec4 s0 = floor(b0) * 2.0 + 1.0;
|
||||
vec4 s1 = floor(b1) * 2.0 + 1.0;
|
||||
vec4 sh = -step(h, vec4(0.0));
|
||||
|
||||
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
|
||||
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
|
||||
|
||||
vec3 g0 = vec3(a0.xy, h.x);
|
||||
vec3 g1 = vec3(a0.zw, h.y);
|
||||
vec3 g2 = vec3(a1.xy, h.z);
|
||||
vec3 g3 = vec3(a1.zw, h.w);
|
||||
|
||||
// Normalize gradients
|
||||
vec4 norm =
|
||||
taylorInvSqrt(vec4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3)));
|
||||
g0 *= norm.x;
|
||||
g1 *= norm.y;
|
||||
g2 *= norm.z;
|
||||
g3 *= norm.w;
|
||||
|
||||
// Compute noise and gradient at P
|
||||
vec4 m =
|
||||
max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
|
||||
vec4 m2 = m * m;
|
||||
vec4 m3 = m2 * m;
|
||||
vec4 m4 = m2 * m2;
|
||||
vec3 grad = -6.0 * m3.x * x0 * dot(x0, g0) + m4.x * g0 +
|
||||
-6.0 * m3.y * x1 * dot(x1, g1) + m4.y * g1 +
|
||||
-6.0 * m3.z * x2 * dot(x2, g2) + m4.z * g2 +
|
||||
-6.0 * m3.w * x3 * dot(x3, g3) + m4.w * g3;
|
||||
vec4 px = vec4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3));
|
||||
return 42.0 * vec4(grad, dot(m4, px));
|
||||
}
|
||||
|
||||
// The MIT License
|
||||
// Copyright © 2013 Inigo Quilez
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions: The above copyright
|
||||
// notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
// THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// https://www.youtube.com/c/InigoQuilez
|
||||
// https://iquilezles.org/
|
||||
//
|
||||
// https://www.shadertoy.com/view/Xsl3Dl
|
||||
vec3 hash3(vec3 p) // replace this by something better
|
||||
{
|
||||
p = vec3(dot(p, vec3(127.1, 311.7, 74.7)), dot(p, vec3(269.5, 183.3, 246.1)),
|
||||
dot(p, vec3(113.5, 271.9, 124.6)));
|
||||
|
||||
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
|
||||
}
|
||||
|
||||
float noise(in vec3 p) {
|
||||
vec3 i = floor(p);
|
||||
vec3 f = fract(p);
|
||||
|
||||
vec3 u = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
return mix(
|
||||
mix(mix(dot(hash3(i + vec3(0.0, 0.0, 0.0)), f - vec3(0.0, 0.0, 0.0)),
|
||||
dot(hash3(i + vec3(1.0, 0.0, 0.0)), f - vec3(1.0, 0.0, 0.0)),
|
||||
u.x),
|
||||
mix(dot(hash3(i + vec3(0.0, 1.0, 0.0)), f - vec3(0.0, 1.0, 0.0)),
|
||||
dot(hash3(i + vec3(1.0, 1.0, 0.0)), f - vec3(1.0, 1.0, 0.0)),
|
||||
u.x),
|
||||
u.y),
|
||||
mix(mix(dot(hash3(i + vec3(0.0, 0.0, 1.0)), f - vec3(0.0, 0.0, 1.0)),
|
||||
dot(hash3(i + vec3(1.0, 0.0, 1.0)), f - vec3(1.0, 0.0, 1.0)),
|
||||
u.x),
|
||||
mix(dot(hash3(i + vec3(0.0, 1.0, 1.0)), f - vec3(0.0, 1.0, 1.0)),
|
||||
dot(hash3(i + vec3(1.0, 1.0, 1.0)), f - vec3(1.0, 1.0, 1.0)),
|
||||
u.x),
|
||||
u.y),
|
||||
u.z);
|
||||
}
|
||||
|
||||
float fbm6(vec3 p, float persistence, float lacunarity, float exponentiation) {
|
||||
float amplitude = 0.5;
|
||||
float frequency = 1.0;
|
||||
float total = 0.0;
|
||||
float normalization = 0.0;
|
||||
|
||||
p = p + frag_info.seed_value;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
float noiseValue = snoise(p * frequency).w;
|
||||
total += noiseValue * amplitude;
|
||||
normalization += amplitude;
|
||||
amplitude *= persistence;
|
||||
frequency *= lacunarity;
|
||||
}
|
||||
|
||||
total /= normalization;
|
||||
total = total * 0.5 + 0.5;
|
||||
total = pow(total, exponentiation);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
float fbm2(vec3 p, float persistence, float lacunarity, float exponentiation) {
|
||||
float amplitude = 0.5;
|
||||
float frequency = 1.0;
|
||||
float total = 0.0;
|
||||
float normalization = 0.0;
|
||||
p = p + frag_info.seed_value;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
float noiseValue = snoise(p * frequency).w;
|
||||
total += noiseValue * amplitude;
|
||||
normalization += amplitude;
|
||||
amplitude *= persistence;
|
||||
frequency *= lacunarity;
|
||||
}
|
||||
|
||||
total /= normalization;
|
||||
total = total * 0.5 + 0.5;
|
||||
total = pow(total, exponentiation);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
vec3 GenerateStarGrid(vec2 pixel_coords,
|
||||
float cell_width,
|
||||
float star_radius,
|
||||
float seed,
|
||||
bool twinkle) {
|
||||
// fract() gives you 0.0 to 1.0 for the cell_width
|
||||
// - 0.5 will move the origin from the bottom left to the cetner
|
||||
vec2 cell_coords = fract(pixel_coords / cell_width) - 0.5;
|
||||
// "each cell is now scaled in terms of pixels"
|
||||
cell_coords *= cell_width;
|
||||
|
||||
vec2 cell_id = (floor(pixel_coords / cell_width) + seed) / 100.0; // "(x,y)"
|
||||
vec3 cell_hash_value =
|
||||
hash3(vec3(cell_id, 0.0)); // [-1, 1] - note; "z" is unused right now.
|
||||
|
||||
// Hash gives you -1 to 1; saturate clamps to 0,1. This will effectivly
|
||||
// kill some of the stars (wanted) vs remap giving you a star per-cell
|
||||
float starBrighness = saturate(cell_hash_value.z); // -1,1 -> 0->1
|
||||
|
||||
// Get a star position and
|
||||
vec2 star_position = vec2(0.0);
|
||||
star_position += cell_hash_value.xy * (cell_width * 0.5 - star_radius * 4.0);
|
||||
|
||||
// float distance_to_star = length(cell_coords); // stars in the middle
|
||||
float distance_to_star = length(cell_coords + star_position);
|
||||
|
||||
// better falloff
|
||||
float glow = exp(-2.0 * distance_to_star / star_radius);
|
||||
|
||||
if (twinkle) {
|
||||
// verticle and horizontal flare
|
||||
float noise_sample = noise(vec3(cell_id, frag_info.time * 1.5));
|
||||
float twinkle_size =
|
||||
remap(noise_sample, -1.0, 1.0, 1.0, 0.1) * star_radius * 6.0;
|
||||
|
||||
vec2 abs_distance =
|
||||
abs(cell_coords - star_position); // manhattan distance to cell center.
|
||||
|
||||
// horizontal
|
||||
float twinkleValue = smoothstep(star_radius * 0.25, 0.0, abs_distance.y) *
|
||||
smoothstep(twinkle_size, 0.0, abs_distance.x);
|
||||
// vertical
|
||||
twinkleValue += smoothstep(star_radius * 0.25, 0.0, abs_distance.x) *
|
||||
smoothstep(twinkle_size, 0.0, abs_distance.y);
|
||||
|
||||
glow += twinkleValue;
|
||||
}
|
||||
|
||||
return vec3(glow * starBrighness);
|
||||
}
|
||||
|
||||
vec3 GenerateStars(vec2 pixel_coords) {
|
||||
vec3 stars = vec3(0.0);
|
||||
float size = 4.0;
|
||||
float cell_width = 500.0;
|
||||
for (float i = 0.0; i <= 2.0; i++) {
|
||||
stars += GenerateStarGrid(pixel_coords, cell_width, size,
|
||||
i + frag_info.seed_value, true);
|
||||
size *= 0.5;
|
||||
cell_width *= 0.35;
|
||||
}
|
||||
|
||||
for (float i = 3.0; i <= 5.0; i++) {
|
||||
stars += GenerateStarGrid(pixel_coords, cell_width, size,
|
||||
i + frag_info.seed_value, false);
|
||||
size *= 0.5;
|
||||
cell_width *= 0.35;
|
||||
}
|
||||
return stars;
|
||||
}
|
||||
|
||||
// 2D circle
|
||||
float sdfCircle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float map(vec3 pos) {
|
||||
return fbm6(pos, 0.5, 2.0, 4.0);
|
||||
}
|
||||
|
||||
vec3 calcNormal(vec3 pos, vec3 n) {
|
||||
// if you sample the noise field along each axis, a small amount of distance
|
||||
// away from the position you're interested, you'll get a gradient
|
||||
vec2 e = vec2(0.0001, 0.0);
|
||||
/* -500.0 was added without comment, but it gives bump */
|
||||
return normalize(n + -500.0 * vec3(map(pos + e.xyy) - map(pos - e.xyy),
|
||||
map(pos + e.yxy) - map(pos - e.yxy),
|
||||
map(pos + e.yyx) - map(pos - e.yyx)));
|
||||
}
|
||||
|
||||
mat3 rotateY(float radians) {
|
||||
float s = sin(radians);
|
||||
float c = cos(radians);
|
||||
return mat3( // split
|
||||
c, 0.0, s, // 1
|
||||
0.0, 1.0, 0.0, // 2
|
||||
-s, 0.0, c); // 3
|
||||
}
|
||||
|
||||
vec3 DrawPlanet(vec2 pixel_coords,
|
||||
vec3 color,
|
||||
float planet_size,
|
||||
float atmosphere_thickness,
|
||||
float rotation_speed) {
|
||||
vec3 planet_color = vec3(1.0);
|
||||
|
||||
// Get a nice big 2D circle and the distance to the edge.
|
||||
float d = sdfCircle(pixel_coords, planet_size);
|
||||
|
||||
if (d <= 0.0) {
|
||||
// inside the planet.
|
||||
float x = pixel_coords.x / planet_size;
|
||||
float y = pixel_coords.y / planet_size;
|
||||
|
||||
// surface area of a sphere is x^2 + y^2 + z^2 = 1, so...
|
||||
// z = 1 - x^2 - y^2
|
||||
float z = sqrt(1.0 - x * x - y * y);
|
||||
|
||||
// sping around; right round...
|
||||
mat3 planet_rotation = rotateY(frag_info.time * rotation_speed);
|
||||
|
||||
// veiw space normal;
|
||||
vec3 view_normal = vec3(x, y, z);
|
||||
vec3 worldspace_position = planet_rotation * view_normal;
|
||||
vec3 worldspace_normal = planet_rotation * normalize(worldspace_position);
|
||||
vec3 wsViewDir = planet_rotation * vec3(0.0, 0.0, 1.0);
|
||||
|
||||
vec3 noise_coord = worldspace_position * 2.0;
|
||||
float noise_sample = fbm6(noise_coord, 0.5, 2.0, 4.0);
|
||||
float moistureMap = fbm2(noise_coord * 0.5 + vec3(20.0), 0.5, 2.0, 4.0);
|
||||
|
||||
vec3 shallowWaterColor = vec3(0.01, 0.09, 0.55); // light blue
|
||||
vec3 deepWater = vec3(0.09, 0.26, 0.57);
|
||||
vec3 waterColor =
|
||||
mix(shallowWaterColor, deepWater,
|
||||
smoothstep(0.02 /*deep*/, 0.06 /* shallow */, noise_sample));
|
||||
|
||||
vec3 coast_land = vec3(0.5, 1.0, 0.3);
|
||||
vec3 jungle_land = vec3(0.0, 0.7, 0.0);
|
||||
vec3 land_color =
|
||||
mix(coast_land, jungle_land, smoothstep(0.05, 0.1, noise_sample));
|
||||
|
||||
vec3 sandyColor = vec3(1.0, 1.0, 0.5);
|
||||
land_color =
|
||||
mix(sandyColor, land_color, smoothstep(0.05, 0.1, moistureMap));
|
||||
|
||||
// Put in some mountains and snow...
|
||||
vec3 mountainColor = vec3(0.5);
|
||||
land_color =
|
||||
mix(land_color, mountainColor, smoothstep(0.1, 0.2, noise_sample));
|
||||
|
||||
vec3 snowColor = vec3(1.0);
|
||||
land_color =
|
||||
mix(land_color, snowColor, smoothstep(0.15, 0.3, noise_sample));
|
||||
|
||||
// Take care of the poles...
|
||||
land_color =
|
||||
mix(land_color, vec3(0.9), smoothstep(0.6, 0.9, abs(view_normal.y)));
|
||||
|
||||
planet_color =
|
||||
mix(waterColor, land_color, smoothstep(0.05, 0.06, noise_sample));
|
||||
|
||||
// Lighting
|
||||
// Check out the previous sections on lighting.
|
||||
|
||||
// specularity of water vs land is different.
|
||||
float water_selector = smoothstep(0.05, 0.06, noise_sample);
|
||||
vec2 spec_params = mix(vec2(0.5, 32.0), // land
|
||||
vec2(0.01, 2.0), // sea
|
||||
water_selector);
|
||||
|
||||
vec3 worldspace_light_direction =
|
||||
planet_rotation * normalize(vec3(0.5, 1.0, 0.5));
|
||||
|
||||
// update: make water flat - though from space we should see some waves
|
||||
// (to-do)
|
||||
vec3 worldspace_surface_normal =
|
||||
mix(worldspace_normal, calcNormal(noise_coord, worldspace_normal),
|
||||
water_selector);
|
||||
|
||||
if (frag_info.show_normals > 0.0) {
|
||||
planet_color = worldspace_surface_normal;
|
||||
}
|
||||
float wrap = 0.05;
|
||||
// float dp = max(0.0, dot(worldspace_light_direction,
|
||||
// worldspace_surface_normal)); // dot product nvida surface scattering
|
||||
// trick
|
||||
float dp = max(
|
||||
0.0,
|
||||
(dot(worldspace_light_direction, worldspace_surface_normal) + wrap) /
|
||||
(1.0 + wrap));
|
||||
|
||||
vec3 darkRed = vec3(0.25, 0.0, 0.0);
|
||||
vec3 lightColor = mix(darkRed, vec3(0.75), smoothstep(0.05, 0.5, dp));
|
||||
|
||||
vec3 ambient = vec3(0.002); // lets not have complete darkness
|
||||
vec3 diffuse = lightColor * dp;
|
||||
|
||||
vec3 r = normalize(
|
||||
reflect(-worldspace_light_direction, worldspace_surface_normal));
|
||||
float phongValue = max(0.0, dot(wsViewDir, r));
|
||||
phongValue = pow(phongValue, spec_params.y);
|
||||
|
||||
vec3 specular = vec3(phongValue) * spec_params.x * diffuse;
|
||||
|
||||
vec3 planetShading = planet_color * (diffuse + ambient) + specular;
|
||||
planet_color = planetShading;
|
||||
|
||||
// Fresnel for atmosphere
|
||||
float fresnel = smoothstep(1.0, 0.1, view_normal.z); // z == from camera.
|
||||
// "blue halo goes around the dark side of the planet
|
||||
// fresnel = pow(fresnel, 8.0);
|
||||
fresnel = pow(fresnel, 8.0) * dp;
|
||||
planet_color = mix(planet_color, vec3(0.0, 0.5, 1.0), fresnel);
|
||||
|
||||
if (frag_info.show_noise > 0.0) {
|
||||
planet_color = vec3(noise_sample);
|
||||
}
|
||||
}
|
||||
// (color -> planet_color) when "d" is between 0 and -1 (inside the circle)
|
||||
color = mix(color, planet_color, smoothstep(0.0, -1.0, d));
|
||||
|
||||
// Atmospheric glow
|
||||
// 40 pixels outside the planet
|
||||
if (d < atmosphere_thickness && d >= -1.0) {
|
||||
// color = vec3(1.0); // draw the halo
|
||||
float planetSizeAtmos = planet_size + atmosphere_thickness;
|
||||
mat3 planet_rotation = rotateY(frag_info.time * rotation_speed);
|
||||
|
||||
float x = pixel_coords.x / planetSizeAtmos;
|
||||
float y = pixel_coords.y / planetSizeAtmos;
|
||||
float z = sqrt(1.0 - x * x - y * y);
|
||||
vec3 normal = planet_rotation * vec3(x, y, z);
|
||||
|
||||
float lighting = dot(normal, normalize(vec3(0.5, 1.0, 0.5)));
|
||||
lighting =
|
||||
smoothstep(-0.15, 1.0, lighting); // same as above; just no wrap.
|
||||
|
||||
vec3 glow_color =
|
||||
vec3(0.05, 0.3, 0.9) * exp(-0.01 * d * d) * lighting * 0.75;
|
||||
color += glow_color;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 vUvs = (gl_FragCoord.xy - 0.5) / frag_info.resolution;
|
||||
vUvs.y = 1.0 - vUvs.y; // flip flutter's upside down.
|
||||
vec2 pixel_coords = (vUvs - 0.5) * frag_info.resolution;
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
color = GenerateStars(pixel_coords);
|
||||
color = DrawPlanet(pixel_coords, color, frag_info.planet_size,
|
||||
frag_info.planet_size * 0.1, frag_info.speed);
|
||||
|
||||
frag_color = vec4(pow(color, vec3(1.0 / 2.2)), 1.0);
|
||||
}
|
||||
16
engine/src/flutter/impeller/fixtures/planet.vert
Normal file
16
engine/src/flutter/impeller/fixtures/planet.vert
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
uniform FrameInfo {
|
||||
mat4 mvp;
|
||||
}
|
||||
frame_info;
|
||||
|
||||
in vec2 vertex_position;
|
||||
out vec2 v_screen_position;
|
||||
|
||||
void main() {
|
||||
v_screen_position = vertex_position;
|
||||
gl_Position = frame_info.mvp * vec4(vertex_position, 0.0, 1.0);
|
||||
}
|
||||
@ -24,6 +24,8 @@
|
||||
#include "impeller/fixtures/instanced_draw.vert.h"
|
||||
#include "impeller/fixtures/mipmaps.frag.h"
|
||||
#include "impeller/fixtures/mipmaps.vert.h"
|
||||
#include "impeller/fixtures/planet.frag.h"
|
||||
#include "impeller/fixtures/planet.vert.h"
|
||||
#include "impeller/fixtures/sepia.frag.h"
|
||||
#include "impeller/fixtures/sepia.vert.h"
|
||||
#include "impeller/fixtures/swizzle.frag.h"
|
||||
@ -926,6 +928,72 @@ TEST_P(RendererTest, TheImpeller) {
|
||||
OpenPlaygroundHere(callback);
|
||||
}
|
||||
|
||||
TEST_P(RendererTest, Planet) {
|
||||
using VS = PlanetVertexShader;
|
||||
using FS = PlanetFragmentShader;
|
||||
|
||||
auto context = GetContext();
|
||||
auto pipeline_descriptor =
|
||||
PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
|
||||
ASSERT_TRUE(pipeline_descriptor.has_value());
|
||||
pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
|
||||
pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
|
||||
auto pipeline =
|
||||
context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
|
||||
ASSERT_TRUE(pipeline && pipeline->IsValid());
|
||||
|
||||
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
|
||||
|
||||
SinglePassCallback callback = [&](RenderPass& pass) {
|
||||
static Scalar speed = 0.1;
|
||||
static Scalar planet_size = 550.0;
|
||||
static bool show_normals = false;
|
||||
static bool show_noise = false;
|
||||
static Scalar seed_value = 42.0;
|
||||
|
||||
auto size = pass.GetRenderTargetSize();
|
||||
|
||||
ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
|
||||
ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
|
||||
ImGui::Checkbox("Show Normals", &show_normals);
|
||||
ImGui::Checkbox("Show Noise", &show_noise);
|
||||
ImGui::InputFloat("Seed Value", &seed_value);
|
||||
ImGui::End();
|
||||
|
||||
pass.SetPipeline(pipeline);
|
||||
pass.SetCommandLabel("Planet scene");
|
||||
VertexBufferBuilder<VS::PerVertexData> builder;
|
||||
builder.AddVertices({{Point()},
|
||||
{Point(0, size.height)},
|
||||
{Point(size.width, 0)},
|
||||
{Point(size.width, 0)},
|
||||
{Point(0, size.height)},
|
||||
{Point(size.width, size.height)}});
|
||||
pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
|
||||
|
||||
VS::FrameInfo frame_info;
|
||||
EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
|
||||
frame_info.mvp = pass.GetOrthographicTransform();
|
||||
VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
|
||||
|
||||
FS::FragInfo fs_uniform;
|
||||
fs_uniform.resolution = Point(size);
|
||||
fs_uniform.time = GetSecondsElapsed();
|
||||
fs_uniform.speed = speed;
|
||||
fs_uniform.planet_size = planet_size;
|
||||
fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
|
||||
fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
|
||||
fs_uniform.seed_value = seed_value;
|
||||
FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
|
||||
|
||||
pass.Draw().ok();
|
||||
host_buffer->Reset();
|
||||
return true;
|
||||
};
|
||||
OpenPlaygroundHere(callback);
|
||||
}
|
||||
|
||||
TEST_P(RendererTest, ArrayUniforms) {
|
||||
using VS = ArrayVertexShader;
|
||||
using FS = ArrayFragmentShader;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user