2014-02-17 6 views
0

WebGL에서 선택을 구현하려고합니다. 나는 많은 물건 (약 500 개)을 가지고 있으며, 나는 각각의 물건을 골라야한다. 그렇게하기 위해, 나는 각 개체에 고유 한 색을 할당하는 루프 (참조 따기 원리를)했다 :WebGL : 프레임 버퍼를 사용하여 여러 객체 선택

for (var i = 0, len = objects.length; i < len; i++) { 
    framecolors[count++] = i % 256/256; //Red 
    framecolors[count++] = Math.floor(i/256)/256; //Green 
    framecolors[count++] = Math.floor(i/(256*256))/256; //Blue 
} 

framecolors 다음 각 객체의 다른 그늘을 가지고 있는지 여부를 확인하기 위해 고전 버퍼에 사용 된 빨간. 그것은 효과가 있었다.

이제 개체의 원래 색을 사용하고 백그라운드에서 빨간색 음영을 사용하는 프레임 버퍼를 사용하고 싶습니다. 나는 약간의 코드를 겪었고, 나는 약간 혼란 스럽다.

여기까지 제가 시도한 바가 있습니다. 따기 전에 호출

기능 :

//Creates texture 
colorTexture = gl.createTexture(); 
gl.bindTexture(gl.TEXTURE_2D, colorTexture); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 400, 400, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 

//Creates framebuffer 
fb = gl.createFramebuffer(); 
gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTexture, 0); 
gl.bindTexture(gl.TEXTURE_2D, colorTexture); 
gl.enable(gl.DEPTH_TEST); 

gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 
gl.clear(gl.DEPTH_BUFFER_BIT); 
gl.drawArrays(gl.POINTS, 0, vertexPositionBuffer.numItems); 

기능은 다음에 호출 : 당신은 아마 이해할 수 있듯이

gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
gl.bindTexture(gl.TEXTURE_2D, colorTexture); 
gl.drawArrays(gl.POINTS, 0, vertexPositionBuffer.numItems); 

, 나는 프레임 버퍼와 매우 편안하지 않다, 나는 정말 그들이 어떻게하지 않는다 비록 내가 그들에 대해 많이 읽었지만, 일한다. framecolors을 어떻게 프레임 버퍼에 연결할 수 있는지 잘 모르겠습니다. 방법이 있습니까?

덕분 R.

답변

2

프레임 버퍼 첨부 (renderbuffers 및/또는 텍스처)의 집합이다. 이것은 프레임 버퍼없이 렌더링과 똑같이 작동합니다. (실제로 브라우저는 WebGL의 캔버스를 구현하기 위해 내부적으로 프레임 버퍼를 사용합니다.)

당신은 몇 가지를 놓치고 있습니다. 장면을 렌더링 할 때 zBuffering을 얻지 못하고 잘못된 객체가 앞에 표시 될 때 그렇지 않으면 깊이 버퍼가 필요합니다.

// create renderbuffer 
depthBuffer = gl.createRenderbuffer(); 
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); 

// allocate renderbuffer 
gl.renderbufferStorage(
     gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height); 

// attach renderebuffer 
gl.framebufferRenderbuffer(
     gl.FRAMEBUFFER, 
     gl.DEPTH_ATTACHMENT, 
     gl.RENDERBUFFER, 
     depthBuffer); 

일반적으로 프레임 버퍼가 작동하는지 확인해야합니다. 모든 첨부 파일을 첨부 한 후 gl.checkFramebufferStatus

if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 
    alert("this combination of attachments does not work"); 
    return; 
} 

전화 프레임 버퍼는 이유로 수에 대한 불완전 할 수 있습니다. 가장 일반적인 것은 첨부 파일이 같은 크기가 아니거나 GPU가 해당 첨부 파일 조합을 지원하지 않는다는 것입니다. 참고 : WebGL에서 특정 조합은 작동해야하지만 나중에 다른 형식을 사용하도록 코드를 변경할 수 있으므로 확인하는 것이 좋습니다.

또한 프레임 버퍼를 전환 할 때마다 gl.viewport을 호출하여 뷰포트를 설정해야합니다. 사물을 때 캔버스

gl.bindFramebuffer(gl.FRAMEBUFFER, null); // render to canvas 
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 

다시 다시 넣어 포함

gl.bindFramebuffer(gl.FRAMEBUFFER, someFramebuffer); 
gl.viewport(0, 0, someFramebufferWidth, someFramebufferHeight); 

마지막으로 위의 점에서 코드에서 버그가 당신은 단지 당신이 전화를 프레임 버퍼의 깊이 버퍼를 클리어하고있다 gl.clear. 당신이 전화하기를 원한다면

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 

나중에 색을 읽으려고하므로 오래된 색이 남게됩니다.

마지막으로, 나는 이것을 알고 있습니다. 당신은 마우스 클릭에 해당하는 픽셀 파악하고 호출 할 때 gl.readPixels 당신이 당신의 프레임 버퍼 캔버스에서 읽을 gl.bindFramebuffer 또는 gl.readPixels와 바인딩이 있어야

var colorPicked = new Uint8Array(4); 
gl.readPixels(pickX, pickY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, colorPicked); 

주를 호출합니다.

1

감사합니다. gman. 대답을 완료하기 위해서, 내 프레임 버퍼와 함께 framecolors을 사용하는 방법에 관해서는, 아주 간단합니다. 쉐이더에서, 나는 프레임 버퍼의 색상에 전념 변수 추가 : 나는 readPixels() 기능 덕분에 선택한 개체하는 determing에 전에 지금

if (!offscreen) { 
    gl_FragColor = normalColors; 
} 
else { 
    gl_FragColor = frameColors; 
} 

를, 내가 사용하는 프레임 버퍼로 다시 전환 :

function renderFrame() { 
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb); //fb = framebuffer 
    gl.uniform1i(shaderProgram.uOffscreen, true); //uOffscreen = uniform boolean in shader 
    draw(); //function called to draw objects (contains gl.clear and gl.viewport) 
} 

비슷하게, 함수를 호출 한 후 일반 버퍼로 다시 전환합니다.

마우스를 클릭 할 때 일반 버퍼 대신 프레임 버퍼를 표시하려고합니다. 나는 문제를 겪고 있지만, 내가 찾으면 나중에 해결책을 게시 할 것이다.

EDIT : 해결책 : 프레임 버퍼와 관련된 깊이 버퍼 (렌더 버퍼)를 제거하십시오. 그런 다음 설명 된대로 버퍼를 표시합니다. WebGL display framebuffer?

관련 문제