https://github.com/dlgmlals3/OpenGLES3.0_Example/blob/main/Chapter_2/app/src/main/cpp/Scene/Cube.cpp
OpenGLES3.0_Example/Chapter_2/app/src/main/cpp/Scene/Cube.cpp at main · dlgmlals3/OpenGLES3.0_Example
Contribute to dlgmlals3/OpenGLES3.0_Example development by creating an account on GitHub.
github.com
InitModel() 함수를 부분을 보자.
Original gl 셰이더 프로그램 컴파일을 하려면 아래 절차를 수행한다.
1> 셰이더 생성 및 컴파일
2> 프로그램 생성하여 셰이더를 어태치 후 링킹
3> 프로그램 사용
#include <GLES3/gl3.h>
#include <stdio.h>
#include <stdlib.h>
// -----------------------------------------------------------------------------
// 함수: loadShader
// 설명: 주어진 셰이더 타입(GL_VERTEX_SHADER 또는 GL_FRAGMENT_SHADER)과 소스 코드를
// 이용하여 셰이더 객체를 생성하고 컴파일한다.
// 반환값: 성공하면 컴파일된 셰이더 객체 ID, 실패하면 0을 반환한다.
// -----------------------------------------------------------------------------
GLuint loadShader(GLenum shaderType, const char* pSource) {
// 1) 셰이더 객체 생성
GLuint shader = glCreateShader(shaderType);
if (shader == 0) {
// 셰이더 객체 생성 실패
return 0;
}
// 2) 셰이더 소스 코드 전달
glShaderSource(shader, 1, &pSource, NULL);
// 3) 셰이더 컴파일
glCompileShader(shader);
// 4) 컴파일 상태 확인
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (compiled == GL_FALSE) {
// 컴파일 실패시 오류 로그 출력
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*)malloc(infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("셰이더 컴파일 오류:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
// 셰이더 ID 전달
return shader;
}
// -----------------------------------------------------------------------------
// 함수: createProgram
// 설명: 버텍스 셰이더와 프래그먼트 셰이더 소스 코드를 받아, 셰이더를 컴파일하고
// 프로그램 객체를 생성한 후 셰이더를 첨부하여 링킹한다.
// 반환값: 성공하면 프로그램 객체 ID, 실패하면 0을 반환한다.
// -----------------------------------------------------------------------------
GLuint createProgram(const char* vertexSource, const char* fragmentSource) {
// 1) 버텍스 셰이더 컴파일
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
// 2) 프래그먼트 셰이더 컴파일
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
if (fragmentShader == 0) {
glDeleteShader(vertexShader);
return 0;
}
// 3) 프로그램 객체 생성
GLuint program = glCreateProgram();
if (program == 0) {
return 0;
}
// 4) 셰이더 객체를 프로그램에 첨부
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
// 5) 프로그램 링킹
glLinkProgram(program);
// 6) 링킹 상태 확인
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked == GL_FALSE) {
// 링킹 실패시 오류 로그 출력
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*)malloc(infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
printf("프로그램 링킹 오류:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(program);
return 0;
}
// 7) (Optional) 프로그램 검증: 현재 OpenGL 상태에서 실행 가능한지 확인
glValidateProgram(program);
GLint validated;
glGetProgramiv(program, GL_VALIDATE_STATUS, &validated);
if (validated == GL_FALSE) {
printf("프로그램 검증 실패.\n");
}
// 8) (Optional) 셰이더 객체는 프로그램에 붙였으므로 더 이상 필요하지 않음
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
// -----------------------------------------------------------------------------
// 메인 함수 예제: 셰이더 프로그램을 생성하고 사용하는 방법
// -----------------------------------------------------------------------------
int main() {
// OpenGL ES 초기화 및 컨텍스트 생성은 생략 (각 플랫폼별로 다름)
// 버텍스 셰이더 소스 코드 예제
const char* vertexShaderSource =
"#version 300 es\n"
"layout(location = 0) in vec4 a_Position;\n"
"void main() {\n"
" gl_Position = a_Position;\n"
"}\n";
// 프래그먼트 셰이더 소스 코드 예제
const char* fragmentShaderSource =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 outColor;\n"
"void main() {\n"
" outColor = vec4(1.0, 0.0, 0.0, 1.0);\n" // 빨간색 출력
"}\n";
// 셰이더 프로그램 생성 (컴파일, 첨부, 링킹, 검증)
GLuint program = createProgram(vertexShaderSource, fragmentShaderSource);
if (program == 0) {
printf("셰이더 프로그램 생성 실패.\n");
return -1;
}
// 9) 셰이더 프로그램 사용: 렌더링 전에 반드시 프로그램을 활성화
glUseProgram(program);
// ... 이후 렌더링 관련 코드 작성 ...
return 0;
}
1) 프로그램이 여러개라면 ?
- 프로그램을 관리하는 프로그램 매니저가 필요하다.
2) 셰이더 코드가 코드가 아니라 파일로 존재한다면, 매번 파일로딩을 하면 성능 문제
- 셰이더 코드 캐싱 필요
3) 셰이더가 여러개라면 ?
- 셰이더를 컴파일 및 관리를 할 셰이더 매니저 필요
예제에서 구현된 셰이더 빌드 구조
ProgramManager | Program(const char*) | 지정한 이름("Cube")의 프로그램이 이미 존재하는지 확인하여, 있으면 해당 프로그램 객체를 반환합니다. |
ProgramInit(const char*) | 지정한 이름("Cube")의 새로운 프로그램 객체를 생성 및 초기화합니다. | |
AddProgram(PROGRAM*) | 생성된 프로그램 객체를 내부 리스트나 관리 구조체에 추가하여 관리합니다. | |
ProgramLink(PROGRAM*, int) | 첨부된 셰이더들을 기반으로 프로그램 객체를 링킹(Link)하고, 링킹 성공 여부를 반환합니다. (오류 발생시 종료) | |
ShaderManager | ShaderInit(const char*, GLenum) | 주어진 소스 참조(예: VERTEX_SHADER_PRG, FRAGMENT_SHADER_PRG)와 셰이더 타입(GL_VERTEX_SHADER, GL_FRAGMENT_SHADER)을 기반으로 셰이더 객체를 생성합니다. |
ShaderCompile(셰이더객체, const char*, int) | 제공된 셰이더 소스 코드를 컴파일하며, 컴파일 성공 여부를 반환합니다. (실패 시 오류 로그 출력 후 종료) | |
기타 관련 함수 | reserveCache(const char*, bool) | 셰이더 소스 코드를 읽어오기 위한 캐시 버퍼를 할당하여 소스 코드를 임시로 저장합니다. |
freeCache(CACHE*) | 사용이 끝난 캐시 버퍼를 해제하여 메모리 누수를 방지합니다. |
1.프로그램 생성 후 프로그램 매니저에 등록
2.프로그램 객체에서 버텍스, 프래그먼트 셰이더 등록
3.셰이더 캐시 생성
4.셰이더 컴파일
5.셰이더매니저에서 프로그램 링킹
6.프로그램 사용.
program = ProgramManagerObj->ProgramInit( ( char * )"Cube" );
ProgramManagerObj->AddProgram( program );
program->VertexShader = ShaderManager::ShaderInit( VERTEX_SHADER_PRG, GL_VERTEX_SHADER );
program->FragmentShader = ShaderManager::ShaderInit( FRAGMENT_SHADER_PRG, GL_FRAGMENT_SHADER );
CACHE *m = reserveCache( VERTEX_SHADER_PRG, true );
ShaderManager::ShaderCompile( program->VertexShader, ( char * )m->buffer, 1 )
m = reserveCache( FRAGMENT_SHADER_PRG, true );
ShaderManager::ShaderCompile( program->FragmentShader, ( char * )m->buffer, 1 )
ProgramManagerObj->ProgramLink( program, 1 )
glUseProgram( program->ProgramID );
return;
과제 > 아래 함수를 지우고 구현해보자.
void Cube::InitModel()
'Opengles 3.0 with Android' 카테고리의 다른 글
Chatper 3.1 Layout Qualifier, Grouping Uniforms(UBO) (0) | 2025.02.24 |
---|---|
Chapter 2.5 VAO ? VBO ? ( 참고 ) (1) | 2025.02.22 |
Chapter 2.4 Culling (0) | 2025.02.21 |
Chapter 2.3 Transform and Projection (0) | 2025.02.21 |
Chapter 2.6 Touch Event ( Skip ) (1) | 2025.02.21 |