본문 바로가기
Study Archives/Metal

[Metal] Hello, Metal!

by 2den 2022. 7. 20.
728x90

* 교재 제목 : Metal by Tutorials second edition (Beginning Game Engine Development with Metal)


Questions

1. Metal에서는 vertex shader, fragment shader 대신 vertex function, fragment function이라는 용어를 사용한다. *.metal 쉐이더 파일에 vertex shader에 해당하는 vertex function, fragment shader에 사용하는 fragment function을 한 번에 저장하고 사용하는 게 일반적이어서 그런가?

(이를테면 이런 식이다)

#include <metal_stdlib>
using namespace metal;

struct VertexIn {
	float4 position [[ attribute(0) ]];
};

vertex float4 vertex_main(const VertexIn vertex_in
[[ stage_in ]]) {
	return vertex_in.position;
}

fragment float4 fragment_main() {
	return float4(1, 0, 0, 1);
}
let vertexFunction = library.makeFunction(name: "vertex_main")
let fragmentFunction = library.makeFunction(name: "fragment_main")



2. Model I/O basic 3D shape는 각각의 3D모델 데이터를 다 가지고 있는 것일까? (mesh를 로드할 때 vertex descriptor도 자동으로 생성한다고 후술, mesh가 정점의 간단한 리스트를 포함하는 버퍼 즉 vertex buffer도 가지고 있다고 후술)

let mdlMesh = MDLMesh
	sphereWithExtent: [0.75, 0.75, 0.75],
	segments: [100, 100],
	inwardNormals: false,
	geometryType: .triangles,
	allocator: allocator)



3. (swift) try만 있는 건 정체가 뭐지?

let library = try device.makeLibrary(source: shader, options: nil)



4. draw call

renderEncoder.drawIndexedPrimitives(
	type: .triangle,
	indexCount: submesh.indexCount,
	indexType: submesh.indexType,
	indexBuffer: submesh.indexBuffer.buffer,
	indexBufferOffset: 0)

"Here, you're instructing the GPU to render a vertex buffer consisting of triangles with the vertices placed in the correct order by the submesh index information."


5. MTKViewdrawable을 command buffer에 넘겨주면 연결된(?) render pass descriptor(그러니까 MTKView의 descriptor 참조)가 이 drwable을 갖게 되는 것인가?

let view = MTKView(frame: frame, device: device)

let commandBuffer = commandQueue.makeCommandBuffer()
let renderPassDescriptor = view.currentRenderPassDescriptor
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)

let drawable = view.currentDrawable

commandBuffer.present(drawable)

"MTKView provides a render pass descriptor that will hold a texture called the drawable."
"You get the drawable from the MTKView."
"The MTKView is backed by a Core Animation CAMetalLayer and the layer owns a drawable texture which Metal can read and write to."


6. draw call에서 렌더가 일어나진 않는다. 렌더는 GPU가 command buffer의 모든 command를 받고 나서 이루어진다. 그게 여기?

commandBuffer.commit()



Archives

- Metal 렌더링의 프로세스는 앱의 크기나 복잡도에 상관 없이 같다고 볼 수 있다.


- (Xcode) PlaygroundSupportassistant editor에서 live view를 보게 해준다. (playground에서 Metal 코드를 실행하면 live view로 결과를 볼 수 있음)


- MetalKit는 Metal을 보다 쉽게 사용할 수 있게 해주는 프레임워크이다. 텍스처를 로드하고, Metal 버퍼로 작업할 수 있게 해주며, Model I/O 프레임워크와 interfacing한다.


- (swift) guard : 조건이 false일 때 구문을 실행하는 조건문, 조건을 그대로 적어서 가독성이 높다. guard 조건 else { 구문}


- (swift) let : 상수 선언 (재할당 불가) > var : 변수


- MTLClearColorMTKViewclearColor를 설정

let view = MTKView(frame: frame, device: device)
view.clearColor = MTLClearColor(red: 1, green: 1, blue: 1, alpha: 1)



- primitive : Model I/O basic 3D shape, 큐브, 구, 실린더, 토러스 등이 있다. (OpenGL에서 primitive가 point, line, triangle 등의 drawing primitive를 일컫는 용어라는 점을 기억하면 좋을듯)


- MTKMeshBufferAllocator는 mesh data를 위한 메모리를 관리한다.


- Metal에서 MDLMesh가 반환하는 mesh를 사용하려면, Model I/O mesh를 MetalKit mesh로 바꾸어야 한다.

let mesh = try MTKMesh(mesh: mdlMesh, device: device)



- (os) descriptor : linux나 unix 계열 시스템(맥은 unix 기반)에서 process가 file을 다룰 때 사용하는 추상적인 정수 값, 파일을 지칭한다. 참고로, unix에서는 디렉토리, 소켓, 파이프, 블록 디바이스, 캐릭터 디바이스 등 모든 객체가 파일로 관리된다.


- pipeline state를 설정하는 것은 GPU에게 state가 변경될 때까지 아무것도 변하지 않을 것이란 걸 알려주는 것이다. pipeline state에는 GPU가 어떤 pixel 포맷을 사용해야 하는지, depth 렌더링을 해야하는지, shader function 등 GPU가 필요한 모든 정보를 포함한다.


- .vertexDescriptor : GPU에게 메모리에서의 정점들의 레이아웃을 알려준다.


- "In a real app, you might create several pipeline states to call different shading functions or use different vertex layouts."


- (swift) delegate method : 번역하자면 대리 매소드, c++의 함수 포인터와 비슷한 개념


- MTKView는 매 프레임마다 실행되는 delegate method를 가지고 있다.


- render pass : 그림자, light, 반사 등의 복잡한 계산을 각각의 render pass에서 분리하여 수행한다. 예를 들어, shadow render pass는 3D 모델의 전체 scene을 렌더하지만 grayscale shadow 정보만 유지한다. 다른 render pass는 모델을 색상 전체로 렌더한다. 이 두가지 텍스처를 합쳐서 하나의 결과물로 screen에 보여주는 것이다.


- command buffer : GPU가 실행할 모든 command를 저장한다.

let commandBuffer = commandQueue.makeCommandBuffer()



- attatchment : 렌더 목적지 (render destination) 데이터로, 저장할 텍스처나 render pass에서 텍스처를 유지할지 말지 등의 정보를 필요로 한다.


- render pass descriptor : MTKView의 render pass descriptor의 레퍼런스로 사용, attatchment를 가지고 있다.


- render pass descriptor를 사용하여 render command encoder를 만든다.


- render command encoder : GPU가 정점을 그리기 위해 필요한 모든 정보를 가지고 있다.


- 아래 코드에서 offset은 vertex 정보가 시작하는 버퍼에서의 위치를, index는 vertex shader function이 해당 버퍼를 몇번째 index로 가지는지를 나타낸다.

renderEncoder.setVertexBuffer(mesh.vertexBuffers[0].buffer, offset: 0, index: 0)



- submesh : mesh는 submesh로 이루어진다. material이라고 생각해도 된다.


- 더 이상 draw call이 없을 것이란 뜻 :

renderEncoder.endEncoding()


Words

* integrate : 통합하다
* take into account : 고려하다

728x90

'Study Archives > Metal' 카테고리의 다른 글

[Metal] 3D Models  (0) 2022.08.07

댓글