-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Terrain mipmapping #172
Labels
Comments
(Buggy?) code to generate the mipmaps manually: function mipmap(img, scale = false) {
const imageCanvas = document.createElement( "canvas" )
const context = imageCanvas.getContext( "2d" )
if (!scale) {
imageCanvas.width = imageCanvas.height = img.width
context.drawImage(img, 0, 0)
} else {
imageCanvas.width = imageCanvas.height = img.width / 2
const inData = img.getContext('2d').getImageData(0, 0, img.width, img.height).data
const out = context.getImageData(0, 0, imageCanvas.width, imageCanvas.height)
for (let i=0 ; i<imageCanvas.height; i++) {
for (let j=0 ; j<imageCanvas.width; j++) {
let in0 = (i*2 * imageCanvas.width + j*2) * 4
let in1 = in0 + 4
let in2 = in0 + img.width
let in3 = in0 + img.width + 4
let a0 = inData[in0+3]
let a1 = inData[in1+3]
let a2 = inData[in2+3]
let a3 = inData[in3+3]
let r = (inData[in0] * a0 + inData[in1] * a1 + inData[in2] * a2 + inData[in3] * a3) / 1020
let g = (inData[in0+1] * a0 + inData[in1+1] * a1 + inData[in2+1] * a2 + inData[in3+1] * a3) / 1020
let b = (inData[in0+2] * a0 + inData[in1+2] * a1 + inData[in2+2] * a2 + inData[in3+2] * a3) / 1020
let a = Math.max(Math.max(a0, a1), Math.max(a2, a3))
let outIdx = (i * imageCanvas.width + j) * 4
out.data[outIdx++] = r
out.data[outIdx++] = g
out.data[outIdx++] = b
out.data[outIdx++] = a
}
}
context.putImageData(out, 0, 0)
}
return imageCanvas
}
function loadTextureMipmap(path, cb) {
let img = new Image()
img.onload = () => {
const canvas = mipmap(img)
const texture = new THREE.CanvasTexture(canvas)
texture.mipmaps[0] = canvas
let i=0
while (texture.mipmaps[i].width != 1) {
i++
texture.mipmaps[i] = mipmap(texture.mipmaps[i-1], true)
}
texture.wrapS = THREE.ClampToEdgeWrapping
texture.wrapT = THREE.ClampToEdgeWrapping
texture.magFilter = THREE.NearestFilter
texture.minFilter = THREE.NearestMipmapNearestFilter
texture.flipY = false
cb(texture)
}
img.src = path
} |
Debugged mipmap generator: function mipmap(img, scale = false) {
const imageCanvas = document.createElement( "canvas" )
const context = imageCanvas.getContext( "2d" )
if (!scale) {
imageCanvas.width = imageCanvas.height = img.width
context.drawImage(img, 0, 0)
} else {
imageCanvas.width = imageCanvas.height = img.width / 2
const inData = img.getContext('2d').getImageData(0, 0, img.width, img.height).data
const out = context.getImageData(0, 0, imageCanvas.width, imageCanvas.height)
for (let i=0 ; i<imageCanvas.height; i++) {
for (let j=0 ; j<imageCanvas.width; j++) {
let in0 = (i*2 * img.width + j*2) * 4
let in1 = in0 + 4
let in2 = in0 + img.width * 4
let in3 = in0 + img.width * 4 + 4
let a0 = inData[in0 + 3]
let a1 = inData[in1 + 3]
let a2 = inData[in2 + 3]
let a3 = inData[in3 + 3]
let r = g = b = a = 0
let div = 0
if (a0 > 0) {
r += inData[in0]
g += inData[in0 + 1]
b += inData[in0 + 2]
div++
}
if (a1 > 0) {
r += inData[in1]
g += inData[in1 + 1]
b += inData[in1 + 2]
div++
}
if (a2 > 0) {
r += inData[in2]
g += inData[in2 + 1]
b += inData[in2 + 2]
div++
}
if (a3 > 0) {
r += inData[in3]
g += inData[in3 + 1]
b += inData[in3 + 2]
div++
}
if (div > 0) {
r /= div
g /= div
b /= div
}
a = Math.max(Math.max(a0, a1), Math.max(a2, a3))
let outIdx = (i * imageCanvas.width + j) * 4
out.data[outIdx++] = r
out.data[outIdx++] = g
out.data[outIdx++] = b
out.data[outIdx++] = a
}
}
context.putImageData(out, 0, 0)
}
return imageCanvas
}
function loadTextureMipmap(path, cb) {
let img = new Image()
img.onload = () => {
const canvas = mipmap(img)
const texture = new THREE.CanvasTexture(canvas)
texture.mipmaps[0] = canvas
let i=0
while (texture.mipmaps[i].width != 1) {
i++
texture.mipmaps[i] = mipmap(texture.mipmaps[i-1], true)
}
texture.wrapS = THREE.ClampToEdgeWrapping
texture.wrapT = THREE.ClampToEdgeWrapping
texture.magFilter = THREE.NearestFilter
texture.minFilter = THREE.NearestMipmapNearestFilter
texture.flipY = false
cb(texture)
}
img.src = path
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add mipmapping to remove moiré patterns, especially visible in VR but also when moving the camera.
This is not a trivial issue. Setting the minFilter of the texture to
THREE.NearestMipmapNearestFilter
solve the moiré issue but handle very badly transparent blocks and cause issue with the alpha testing.A correct solution would be to generate the mipmaps manually and use a better algorithm to interpolate the alpha (max neighbor?). I tried to do that but it wasn't very concluant, may revisit this solution in the future.
An other solution could be to generate a binary alphaMap that doesnt have the mipmap and use the mipmap on the texture.
The text was updated successfully, but these errors were encountered: