성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>.NET으로 구현하는 OpenGL (3) - Index Buffer</h1> <p> 아래의 글에 이어,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > .NET으로 구현하는 OpenGL (2) - VAO, VBO ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11772'>http://www.sysnet.pe.kr/2/0/11772</a> </pre> <br /> 오늘은 세 번째 강좌의 내용을 따라 하려는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > TheThinMatrix/OpenGL-Tutorial-3 ; <a target='tab' href='https://github.com/TheThinMatrix/OpenGL-Tutorial-3'>https://github.com/TheThinMatrix/OpenGL-Tutorial-3</a> OpenGL 3D Game Tutorial 3: Rendering with Index Buffers ; <a target='tab' href='https://www.youtube.com/watch?v=z2yFlvkBbmk'>https://www.youtube.com/watch?v=z2yFlvkBbmk</a> </pre> <br /> 이번에는, Vertex의 좌표를 인덱스로 지정하는 방법을 설명하고 있습니다. 그렇다면, 기존의 6개 점을 표현하던 vertex 데이터는 4개로 줄어들게 되고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > float[] _vertices = { -0.5f, 0.5f, 0f, // V0 -0.5f, -0.5f, 0f, // V1 0.5f, -0.5f, 0f, // V2 0.5f, 0.5f, 0f // V3 }; </pre> <br /> 이에 대한 Vertex를 나타내는 인덱스 배열이 필요하며,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > int[] _indices = { 0, 1, 3, // Top left triangle (V0, V1, V3) 3, 1, 2 // Bottom right triangle (V3, V1, V2) }; </pre> <br /> 당연히, RAM에 있는 _indices 배열을 GPU에 할당하는 작업이 수반되어야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // MainForm.cs private void glControl_ContextCreated(object sender, OpenGL.GlControlEventArgs e) { GlControl glControl = (GlControl)sender; _displayManager.createDisplay(glControl); _loader = new Loader(); _model = _loader.loadToVAO(_vertices<span style='color: blue; font-weight: bold'>, _indices</span>); _renderer = new Renderer(); } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // Loader.cs public RawModel loadToVAO(float [] positions, <span style='color: blue; font-weight: bold'>int[] indices</span>) { uint vaoID = createVAO(); <span style='color: blue; font-weight: bold'>bindIndicesBuffer(indices);</span> storeDataInAttributeList(0, positions); unbindVAO(); return new RawModel(vaoID, <span style='color: blue; font-weight: bold'>positions.Length</span>); } <span style='color: blue; font-weight: bold'>void bindIndicesBuffer(int[] indices) { uint vboID = Gl.GenBuffer(); _vbos.Add(vboID); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, vboID); Gl.BufferData(BufferTarget.ElementArrayBuffer, (uint)(indices.Length * sizeof(int)), indices, BufferUsage.StaticDraw); }</span> </pre> <br /> 그런데 재미있는 것은,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Gl.BindBuffer(BufferTarget.ElementArrayBuffer, vboID); </pre> <br /> 로 바인드는 했으나, "<a target='tab' href='https://www.youtube.com/watch?v=z2yFlvkBbmk'>OpenGL 3D Game Tutorial 3: Rendering with Index Buffers</a>" 강좌를 보면 이후에 BufferTarget.ElementArrayBuffer에 대해서는 언바인드를 하지는 않습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Gl.BindBuffer(BufferTarget.ElementArrayBuffer, 0); </pre> <br /> 다음의 글을 읽어보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > OpenGL glBindBuffer(0) outside vao? ; <a target='tab' href='https://stackoverflow.com/questions/25412767/opengl-glbindbuffer0-outside-vao'>https://stackoverflow.com/questions/25412767/opengl-glbindbuffer0-outside-vao</a> </pre> <br /> GL_ELEMENT_ARRAY_BUFFER(BufferTarget.ElementArrayBuffer)의 경우 VAO 상태의 일부로 바인딩이 되기 때문에 VAO를 Unbind 하면 GL_ELEMENT_ARRAY_BUFFER 역시 자동으로 Unbind 시킨다고 합니다. 반면 GL_ARRAY_BUFFER(BufferTarget.ArrayBuffer)는 VAO의 일부가 아니기 때문에 명시적으로 Unbind 호출이 필요하다고. (실제로, unbind 유무에 상관없이 메모리 누수 같은 현상은 발생하지 않습니다.)<br /> <br /> 심지어 VAO 조차도 Unbind를 할 필요는 없다고 합니다. 어차피 다른 VAO를 Bind 하면 기존 바인드 되었던 VAO가 Unbind되므로 오히려 명시적인 Unbind는 성능상 좋지 않다고 합니다. 단지, Unbind를 명시적으로 하는 것이 어떤 식으로든 지나칠 수 있는 실수를 미연에 방지할 수 있기 때문에 그 정도 성능은 감수하고 맞춰 주는 것이 좋다는 언급도 합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> Vertex에 대한 인덱스 정보로 바뀌었기 때문에 Render 방식에도 변화가 있습니다. 기존의 DrawArrays에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Gl.DrawArrays(PrimitiveType.Triangles, 0, model.VertexCount); // model.VertexCount == 6 (점의 수, float [18]) </pre> <br /> DrawElements로 바뀝니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public void Render(RawModel model) { Gl.BindVertexArray(model.VaoID); Gl.EnableVertexAttribArray(0); <span style='color: blue; font-weight: bold'>Gl.DrawElements(PrimitiveType.Triangles, model.VertexCount, DrawElementsType.UnsignedInt, IntPtr.Zero);</span> Gl.DisableVertexAttribArray(0); Gl.BindVertexArray(0); } </pre> <br /> 여기서 재미있는 것은 Triangles에 model.VertexCount == 12 (float [12])로 4개의 점에 대한 정보가 전달되지만, index 버퍼에 대한 정보는 Render 코드에서 찾아볼 수 없습니다. 아마도 이것은 VAO에 Gl.VertexAttribPointer 메서드로 바인딩하는 시점에 BufferTarget.ElementArrayBuffer로 지정된 index 버퍼의 정보가 VAO에 기록되는 것이 아닌가 예상해 봅니다. (혹시 아시는 분은 덧글 부탁드립니다. ^^)<br /> <br /> 정리하면, 이번 프로그램은 <a target='tab' href='http://www.sysnet.pe.kr/2/0/11772'>지난번 예제</a>를 인덱스 버퍼로 변환한 것에 불과하므로 실행 결과는 동일합니다.<br /> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1397&boardid=331301885'>첨부 파일은 이 글의 예제 프로젝트를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1418
(왼쪽의 숫자를 입력해야 합니다.)