void EdgeDetection::Render()
{
SetUpPerspectiveProjection(); // 3차원 원근 효과 적용
// 원숭이 3d obj 렌더링을 한다.
// FBO에 렌더링이 되고, 퐁라이팅이 적용된다.
RenderObj();
// FBO를 2차원 평면에 렌더링 하기 위한 ortho Projection 적용
SetUpOrthoProjection();
// 엠보싱 효과 적용
EdgeDetect();
}
void EdgeDetection::RenderObj()
{
// 1. 현재 바인딩된 기본 프레임버퍼(Default Framebuffer)의 ID를 가져옵니다.
// 이는 나중에 프레임버퍼를 기본 상태로 복원하기 위해 필요합니다.
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &DefaultFBO);
// 2. 사용자 정의 프레임버퍼 객체(FBO)를 바인딩합니다.
// 이후의 렌더링 결과가 이 프레임버퍼로 출력됩니다.
glBindFramebuffer(GL_FRAMEBUFFER, FboId);
// 3. 화면(Viewport)의 크기를 프레임버퍼 크기(TEXTURE_WIDTH, TEXTURE_HEIGHT)로 설정합니다.
glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
// 4. 프레임버퍼를 초기화합니다.
// 배경색을 검정색(0.0f, 0.0f, 0.0f)으로 설정하고, 이를 클리어합니다.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 5. 프레임버퍼의 컬러 첨부(Attachment)로 텍스처를 설정합니다.
// 렌더링된 컬러 데이터를 `textureId`에 저장하도록 지정합니다.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
// 6. 프레임버퍼의 깊이 첨부(Attachment)로 텍스처를 설정합니다.
// 렌더링된 깊이 데이터를 `depthTextureId`에 저장하도록 지정합니다.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureId, 0);
// 7. 프레임버퍼를 다시 초기화하여 이전의 렌더링 잔여물을 제거합니다.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 8. 모델 데이터를 렌더링합니다.
// 여기서 렌더링된 결과는 `textureId`(컬러)와 `depthTextureId`(깊이)에 저장됩니다.
objModel->Render();
// 9. 렌더링이 끝난 후 기본 프레임버퍼로 바인딩을 복원합니다.
// 이후의 렌더링은 기본 프레임버퍼(화면)에 출력됩니다.
glBindFramebuffer(GL_FRAMEBUFFER, DefaultFBO);
}
엠보싱 프래그먼트 코드
#version 300 es
precision mediump float;
// 텍스처 좌표 (버텍스 셰이더에서 전달된 값)
in vec2 TexCoord;
// 유니폼 변수
uniform vec2 pixelSize; // 한 픽셀의 크기 (텍스처 좌표 기준)
uniform sampler2D Tex1; // 입력 텍스처 샘플러
uniform float ScreenCoordinateX; // 화면 좌표 기준선 (사용 안 함, dlgmlals3 참고)
// 출력 색상
layout(location = 0) out vec4 outColor;
void main()
{
// 임시로 기준선을 하드코딩 (ScreenCoordinateX 유니폼 대신 사용)
float ScreenCoordX = 550.0f;
// 엠보싱 밝기를 조정하는 값 (기본 밝기에 더해줌)
float EmbossBrightness = 0.7f;
// 빨간색 선을 그려 기준선을 시각화 (±3 픽셀 두께)
if(gl_FragCoord.x < ScreenCoordX + 3.0 && gl_FragCoord.x > ScreenCoordX - 3.0) {
outColor = vec4(1.0, 0.0, 0.0, 1.0); // 빨간색
return; // 빨간색을 그린 후 더 이상의 처리는 필요 없음
}
// 기준선 오른쪽 영역: 엠보싱 효과 적용
if (gl_FragCoord.x > ScreenCoordX) {
// 현재 텍셀 (기준점) 샘플링
vec3 p00 = texture(Tex1, TexCoord).rgb;
// 수직 방향 (아래쪽 텍셀) 샘플링
vec3 p01 = texture(Tex1, TexCoord + vec2(0.0, pixelSize.y)).rgb;
// 수평 방향 (오른쪽 텍셀) 샘플링
vec3 p02 = texture(Tex1, TexCoord + vec2(pixelSize.x, 0.0)).rgb;
// 수직 방향 텍셀 차이
vec3 diffY = p00 - p01;
// 수평 방향 텍셀 차이
vec3 diffX = p00 - p02;
// RGB 채널 중 가장 큰 절대값 (수직 방향 차이)
float max = diffY.r;
if(abs(diffY.g) > abs(max)) { max = diffY.g; }
if(abs(diffY.b) > abs(max)) { max = diffY.b; }
// RGB 채널 중 가장 큰 절대값 (수평 방향 차이)
if(abs(diffX.r) > abs(max)) { max = diffX.r; }
if(abs(diffX.g) > abs(max)) { max = diffX.g; }
if(abs(diffX.b) > abs(max)) { max = diffX.b; }
// 밝기 값 계산
float gray = clamp(max + EmbossBrightness, 0.0, 1.0); // 결과를 [0.0, 1.0]로 제한
// 흑백으로 변환하여 출력
outColor = vec4(gray, gray, gray, 1.0);
}
// 기준선 왼쪽 영역: 원본 텍스처 출력
else {
outColor = texture(Tex1, TexCoord); // 원본 텍스처 색상
}
return; // 셰이더 종료
}
주변색상과 픽셀값이 차이가 날수록 max 값은 커지게 되고, gray 값이 점점 밝아지게 된다.
즉 경계 부분이 밝아지게 되고, 빛에 닿는 부분 처럼 느껴져서 엠보싱 효과처럼 보인다.
'Opengles 3.0 with Android' 카테고리의 다른 글
10.2 Object Picking ( with Raytracing ) (0) | 2025.01.30 |
---|---|
10.1 Scene Graph (Transformation Graph) (0) | 2025.01.30 |
9.3 툰 셰이딩: 엣지 디텍팅과 카툰화 (0) | 2024.12.25 |
Chapter 9.2 Gawsian Blur ( 2 step ) (0) | 2024.12.01 |
Chapter 7.5. displace map (0) | 2024.11.18 |