OpenGL : 쉐이더를 어디에 배치해야합니까?


17

OpenGL ES 2.0을 배우려고하는데 쉐이더를 "관리"하는 가장 일반적인 방법이 궁금합니다.
내가 찾은 예제에서 (안드로이드 SDK와 함께 제공되는 API 데모에 포함 된 예제와 같이) 일반적으로 GLRenderer 클래스 내부의 모든 것을 볼 수 있기 때문에 내가 가질 수있는 것을 분리하기 때문에, 예를 들어, OpenGL ES 1.0 코드에서와 같이 텍스처 쿼드를 그릴 때마다 재사용 할 수있는 GLImage 객체 (현재 2D에만 초점을 맞추고 있습니다). 내가 찾은 거의 모든 예제에서 셰이더는 클래스 속성으로 정의되었습니다. 예를 들면 다음과 같습니다.

public class Square {

public final String vertexShader =
        "uniform mat4 uMVPMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec4 aColor;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_Position = uMVPMatrix * aPosition;\n" +
        "  vColor = aColor;\n" +
        "}\n";

public final String fragmentShader =
        "precision mediump float;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_FragColor = vColor;\n" +
        "}\n";
// ...
}

이러한 질문 중 일부가 멍청한 경우 사전에 사과하지만 이전에는 쉐이더로 작업 한 적이 없습니다.

1) 위 코드는 셰이더 (공공 최종 클래스 속성)를 정의하는 일반적인 방법입니까?
2) 별도의 Shader 클래스가 있어야합니까?
3) 셰이더를 사용하는 클래스 외부에서 셰이더를 정의한 경우 속성 이름 (예 : 다음 코드에서 "aColor")을 어떻게 알 수 있습니까?

colorHandle = GLES20.glGetAttribLocation(program, "aColor");

답변:


16

나는 항상 문자열을 사용하여 쉐이더를 정의하는 방식을 싫어했습니다. 텍스트 파일에서 내 것을하고로드 할 때 읽는 것을 선호합니다. 문자열로 정의하면 디버깅이 번거롭고 나에게 지저분 해 보입니다. 문자열을 입력하는 대신 입력하고 입력해야하는 것이 훨씬 쉽습니다.

또한 셰이더 읽기 및 셰이더 디버깅을위한 로깅 정보 인쇄와 같은 일반적인 셰이더 기능이있는 별도의 클래스가 있습니다.

셰이더가 정의 된 곳에서는 예제에서와 같이 이름에 액세스 할 수 있습니다. 문자열 리터럴을 사용하는 것은 일단 구현 한 후에는 값이 변경되지 않으므로 셰이더에 허용됩니다.

그러나 결국 그것은 당신에게 달려 있습니다. 문제를 일으키지 않으면 현재하고있는 방식이 훌륭하게 작동합니다.


2
별도의 파일에 셰이더가 있다는 것은 편리한 댄디 셰이더 편집기를 사용하고 전체 구문 강조를 할 수 있으며, 지원하는 경우 프로그램에서 테스트하기 전에 미리 볼 수도 있습니다.
Raceimaztion

6
문자열에 셰이더가있는 유일한 이유는 빠른 테스트 및 자습서입니다. 파일 처리에 많은 "불필요한 코드"가 추가됩니다.
Jari Komppa

2
셰이더 파일에 핫 리로드를 구현하여 게임을 다시 시작하지 않고도 변경 사항을 디버깅 할 수 있습니다. 생산성 ++
Liosan

나는 파일을 읽고 별도의 Shader 클래스를 갖는 아이디어를 좋아합니다. 항상 문자열로 그것들을 보는 것이 혼란 스러웠습니다. 왜냐하면 그것이 그것이 일반적으로 정의 된 방식인지 또는 학습 목적인지 알지 못했습니다. 감사!
miviclin December

8

셰이더 (및 머티리얼) 관리는 그래픽 시스템이 복잡해지고 모든 셰이더가 하드 코딩 될 때 엄청난 코드 복제로 이어질 때 발생하는 다소 까다로운 문제입니다. 이를 해결하기위한 몇 가지 대안이 있습니다.

  • Jari Komppa가 언급 한 것처럼 몇 개의 셰이더 만있는 작은 예제는 파일 처리를 피하기 위해 문자열로 하드 코딩하는 경향이 있습니다.
  • 구문 강조와 적절한 형식을 지정할 수있는 별도의 파일을 사용하는 것이 좋습니다. 또한 해당 파일의 변경 사항을 감시하고 게임이 실행되는 동안 수정 된 셰이더를 즉시 적용하는 간단한 디버그 시스템을 코딩 할 수도 있습니다.
  • 재료 수가 증가하면 셰이더 생성기가 거의 필요합니다. 기본적으로 "조각 셰이더 노멀 매핑 스 니펫"과 같은 공통 스 니펫을 정의하고 원하는 구성 요소를 포함하여 전체 셰이더를 구성합니다.
    • 하드 코딩 된 문자열 스 니펫을 사용할 수는 있지만 정말 지저분 해지므로 파일을 다시 한 번 사용하는 것이 좋습니다.
    • 별도의 파일 (또는 동일한)에 약간의 코드 를 사용하거나 전 처리기 (또는 균일 한 플래그)를 사용하여 항목을 활성화 / 비활성화 하는 ubershader / supershader 를 사용할 수도 있습니다.

속성과 균일 한 이름 등은 모든 쉐이더에서 일관된 이름을 사용합니다.


쉐이더를 별도의 파일로 옮길 것입니다. 감사!
miviclin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.