Idris2+WebGL, 제13부분: 느리고 낙담할 만한 진전

6167 단어 idrisfunctional
내가 지난번 개발 일지를 쓴 이후로 상당히 낙담했다.Idris와 WebGL 사이의 결혼에는 내가 확실하지 않은 장애가 있다
진짜 극복할 수 있어.
우선, 나와 이드리스의 유한한 외국 금융기관 간의 투쟁은 영원히 멈추지 않을 것이다.일찍이 나의 첫 번째 개발 일지 항목에서 나는 이 문제를 불평한 적이 있지만, 그것은 여전히 나를 곤란하게 한다.요컨대 지원되는 유형은 유한하지만 편견이 있어 FFI에서 선형 값을 처리하는 것은 불필요하고 복잡하다.그러나, 나는 이미 몇 가지 일을 개선하려고 노력했지만, 단지 내가 원하는 만큼 많지 않다.
각 FFI에서 AnyPtr 또는 숨겨진 구조 함수가 있는 추상적인 데이터 형식을 사용하지 않고 AnyPtr 라는 별명을 사용합니다.
export
WebGLRenderingContext : Type
WebGLRenderingContext = AnyPtr

export
WebGLProgram : Type
WebGLProgram = AnyPtr

export
%foreign "browser:lambda: (rtype, gl, cbk) => cbk(gl.createProgram())(gl)"
prim__createProgram : (1 _ : WebGLRenderingContext) -> (1 _ : (1 _ : WebGLProgram) -> (1 _ : WebGLRenderingContext) -> rtype) -> rtype
모든 데이터 유형이 export이지 public export가 아니기 때문에 다른 모듈은 몰라WebGLProgram = AnyPtr, 일부WebGLProgram만 존재하고 prim__createProgram에게 전달해야 한다.이것은 여전히 추상적인 데이터 형식이지만 효율이 더 높다(Haskell에서 우리는 newtype로 실현할 수 있다).
불행하게도 실천에서 나는 이 기교를 환영 유형과 결합시킬 수 없다. 왜냐하면 이것은 왠지 해결할 수 없는 많은 빈틈을 초래할 수 있기 때문에 구체적으로 설명하기 어렵다.예를 들어,
export
WebGLProgram : ProgramStatus -> Type
WebGLProgram status = AnyPtr
나는 모든 곳에서 status 의 값을 지정해야 한다.나는 무슨 원인이 야기되었는지 확실하지 않다.다른 한편, 다음 사항도 가능합니다.
export
data WebGLProgram : ProgramStatus -> Type where
  MkWebGLProgram : AnyPtr -> WebGLProgram status
그래서 나는 여분의 데이터 구조 함수를 사용할 것이다.적어도 이것은 나로 하여금 서로 바꿀 수 있는 신속하고 안전한 모듈을 가지게 할 것이다.
외국 금융기구에 관해서 나는 이미 glenums의 문제를 부분적으로 해결했다.
WebGL/OpenGL 규범에서glenumints일 뿐이고 특정 명칭은 특정 값에 귀속된다WebGL constants on MDN 참조.나는 몇 가지 방법으로 이 문제를 처리할 수 있지만, 나는 하나도 좋아하지 않는다.
다른 유형과 마찬가지로 추상 데이터 strick을 사용합니다.
-- shaders
export
ShaderType : Type
ShaderType = AnyPtr

export
%foreign "browser:lambda: () => 0x8B30"
GL_FRAGMENT_SHADER : ShaderType
그러나 만약 내가 그럼스에서 시합을 해야 한다면 이런 상황이 발생할 것이다. 예를 들어getProgramParameter또 다른 솔루션으로는 Ints만 사용할 수 있습니다.
export
ShaderType : Type
ShaderType = Int

export
GL_FRAGMENT_SHADER : ShaderType
GL_FRAGMENT_SHADER = 0x8B30
이것이 바로 내가 현재 가지고 있는 것이지만 다시 한 번 강조하지만 만약에 대소문자 일치를 하려면 값을 생성해야 한다public export. 이것은 추상적인 데이터 형식을 통해 유형의 안전성을 깨뜨렸다.
이곳의 정교한 유형은 정말 훌륭하다.나는 다음과 같이 하고 싶다.
public export
GLEnum = Int

public export
GL_FRAGMENT_SHADER : GLEnum
GL_FRAGMENT_SHADER = 0x8B30


export
%foreign "browser:lambda: (aType, gl, type, callback) => callback(gl.createShader(Number(type)))(gl)"
prim__createShader : IsElem shaderType [GL_VERTEX_SHADER, GL_FRAGMENT_SHADER] => (1 _ : WebGLRenderingContext) -> (shaderType : GLEnum) -> (1 _ : (1 _ : WebGLShader) -> (1 _ : WebGLRenderingContext) -> a) -> a
while you can express refinements in a dependently typed language, the result is verbose 및 엔드 유저에게 증명을 요청합니다.나는 이것이 받아들일 수 없다고 생각한다.나는 라이브러리의 내부 작업을 가능한 한 복잡하게 할 수 있지만, API는 깨끗해야 한다.이것이 바로 전체 실험의 중점이다.예를 들어, 위의 컨텐트에 대해 최종 사용자는 다음과 같이 써야 합니다.
createShader (There Here) gl GL_FRAGMENT_SHADER
There Here 부분은 증거로 공인된glenum값 목록과 함께 길어진다.
내가 생각할 수 있는 마지막 옵션도 내가 생각할 수 있는 것이다. 기초로 돌아가 성능의 충격을 받아들이는 것이다. sum 유형을 사용하여AnyPtr나 Int와의 변환 함수를 만드는 것이다.
data ShaderType
  = GL_VERTEX_SHADER
  | GL_FRAGMENT_SHADER

toShaderType : Int -> Maybe ShaderType
toShaderType i = case i of
  0x8B30 => Just GL_FRAGMENT_SHADER
  0x8B31 => Just GL_VERTEX_SHADER
  _ => Nothing
FFI의 세계를 벗어나 WebGL API의 디자인에는 선형 유형에 대한 흥미롭고 짜증나는 문제가 하나 있는데 그것이 바로null을 자원으로 전달하는 것이다.
예를 들어 이것은 함수bindVertexArray에서 발생한다.이것은 보통 WebGLVertexArrayObject 을 사용하지만,null을 값으로 받아들여 '기본' 정점 그룹의 대상을 연결합니다.기본vao가 귀속되어 있다고 가정하면 범위를 초과한 코드가 특정vao를 덮어쓰는 것을 방지할 수 있기 때문에null을 bindVertexArray 에 전달하는 것을 권장합니다.현재, 나는 이 문제를 소홀히 할 것이다. 유형이 안전해야 할 문제에 대해, 이 건의가 약한 해결 방안인지 아닌지.
중점은 전달null은 유효하지만 WebGLVertexArrayObject에 대해 선형값을 사용하면 null도 선형이 된다는 것을 의미하고bindVertexArray는 우리에게 되돌아온다!그리고 우리는 null부터 deleteVertexArray까지 통과해야 한다.나는 이것이 해결할 수 있다고 자신한다. 다른 방법이 없다면 함수 unbindVertexArray 를 만드는 것이다. 그러나 이것은 재미있는 디자인 문제이다.이 점을 깊이 연구하기 전에 VAO의 다른 유형의 안전 문제를 먼저 해결하고 싶습니다. 왜냐하면 서로 영향을 미칠 수 있기 때문입니다.
더욱 구체적으로 말하면 VAOs의 다른 유형의 안전 문제는 프로그램과 일치하는지 확인하는 것과 관련된다.정점 속성의 경우 특정 프로그램에서 하나의 속성을 가져와 가상 유형에 프로그램 ID를 넣기만 하면 됩니다.프로그래머가 수동으로 속성의 위치를 지정하여 프로그램이 같은 위치를 사용하고 속성을 정적 위치로 연결할 수 있기 때문에 이것은 결코 정확한 해결 방안이 아니다.VAO에 대해 이 문제는 더욱 커질 것이다. 왜냐하면 VAO가 특정한 프로그램과 일치하지 않기 때문이다.VAO는 변체가 없고 getAttribLocation만 있다.나는 특정한 프로그램과 일치하는 인위적인 제한을 추가할 수 있지만, 나는 그러기를 원하지 않는다. 가능한 한 많은vao를 만들어야 한다. 이것은 번거롭고 효과가 없다.
반대로 나는 프로그램 ID를 사용하는 것에서 모든 속성을 프로그램 유형에 넣는 것으로 전환할 수 있다.처음에는 훨씬 더 상세한 것 같았다.
Program Linked pid
vs
Program Linked [attributeType0, attributeType1, attributeType2...] [uniformType0, uniformType1, uniformType2]
그러나 이러한 프로그램 유형은 사용자 최종 코드에서 제한될 것으로 예상되므로 다음과 같은 별칭으로 지정할 수 있습니다.
BlinnPhongProgram : Type
BlinnPhongProgram = Program Linked [...] [...]
이런 방법의 단점은 전달이 얻는 속성이 더욱 어려워진다createVertexArray.getAttribLocationenableVertexAttribArray는 프로그램이 컴파일할 때 알 수 없는 위치 변수가 프로그램에 유효하다는 것을 어떻게 알았습니까?즉 VAOs를 사용하는 것이 웹GL 프로그램을 작성하는 최선의 방법이기 때문에 이 점을 중점적으로 소개하겠습니다.
전반적으로 말하면, 나는 아직 해야 할 일이 매우 많은데, 하나도 쉽지 않다.

좋은 웹페이지 즐겨찾기