C/C++에서 OpenGL 셰이더를 위한 손쉬운 프레임워크
그냥 납작한 이미지에 쉐이더를 써보고 싶었어요.사진을 텍스처로 찍어 적용하는 C 프로그램을 작성하는 것은 그리 쉽지 않은 것으로 드러났습니다. 그 위에 프래그먼트 쉐이더로 가우스 블러를 적용하는 것입니다.코드 100줄 같은 OpenGL을 초기화하고 GL 버퍼 등을 이해해야 합니다.또한 윈도잉 시스템과 통신하기 위해서는 또 다른 프레임워크인 GLUT를 사용해야 합니다.
엔비디아의 Fx 작곡가가 쉐이더를 가지고 놀기에 좋은 것으로 드러났습니다.하지만 저는 주어진 프래그먼트 쉐이더를 이미지에 적용해서 그 결과를 보여주는 간단한 C나 C++ 프로그램을 가지고 싶습니다.예를 든 사람이 있습니까, 아니면 틀이 있습니까?
무엇보다도, 저는 과도한 양을 사용하는 것을 피하고자 합니다. 그것은 버그가 많고, 약 10년 동안 업데이트되지 않았고, 그것의 디자인은 오늘날 대부분의 사람들이 원하는 것과 잘 맞지 않습니다. 예를 들어, 애니메이션에 사용할 수 있지만, 그것은 주로 정적인 디스플레이를 만들기 위한 것입니다.저는 이전 답변에서 과식에 대한 몇 가지 대안을 지적했습니다.
대부분은 코드를 컴파일하고 링크하고 쉐이더를 사용하도록 남겨 둡니다.이 목적을 위해 도움이 되는 작은 수업을 작성했습니다.
class shader_prog {
GLuint vertex_shader, fragment_shader, prog;
template <int N>
GLuint compile(GLuint type, char const *(&source)[N]) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, N, source, NULL);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
std::string log(length, ' ');
glGetShaderInfoLog(shader, length, &length, &log[0]);
throw std::logic_error(log);
return false;
}
return shader;
}
public:
template <int N, int M>
shader_prog(GLchar const *(&v_source)[N], GLchar const *(&f_source)[M]) {
vertex_shader = compile(GL_VERTEX_SHADER, v_source);
fragment_shader = compile(GL_FRAGMENT_SHADER, f_source);
prog = glCreateProgram();
glAttachShader(prog, vertex_shader);
glAttachShader(prog, fragment_shader);
glLinkProgram(prog);
}
operator GLuint() { return prog; }
void operator()() { glUseProgram(prog); }
~shader_prog() {
glDeleteProgram(prog);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
}
};
간단한 데모의 경우, 몇 개의 "패스스루" 쉐이더(고정 기능 파이프라인을 모방하기만 하면 됨):
const GLchar *vertex_shader[] = {
"void main(void) {\n",
" gl_Position = ftransform();\n",
" gl_FrontColor = gl_Color;\n",
"}"
};
const GLchar *color_shader[] = {
"void main() {\n",
" gl_FragColor = gl_Color;\n",
"}"
};
다음과 같은 것을 사용할 수 있습니다.
void draw() {
// compile and link the specified shaders:
static shader_prog prog(vertex_shader, color_shader);
// Use the compiled shaders:
prog();
// Draw something:
glBegin(GL_TRIANGLES);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3d(0.0, -1.0, -1.0);
glEnd();
}
예를 들어 장면을 그리는 과정에서 여러 가지 다른 프래그먼트 쉐이더를 사용할 경우 각각에 대해 정적 개체를 정의한 다음 실행합니다.prog1();
,prog2();
, 등, 각 쉐이더로 음영을 주고 싶은 객체를 그리기 직전에.예.,
void draw() {
static shader_prog wall_shader("wall_vertex", "wall_frag");
static shader_prog skin_shader("skin_vertex", "skin_frag");
wall_shader();
draw_walls();
skin_shader();
draw_skin();
}
편집: @rotoglup이 정확히 지적한 바와 같이, 이 사용은static
변수는 OpenGL 컨텍스트가 파괴된 후까지 파괴를 지연하므로 파괴자가 사용을 시도할 때glDeleteProgram
/glDeleteShader
, 결과를 예측할 수 없습니다.
이는 데모 프로그램에서는 사용할 수 있지만 실제 사용에서는 확실히 바람직하지 않습니다.동시에 일반적으로 셰이더를 사용하는 함수를 입력할 때마다 셰이더를 다시 컴파일하고 싶지 않습니다.
일반적으로 두 문제를 방지하기 위해 쉐이더 개체를 클래스 인스턴스의 멤버로 만들고 수명은 쉐이더로 표시되는 수명과 연결됩니다.
class some_character_type {
shader_prog skin_shader;
public:
// ...
};
이는 해당 유형의 캐릭터를 생성할 때 쉐이더 프로그램을 한 번 컴파일/링크하고 해당 캐릭터를 파괴할 때 파괴합니다.
물론, 몇몇의 경우에는, 이것 또한 정확히 바람직하지 않습니다.예를 들어, 갈라가나 센티페데와 같은 고대의 "많은 목표물을 죽인다"는 게임의 3D 버전을 생각해 보세요.이와 같은 게임의 경우 본질적으로 동일한 타겟을 상대적으로 빠르게 많이 생성하고 파괴하는 것입니다.많은 수의 본질적으로 동일한 대상을 고려할 때, 당신은 아마도 다음과 같은 것을 사용하기를 원할 것입니다.shared_ptr<shader_prog>
특정 대상 유형의 모든 인스턴스 간에 공유되는 쉐이더의 단일 인스턴스를 생성합니다.동일한 타겟 타입을 여러 번 다시 사용하는 것을 고려할 때, 그보다 조금 더 나아가기를 원할 수도 있기 때문에 특정 타입의 타겟이 보여질 때만이 아니라 전체 게임을 통해 동일한 쉐이더를 유지하게 됩니다.
어쨌든, 우리는 여기서 약간 궤도를 벗어나고 있습니다.중요한 것은 쉐이더를 컴파일하고 연결하는 것은 상당히 비용이 많이 드는 과정이기 때문에 일반적으로 쉐이더를 생성하고 파괴하는 것을 피하기 위해 수명을 관리하기를 원한다는 것입니다(하지만 게임 초반에 쉐이더를 모두 생성하고 마지막에만 파괴하는 것이 중요하다는 것은 아닙니다).
약 1년 반 전에도 저는 비슷한 입장이었습니다.GLSL을 사용하기 위한 간단한 튜토리얼과 소스 코드를 빠르게 찾았습니다. 하지만 GLUT와 GLW를 작동시켜야 했고, 적어도 하나는 내가 직접 컴파일한 것 같습니다.Windows(윈도우)를 사용하고 있었기 때문에(Windows(윈도우)는 표준이 아닌 특수한 경우로, 오픈 프로젝트에서는 거의 완벽하게 처리되지 않습니다.) DLL과 헤더 파일을 수동으로 복사하여 특정 공통 위치에 붙여넣어야 하는 우스꽝스러운 프로세스도 수반되었습니다.항상 고통스럽고 그런 일을 하다 보니 삶의 상당 부분을 잃었지만, 지시대로 그 과정을 터벅터벅 거렸고 결국에는 일반적인 경우처럼 해결되었습니다.
어쨌든 지금 찾을 수 있는 GLSL을 이용한 가장 편리한 쉐이더 예는 이것입니다 - http://www.lighthouse3d.com/opengl/glsl/index.php?minimal
원하는 대로 텍스처를 특별히 수정하지는 않습니다.하지만 제 경험으로는 이런 코드를 컴파일하고 실행하면 더 재미있을 것이고 빠르게 발전할 수 있고 필요한 경우 다른 튜토리얼에서 조각을 분리할 수 있습니다.저는 일단 예제가 실행되면 가정과 직장에서 많은 문제를 빠르게 해결하기 위해 같은 프레임워크를 사용했다고 말할 수 있습니다.
유감스럽게도 GLUT와 GLW를 활용하고 있습니다.만약 당신이 이 질문에 대한 더 좋은 답변을 얻게 된다면, 저도 어느 사이트에서 코드를 제공하든 즉시 팬이 될 것입니다.행운을 빌어요.
이 자습서는 유용할 수 있습니다(이전 Cg 내용 외에 GLSL 자료도 포함되어 있음).
그래픽이 아닌 GPGPU 형태의 것들을 구현하기 위해 쉐이더를 쓰는 것은 요즘에는 쓸모없는 접근법이라고 생각합니다.OpenCL 또는 CUDA는 분명히 미래에 가야 할 방향입니다.
목표는 아니지만 Noel Lopis의 OpenGL ES 2.0 쉐이더 샘플에서 무언가를 얻을 수 있습니다. http://www.mobileorchard.com/getting-started-with-opengl-es-20-on-the-iphone-3gs/
언급URL : https://stackoverflow.com/questions/2795044/easy-framework-for-opengl-shaders-in-c-c
'programing' 카테고리의 다른 글
원래 변수는 그대로 유지하면서 mutate_at로 새 변수 만들기 (0) | 2023.11.07 |
---|---|
매크로에서 사용할 수 있는 트릭에는 어떤 것이 있습니까? (0) | 2023.11.07 |
PHP oci_connect() TNS: 연결 식별자(ORA-12154)를 확인할 수 없습니다. (0) | 2023.11.07 |
Python으로 Excel에서 병합된 셀 읽기 (0) | 2023.11.07 |
그래들을 통해 지프스터 프로젝트를 만들고 있는데, 첫 번째 프로젝트는 잘 실행되지만 두 번째 프로젝트는 예외가 있습니까? (0) | 2023.11.07 |