feat(draw): mitigate light leaks near corners by modifying AO texture coordinates in VS

This only mitigates the light leaks on terrain surfaces. It remains to
be seen how to do the same on other surfaces.
This commit is contained in:
yvt 2021-02-10 00:39:47 +09:00
parent 0d53d6fcc8
commit 533e1028c1
5 changed files with 58 additions and 19 deletions

View File

@ -71,7 +71,6 @@ void main() {
vec3 fixedPosition = chunkPosition;
fixedPosition += fixedPositionAttribute * 0.5;
fixedPosition += normalAttribute * 0.1;
vec3 normal = normalAttribute;
vec3 shadowVertexPos = vertexPos.xyz;

View File

@ -80,7 +80,6 @@ void main() {
vec3 fixedPosition = chunkPosition;
fixedPosition += fixedPositionAttribute * 0.5;
fixedPosition += normalAttribute * 0.1;
vec3 normal = normalAttribute;
vec3 shadowVertexPos = vertexPos.xyz;

View File

@ -1,21 +1,21 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
@ -23,7 +23,7 @@
void PrepareForShadow_Map(vec3 vertexCoord, vec3 normal) ;
void PrepareForShadow_Model(vec3 vertexCoord, vec3 normal);
void PrepareForRadiosity_Map(vec3 vertexCoord, vec3 normal);
void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 normal);
void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 centerCoord, vec3 normal);
void PrepareForShadow(vec3 vertexCoord, vec3 normal) {
PrepareForShadow_Map(vertexCoord, normal);
@ -31,9 +31,9 @@ void PrepareForShadow(vec3 vertexCoord, vec3 normal) {
PrepareForRadiosity_Map(vertexCoord, normal);
}
// map uses specialized shadow coordinate calculation to avoid glitch
void PrepareForShadowForMap(vec3 vertexCoord, vec3 fixedVertexCoord, vec3 normal) {
PrepareForShadow_Map(fixedVertexCoord, normal);
void PrepareForShadowForMap(vec3 vertexCoord, vec3 centerCoord, vec3 normal) {
// map uses specialized shadow coordinate calculation to avoid glitch
PrepareForShadow_Map(centerCoord + normal * 0.1, normal);
PrepareForShadow_Model(vertexCoord, normal);
PrepareForRadiosityForMap_Map(vertexCoord, normal);
PrepareForRadiosityForMap_Map(vertexCoord, centerCoord, normal);
}

View File

@ -59,7 +59,7 @@ vec3 Radiosity_Map(float detailAmbientOcclusion, float ssao) {
// ambient occlusion
vec2 ambTexVal = texture3D(ambientShadowTexture, ambientShadowTextureCoord).xy;
float amb = ambTexVal.x / (ambTexVal.y + 1.0e-12);
float amb = ambTexVal.x / max(ambTexVal.y, 0.25);
amb = max(amb, 0.); // for some reason, mainTexture value becomes negative
// mix ambient occlusion values generated by two different methods somehow

View File

@ -1,25 +1,27 @@
/*
Copyright (c) 2013 yvt
This file is part of OpenSpades.
OpenSpades is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenSpades is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
/**** CPU RADIOSITY (FASTER?) *****/
uniform sampler3D ambientShadowTexture;
varying vec3 radiosityTextureCoord;
varying vec3 ambientShadowTextureCoord;
varying vec3 normalVarying;
@ -31,9 +33,48 @@ void PrepareForRadiosity_Map(vec3 vertexCoord, vec3 normal) {
normalVarying = normal;
}
void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 normal) {
void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 centerCoord, vec3 normal) {
radiosityTextureCoord = (vertexCoord + vec3(0., 0., 0.)) / vec3(512., 512., 64.);
ambientShadowTextureCoord = (vertexCoord + vec3(0., 0., 1.) + normal * 0.5) / vec3(512., 512., 65.);
vec3 centerAST = (centerCoord + vec3(0., 0., 1.) + normal * 0.5) / vec3(512., 512., 65.);
vec3 rel = vertexCoord - centerCoord;
vec3 relAST = rel * 2.0 / vec3(512., 512., 65.);
// Detect the following pattern:
//
// +-----+-----+
// |#####| |
// |#####| |
// |#####| |
// +-----+-----+
// | V|#####|
// | C |#####|
// | |#####|
// +-----+-----+
//
// C = centerCoord, V = vertexCoord, # = covered by a solid voxel
//
float weightSum;
if (normal.x != 0.0) {
weightSum = texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, 0.0)).y +
texture3D(ambientShadowTexture, centerAST + vec3(0.0, 0.0, relAST.z)).y -
texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, relAST.z)).y;
} else if (normal.y != 0.0) {
weightSum = texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, 0.0)).y +
texture3D(ambientShadowTexture, centerAST + vec3(0.0, 0.0, relAST.z)).y -
texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, relAST.z)).y;
} else {
weightSum = texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, 0.0)).y +
texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, 0.0)).y -
texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, relAST.y, 0.0)).y;
}
// Hide the light leaks by corners by modifying the AO texture coordinates
if (weightSum < -0.5) {
radiosityTextureCoord -= rel / vec3(512., 512., 64.);
ambientShadowTextureCoord = centerAST;
}
normalVarying = normal;
}