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

View file

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

View file

@ -1,4 +1,3 @@
import { WebGl2Renderer } from '../webgl2-renderer';
import { InfoText } from '../../objects/types/info-text'; import { InfoText } from '../../objects/types/info-text';
// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/ // 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]), new FragmentShaderOnlyProgram(this.gl, ...shaderSources[1]),
]); ]);
this.distanceFieldFrameBuffer.renderScale = 1; this.distanceFieldFrameBuffer.renderScale = 0.5;
this.lightingFrameBuffer.renderScale = 1; this.lightingFrameBuffer.renderScale = 1;
try { try {
@ -55,7 +55,7 @@ export class WebGl2Renderer implements Drawer {
this.distanceFieldFrameBuffer.render(this.uniforms); this.distanceFieldFrameBuffer.render(this.uniforms);
this.lightingFrameBuffer.render( this.lightingFrameBuffer.render(
this.uniforms, this.uniforms,
this.distanceFieldFrameBuffer.texture this.distanceFieldFrameBuffer.colorTexture
); );
this.stopwatch?.stop(); this.stopwatch?.stop();
@ -96,6 +96,7 @@ export class WebGl2Renderer implements Drawer {
worldToDistanceUV, worldToDistanceUV,
cursorPosition, cursorPosition,
ndcToWorld, ndcToWorld,
viewBoxSize: this.viewBox.size,
}); });
} }

View file

@ -1,6 +1,6 @@
#version 300 es #version 300 es
precision mediump float; precision lowp float;
#define INFINITY 10000.0 #define INFINITY 10000.0
@ -19,7 +19,7 @@ float lineDistance(
) { ) {
vec2 pa = target - start, ba = end - start; vec2 pa = target - start, ba = end - start;
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); 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) { float getDistance(in vec2 target) {
@ -36,18 +36,15 @@ float getDistance(in vec2 target) {
return -minDistance; 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; in vec2 worldCoordinates;
out vec4 fragmentColor; out vec4 fragmentColor;
void main() { void main() {
float distance = getDistance(worldCoordinates); float distance = getDistance(worldCoordinates);
const vec3 caveColor = vec3(0.0);
const vec3 airColor = vec3(1.0);
fragmentColor = vec4( fragmentColor = vec4(
branchlessTernary(distance, vec3(1.0), vec3(0.0, 1.0, 0.5)), mix(caveColor, airColor, distance),
distance / 128.0 + 0.5 distance / 32.0
); );
} }

View file

@ -4,21 +4,24 @@ precision mediump float;
#define INFINITY 10000.0 #define INFINITY 10000.0
#define LIGHT_COUNT 3 #define LIGHT_COUNT 3
#define LIGHT_PENETRATION 1000.0 #define AMBIENT_LIGHT vec3(0.05)
#define ANTIALIASING_RADIUS 1.0 #define LIGHT_DROP 800.0
#define AMBIENT_LIGHT vec3(0.075) #define SHADOW_BIAS 0.01
struct Light { struct Light {
vec2 center; vec2 center;
float radius; float radius;
vec3 value; vec3 value;
}; }[LIGHT_COUNT] lights;
uniform sampler2D distanceTexture; uniform sampler2D distanceTexture;
uniform mat3 worldToDistanceUV; uniform mat3 worldToDistanceUV;
uniform vec2 cursorPosition; 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) { float getDistance(in vec2 target, out vec3 color) {
// should avoid this matrix multiplication // should avoid this matrix multiplication
@ -26,7 +29,7 @@ float getDistance(in vec2 target, out vec3 color) {
vec4 values = texture(distanceTexture, targetUV); vec4 values = texture(distanceTexture, targetUV);
color = values.rgb; color = values.rgb;
return (values.a - 0.5) * 128.0; return values.w * 32.0;
} }
float getDistance(in vec2 target) { float getDistance(in vec2 target) {
@ -34,81 +37,67 @@ float getDistance(in vec2 target) {
vec2 targetUV = (vec3(target.xy, 1.0) * worldToDistanceUV).xy; vec2 targetUV = (vec3(target.xy, 1.0) * worldToDistanceUV).xy;
vec4 values = texture(distanceTexture, targetUV); vec4 values = texture(distanceTexture, targetUV);
return (values.a - 0.5) * 128.0; return values.w * 32.0;
} }
void createWorld() { void createWorld() {
lights[0] = Light(vec2(600, 700), 40.5, normalize(vec3(1.0)) * 2.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[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[2] = Light(cursorPosition, 52.5, normalize(vec3(0.93, 0.25, 0.5)) * 1.0);
} }
float getFractionOfLightArriving( float getFractionOfLightArriving(
in vec2 target, in vec2 target,
in vec2 direction, in vec2 direction,
in float startingDistance,
in float lightDistance, in float lightDistance,
in float lightRadius in float lightRadius
) { ) {
float q = INFINITY; float q = INFINITY;
float rayLength = 0.0; float rayLength = 0.0;
float movingAverageMeanDistance = startingDistance;
for (int j = 0; j < 64; j++) { for (int j = 0; j < 64; j++) {
float minDistance = getDistance(target + direction * rayLength); float minDistance = getDistance(target + direction * rayLength);
q = min(q, minDistance / rayLength); movingAverageMeanDistance = movingAverageMeanDistance / 2.0 + minDistance / 2.0;
rayLength = min(lightDistance, rayLength + max(1.0, minDistance)); 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) { vec3 getPixelColor(in vec2 worldCoordinates, in vec2 uvCoordinates) {
return a*a;
}
vec3 getPixelColor(in vec2 worldCoordinates) {
vec3 result = vec3(0.0);
vec3 colorAtPosition; vec3 colorAtPosition;
float startingDistance = getDistance(worldCoordinates, 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++) { for (int i = 0; i < LIGHT_COUNT; i++) {
Light light = lights[i]; Light light = lights[i];
float lightDistance = distance(worldCoordinates, light.center) - light.radius; 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); vec2 lightDirection = normalize(light.center - worldCoordinates);
float fractionOfLightArriving = getFractionOfLightArriving( 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); 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 worldCoordinates;
in vec2 uvCoordinates;
out vec4 fragmentColor; out vec4 fragmentColor;
void main() { void main() {
createWorld(); 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; uniform mat3 ndcToWorld;
in vec4 a_position; in vec4 a_position;
out vec2 worldCoordinates; out vec2 worldCoordinates;
out vec2 uvCoordinates;
void main() { void main() {
worldCoordinates = (vec3(a_position.xy, 1.0) * ndcToWorld).xy; worldCoordinates = (vec3(a_position.xy, 1.0) * ndcToWorld).xy;
uvCoordinates = ((a_position.xy + vec2(1.0)) / 2.0).xy;
gl_Position = a_position; gl_Position = a_position;
} }