2017-05-14 3 views
1

J'essaye de comprendre l'approche correcte pour rendre à un niveau spécifique de mipmap de texture.Rendu au niveau de mipmap de texture

Dans l'exemple ci-dessous, je tente de rendre la couleur cyan au niveau de mipmap 1 de texture. Si je change le niveau de 1 à 0 dans l'appel framebufferTexture2D, la toile affiche cyan comme prévu. Cependant, je ne comprends pas pourquoi seul le niveau 0 fonctionne ici, car les niveaux non-zéro sont pris en charge dans la spécification WebGL 2/OpenGL ES 3.

J'ai aussi essayé de niveau 0 détachant explicitement (la liaison à null) et diverses autres combinaisons (à savoir l'aide texImage2D au lieu de texStorage2D), mais aucune des combinaisons semblent rendre au niveau de mipmap.

const 
 
    canvas = document.createElement('canvas'), 
 
    gl = canvas.getContext('webgl2'), 
 
    triangle = new Float32Array([ 0, 0, 2, 0, 0, 2 ]); 
 
    texture = gl.createTexture(), 
 
    framebuffer = gl.createFramebuffer(), 
 
    size = 100, 
 
    vertex = createShader(gl.VERTEX_SHADER, `#version 300 es 
 
    precision mediump float; 
 
    uniform sampler2D sampler; 
 
    layout(location = 0) in vec2 position; 
 
    out vec4 color; 
 
    void main() { 
 
     color = textureLod(sampler, position, 0.5); 
 
     gl_Position = vec4(position * 2. - 1., 0, 1); 
 
    }` 
 
), 
 
    fragment = createShader(gl.FRAGMENT_SHADER, `#version 300 es 
 
    precision mediump float; 
 
    in vec4 color; 
 
    out vec4 fragColor; 
 
    void main() { 
 
     fragColor = color; 
 
    }` 
 
), 
 
    program = gl.createProgram(); 
 

 
canvas.width = canvas.height = size; 
 
document.body.appendChild(canvas); 
 

 
gl.viewport(0, 0, size, size); 
 
gl.attachShader(program, vertex); 
 
gl.attachShader(program, fragment); 
 
gl.linkProgram(program); 
 
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { 
 
    console.error('program'); 
 
} 
 
gl.useProgram(program); 
 

 
// Create a big triangle 
 
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); 
 
gl.bufferData(gl.ARRAY_BUFFER, triangle, gl.STATIC_DRAW); 
 
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); 
 
gl.enableVertexAttribArray(0); 
 

 
// Create a texture with mipmap levels 0 (base) and 1 
 
gl.bindTexture(gl.TEXTURE_2D, texture); 
 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
 
gl.texStorage2D(gl.TEXTURE_2D, 2, gl.RGB8, 2, 2); 
 

 
// Setup framebuffer to render to texture level 1, clear to cyan 
 
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); 
 
gl.framebufferTexture2D(
 
    gl.FRAMEBUFFER, 
 
    gl.COLOR_ATTACHMENT0, 
 
    gl.TEXTURE_2D, 
 
    texture, 
 
    1 // Switching this to `0` will work fine 
 
); 
 
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 
 
if (status !== gl.FRAMEBUFFER_COMPLETE) { 
 
    console.error(status); 
 
} 
 
gl.clearColor(0, 1, 1, 1); 
 
gl.clear(gl.COLOR_BUFFER_BIT); 
 

 
// Detach framebuffer, clear to red 
 
gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
gl.clearColor(1, 0, 0, 1); 
 
gl.clear(gl.COLOR_BUFFER_BIT); 
 

 
// Draw the triangle 
 
gl.drawArrays(gl.TRIANGLES, 0, 3); 
 

 
// Some utility functions to cleanup the above code 
 
function createShader(type, source) { 
 
    const shader = gl.createShader(type); 
 
    gl.shaderSource(shader, source); 
 
    gl.compileShader(shader); 
 
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 
 
    console.log(gl.getShaderInfoLog(shader)); 
 
    } 
 
    return shader; 
 
}

Je pense que je fais quelque chose de mal dans la configuration, mais je ne l'ai pas pu trouver de nombreux exemples.

Répondre

1

Ne vous voulez soit

color = textureLod(sampler, position, 0.0); // lod 0 

ou

color = textureLod(sampler, position, 1.0); // lod 1 

?

Le code n'a pas défini le filtrage de manière à pouvoir accéder aux autres lods.

Il les avait mis à gl.NEAREST ce qui signifie que jamais utiliser lod 0.

const canvas = document.createElement('canvas'); 
 
const gl = canvas.getContext('webgl2'); 
 
const triangle = new Float32Array([0, -1, 1, -1, 1, 1]); 
 
const texture = gl.createTexture(); 
 
const framebuffers = []; 
 
    
 
canvas.width = canvas.height = 100; 
 
document.body.appendChild(canvas); 
 
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 
 

 
const vertex = createShader(gl.VERTEX_SHADER, `#version 300 es 
 
    precision mediump float; 
 
    uniform sampler2D sampler; 
 
    uniform float lod; 
 
    uniform vec4 offset; 
 
    layout(location = 0) in vec4 position; 
 
    out vec4 color; 
 
    void main() { 
 
    color = textureLod(sampler, vec2(.5), lod); 
 
    gl_Position = position + offset; 
 
    }` 
 
); 
 

 
const fragment = createShader(gl.FRAGMENT_SHADER, `#version 300 es 
 
    precision mediump float; 
 
    in vec4 color; 
 
    out vec4 fragColor; 
 
    void main() { 
 
    fragColor = color; 
 
    }` 
 
); 
 

 
const program = createProgram(vertex, fragment); 
 
const lodLocation = gl.getUniformLocation(program, "lod"); 
 
const offsetLocation = gl.getUniformLocation(program, "offset"); 
 

 
// Create a big triangle 
 
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); 
 
gl.bufferData(gl.ARRAY_BUFFER, triangle, gl.STATIC_DRAW); 
 
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); 
 
gl.enableVertexAttribArray(0); 
 

 
// Create a texture with mipmap levels 0 (base) and 1 
 
gl.bindTexture(gl.TEXTURE_2D, texture); 
 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); 
 
gl.texStorage2D(gl.TEXTURE_2D, 2, gl.RGB8, 2, 2); 
 

 
// Setup framebuffers for each level 
 
for (let i = 0; i < 2; ++i) { 
 
    const framebuffer = gl.createFramebuffer(); 
 
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); 
 
    gl.framebufferTexture2D(
 
    gl.FRAMEBUFFER, 
 
    gl.COLOR_ATTACHMENT0, 
 
    gl.TEXTURE_2D, 
 
    texture, 
 
    i); 
 
    let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 
 
    if (status !== gl.FRAMEBUFFER_COMPLETE) { 
 
    console.error(glErrToString(gl, status)); 
 
    } 
 
    const r = (i === 0) ? 1 : 0; 
 
    const g = (i === 1) ? 1 : 0; 
 
    gl.clearColor(r, g, 0, 1); 
 
    gl.clear(gl.COLOR_BUFFER_BIT); 
 
    framebuffers.push(framebuffer); 
 
}; 
 

 
// Detach framebuffer, clear to red 
 
gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
gl.clearColor(0, 0, 0, 1); 
 
gl.clear(gl.COLOR_BUFFER_BIT); 
 

 
// Draw the triangle 
 
gl.uniform1f(lodLocation, 0); 
 
gl.uniform4fv(offsetLocation, [0, 0, 0, 0]); 
 
gl.drawArrays(gl.TRIANGLES, 0, 3); 
 

 
gl.uniform1f(lodLocation, 1.); 
 
gl.uniform4fv(offsetLocation, [-1, 0, 0, 0]); 
 
gl.drawArrays(gl.TRIANGLES, 0, 3); 
 

 
// Some utility functions to cleanup the above code 
 
function createShader(shaderType, source) { 
 
    const shader = gl.createShader(shaderType); 
 
    gl.shaderSource(shader, source); 
 
    gl.compileShader(shader); 
 
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 
 
    console.log(gl.getShaderInfoLog(shader)); 
 
    } 
 
    return shader; 
 
} 
 

 
function createProgram(vertex, fragment) { 
 
    const program = gl.createProgram(); 
 
    gl.attachShader(program, vertex); 
 
    gl.attachShader(program, fragment); 
 
    gl.linkProgram(program); 
 
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { 
 
    console.error('program'); 
 
    } 
 
    gl.useProgram(program); 
 
    return program; 
 
} 
 

 
function glErrToString(gl, error) { 
 
    for (var key in gl) { 
 
    if (gl[key] === error) { 
 
     return key; 
 
    } 
 
    } 
 
    return "0x" + error.toString(16); 
 
}

+0

je aurais dû préciser dans ma question que ni de ceux qui travaillent soit. J'ai laissé 0.5 là-bas quand j'ai posté la question parce qu'elle devrait afficher au moins quelque chose en plus du noir si c'est l'interpolation entre les deux niveaux. – grovesNL

+0

mise à jour réponse .. – gman

+0

ajouté un autre problème avec 'status' – gman