2017-05-14 2 views
1

Ich versuche, den richtigen Ansatz zu verstehen, auf eine bestimmte Textur Mipmap-Ebene zu rendern.Rendern Textur mipmap Ebene

Im folgenden Beispiel versuche ich, die Farbe Cyan auf Mipmap Level 1 von texture zu rendern. Wenn ich die Ebene von 1 zu 0 in dem Aufruf framebufferTexture2D ändere, zeigt die Zeichenfläche Cyan wie erwartet an. Allerdings verstehe ich nicht, warum nur die Ebene 0 hier funktioniert, da in der WebGL 2/OpenGL ES 3-Spezifikation Nicht-Null-Ebenen unterstützt werden.

ich auch explizit versucht habe Abnehmen 0 (Bindung an null) und verschiedene andere Kombinationen (das heißt mit texImage2D statt texStorage2D), aber keine der Kombinationen scheinen die Mipmapstufe zu machen.

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; 
 
}

erwarte ich, dass ich etwas falsch im Setup mache, aber ich habe nicht in der Lage gewesen, dies viele Beispiele zu finden.

Antwort

1

Wollen Sie nicht entweder

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

oder

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

?

Der Code hat die Filterung nicht so eingestellt, dass Sie tatsächlich auf die anderen Lods zugreifen können.

Es waren sie zu gl.NEAREST was bedeutet, dass immer nur 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

verwende ich in meiner Frage geklärt haben sollte, dass keiner dieser Arbeit auch nicht. Ich habe 0,5 da drin gelassen, als ich die Frage gepostet habe, weil es zumindest etwas außer Schwarz anzeigen sollte, wenn es zwischen den zwei Ebenen interpoliert. – grovesNL

+0

aktualisierte Antwort .. – gman

+0

hinzugefügt ein weiteres Problem mit 'Status' – gman

Verwandte Themen