Try to fix the lighting

This commit is contained in:
schmelczerandras 2020-07-25 14:20:11 +02:00
parent affb1b4f4f
commit e6782a9a98
7 changed files with 51 additions and 59 deletions

View file

@ -1,5 +1,5 @@
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
import { vec2 } from 'gl-matrix';
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
export abstract class FrameBuffer {
public renderScale = 1;
@ -13,11 +13,11 @@ export abstract class FrameBuffer {
protected programs: Array<FragmentShaderOnlyProgram>
) {}
public render(uniforms: any, input?: WebGLTexture) {
public render(uniforms: any, colorInput?: WebGLTexture) {
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer);
if (input !== null) {
this.gl.bindTexture(this.gl.TEXTURE_2D, input);
if (colorInput !== null) {
this.gl.bindTexture(this.gl.TEXTURE_2D, colorInput);
}
this.gl.viewport(0, 0, this.size.x, this.size.y);

View file

@ -19,7 +19,7 @@ export class IntermediateFrameBuffer extends FrameBuffer {
this.setSize();
}
public get texture(): WebGLTexture {
public get colorTexture(): WebGLTexture {
return this.frameTexture;
}
@ -43,7 +43,11 @@ export class IntermediateFrameBuffer extends FrameBuffer {
private configureTexture() {
this.gl.bindTexture(this.gl.TEXTURE_2D, this.frameTexture);
this.gl.texParameteri(
this.gl.TEXTURE_2D,
this.gl.TEXTURE_MAG_FILTER,
this.gl.NEAREST
);
this.gl.texParameteri(
this.gl.TEXTURE_2D,
this.gl.TEXTURE_MIN_FILTER,

View file

@ -1,4 +1,3 @@
import { WebGl2Renderer } from '../webgl2-renderer';
import { InfoText } from '../../objects/types/info-text';
// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/

View file

@ -34,7 +34,7 @@ export class WebGl2Renderer implements Drawer {
new FragmentShaderOnlyProgram(this.gl, ...shaderSources[1]),
]);
this.distanceFieldFrameBuffer.renderScale = 1;
this.distanceFieldFrameBuffer.renderScale = 0.5;
this.lightingFrameBuffer.renderScale = 1;
try {
@ -55,7 +55,7 @@ export class WebGl2Renderer implements Drawer {
this.distanceFieldFrameBuffer.render(this.uniforms);
this.lightingFrameBuffer.render(
this.uniforms,
this.distanceFieldFrameBuffer.texture
this.distanceFieldFrameBuffer.colorTexture
);
this.stopwatch?.stop();
@ -96,6 +96,7 @@ export class WebGl2Renderer implements Drawer {
worldToDistanceUV,
cursorPosition,
ndcToWorld,
viewBoxSize: this.viewBox.size,
});
}

View file

@ -1,6 +1,6 @@
#version 300 es
precision mediump float;
precision lowp float;
#define INFINITY 10000.0
@ -19,7 +19,7 @@ float lineDistance(
) {
vec2 pa = target - start, ba = end - start;
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
return distance(pa, ba * h) - mix(radiusFrom, radiusTo, smoothstep(0.0, 1.0, h));
return distance(pa, ba * h) - mix(radiusFrom, radiusTo, h);
}
float getDistance(in vec2 target) {
@ -36,18 +36,15 @@ float getDistance(in vec2 target) {
return -minDistance;
}
vec3 branchlessTernary(float condition, vec3 ifPositive, vec3 ifNegative) {
float isPositive = (sign(condition) + 1.0) * 0.5;
return ifPositive * abs(isPositive) + ifNegative * (1.0 - isPositive);
}
in vec2 worldCoordinates;
out vec4 fragmentColor;
void main() {
float distance = getDistance(worldCoordinates);
const vec3 caveColor = vec3(0.0);
const vec3 airColor = vec3(1.0);
fragmentColor = vec4(
branchlessTernary(distance, vec3(1.0), vec3(0.0, 1.0, 0.5)),
distance / 128.0 + 0.5
mix(caveColor, airColor, distance),
distance / 32.0
);
}

View file

@ -4,21 +4,24 @@ precision mediump float;
#define INFINITY 10000.0
#define LIGHT_COUNT 3
#define LIGHT_PENETRATION 1000.0
#define ANTIALIASING_RADIUS 1.0
#define AMBIENT_LIGHT vec3(0.075)
#define AMBIENT_LIGHT vec3(0.05)
#define LIGHT_DROP 800.0
#define SHADOW_BIAS 0.01
struct Light {
vec2 center;
float radius;
vec3 value;
};
}[LIGHT_COUNT] lights;
uniform sampler2D distanceTexture;
uniform mat3 worldToDistanceUV;
uniform vec2 cursorPosition;
uniform vec2 viewBoxSize;
Light lights[LIGHT_COUNT];
float square(in float a) {
return a*a;
}
float getDistance(in vec2 target, out vec3 color) {
// should avoid this matrix multiplication
@ -26,7 +29,7 @@ float getDistance(in vec2 target, out vec3 color) {
vec4 values = texture(distanceTexture, targetUV);
color = values.rgb;
return (values.a - 0.5) * 128.0;
return values.w * 32.0;
}
float getDistance(in vec2 target) {
@ -34,81 +37,67 @@ float getDistance(in vec2 target) {
vec2 targetUV = (vec3(target.xy, 1.0) * worldToDistanceUV).xy;
vec4 values = texture(distanceTexture, targetUV);
return (values.a - 0.5) * 128.0;
return values.w * 32.0;
}
void createWorld() {
lights[0] = Light(vec2(600, 700), 40.5, normalize(vec3(1.0)) * 2.0);
lights[1] = Light(vec2(100.0, 350.0), 52.5, normalize(vec3(2.0, 1.0, 0.25)) * 0.5);
lights[2] = Light(cursorPosition, 52.5, normalize(vec3(0.63, 0.25, 0.5)) * 1.0);
//lights[0] = Light(vec2(600, 700), 40.5, normalize(vec3(1.0)) * 2.0);
//lights[1] = Light(vec2(100.0, 350.0), 52.5, normalize(vec3(2.0, 1.0, 0.25)) * 0.5);
lights[2] = Light(cursorPosition, 52.5, normalize(vec3(0.93, 0.25, 0.5)) * 1.0);
}
float getFractionOfLightArriving(
in vec2 target,
in vec2 direction,
in float startingDistance,
in float lightDistance,
in float lightRadius
) {
float q = INFINITY;
float rayLength = 0.0;
float movingAverageMeanDistance = startingDistance;
for (int j = 0; j < 64; j++) {
float minDistance = getDistance(target + direction * rayLength);
q = min(q, minDistance / rayLength);
rayLength = min(lightDistance, rayLength + max(1.0, minDistance));
movingAverageMeanDistance = movingAverageMeanDistance / 2.0 + minDistance / 2.0;
q = min(q, movingAverageMeanDistance / rayLength);
rayLength = min(lightDistance, rayLength + max(0.0001, minDistance));
}
return smoothstep(0.0, 1.0, q * (lightDistance + lightRadius) / lightRadius);
return smoothstep(0.0, 1.0, (q - SHADOW_BIAS) * (lightDistance + lightRadius) / lightRadius);
}
float square(in float a) {
return a*a;
}
vec3 getPixelColor(in vec2 worldCoordinates) {
vec3 result = vec3(0.0);
vec3 getPixelColor(in vec2 worldCoordinates, in vec2 uvCoordinates) {
vec3 colorAtPosition;
float startingDistance = getDistance(worldCoordinates, colorAtPosition);
float fractionOfLightPenetrating = smoothstep(0.0, 1.0,
1.0 - (min(0.0, startingDistance) / LIGHT_PENETRATION)
);
vec3 result = colorAtPosition * AMBIENT_LIGHT;
for (int i = 0; i < LIGHT_COUNT; i++) {
Light light = lights[i];
float lightDistance = distance(worldCoordinates, light.center) - light.radius;
vec3 lightColorAtPosition = light.value / square(max(0.0, lightDistance / 200.0) + 1.0);
vec3 lightColorAtPosition = light.value / square(max(0.0, lightDistance / LIGHT_DROP) + 1.0);
vec2 lightDirection = normalize(light.center - worldCoordinates);
float fractionOfLightArriving = getFractionOfLightArriving(
worldCoordinates, lightDirection, max(0.0, lightDistance), light.radius
worldCoordinates, lightDirection, startingDistance,
max(0.0, lightDistance), light.radius
);
result += colorAtPosition * lightColorAtPosition * fractionOfLightArriving * fractionOfLightPenetrating;
result += colorAtPosition * lightColorAtPosition * fractionOfLightArriving;
}
// Add ambient light
result += colorAtPosition * AMBIENT_LIGHT;
return clamp(result, 0.0, 1.0);
}
/*vec3 getPixelColorAntialiased(in vec2 position) {
Circle nearest;
float minDistance = getDistance(position, nearest);
if (0.0 < minDistance && minDistance < 1.0) {
vec2 closerDirection = normalize(nearest.center - position);
return mix(getPixelColor(position + closerDirection, true, nearest.color), getPixelColor(position - closerDirection, false, nearest.color), minDistance);
}
return getPixelColor(position, minDistance < 0.0, minDistance < 0.0 ? nearest.color : vec3(1.0));
}*/
in vec2 worldCoordinates;
in vec2 uvCoordinates;
out vec4 fragmentColor;
void main() {
createWorld();
// log2 for compenstaion?
fragmentColor = vec4(getPixelColor(worldCoordinates), 1.0);
fragmentColor = vec4(getPixelColor(worldCoordinates, uvCoordinates), 1.0);
}

View file

@ -3,8 +3,10 @@
uniform mat3 ndcToWorld;
in vec4 a_position;
out vec2 worldCoordinates;
out vec2 uvCoordinates;
void main() {
worldCoordinates = (vec3(a_position.xy, 1.0) * ndcToWorld).xy;
uvCoordinates = ((a_position.xy + vec2(1.0)) / 2.0).xy;
gl_Position = a_position;
}