본문 바로가기
Opengles 3.0 with Android

Chapter 6.3 Pattern Effect - Brick Style

by SimonLee 2025. 4. 22.

 

벽돌 무늬 셰이더

 

 

벽돌 무늬에서 필요한 값들은 다음과 같다.

// GLSL 쉐이더에서 "BrickColor" uniform의 위치를 얻음
char BrickColor = ProgramManagerObj->ProgramGetUniformLocation(program, (char*)"BrickColor");

// GLSL 쉐이더에서 "MortarColor" (시멘트 색상) uniform의 위치를 얻음
char MortarColor = ProgramManagerObj->ProgramGetUniformLocation(program, (char*)"MortarColor");

// 하나의 벽돌 셀 크기 (width, height)를 지정하는 uniform 위치
char RectangularSize = ProgramManagerObj->ProgramGetUniformLocation(program, (char*)"RectangularSize");

// 셀 안에서 벽돌이 차지하는 비율 (x%, y%)을 지정하는 uniform 위치
char BrickPercent = ProgramManagerObj->ProgramGetUniformLocation(program, (char*)"BrickPercent");

if (BrickColor >= 0){
    // 벽돌 색상을 빨간 계열로 설정 (RGB: 1.0, 0.3, 0.2)
    glUniform3f(BrickColor, 1.0, 0.3, 0.2);
}

if (MortarColor >= 0){
    // 시멘트 색상을 밝은 회색 계열로 설정 (RGB: 0.85, 0.86, 0.84)
    glUniform3f(MortarColor, 0.85, 0.86, 0.84);
}

if (RectangularSize >= 0){
	// 벽돌 셀 하나의 크기를 (0.50, 0.10)으로 설정 (가로 0.5, 세로 0.1 단위)
    glUniform2f(RectangularSize, 0.50, 0.10);
}

if (BrickPercent >= 0){
    // 벽돌이 셀 내에서 차지하는 비율을 90% x축, 85% y축으로 설정
    // 즉, 나머지 10%, 15%는 시멘트로 간주
    glUniform2f(BrickPercent, 0.90, 0.85);
}

 

Vertex Shader

#version 300 es
// Vertex information
layout(location = 0) in vec4  VertexPosition;
layout(location = 1) in vec3  Normal;

// Model View Project matrix
uniform mat4    ModelViewProjectionMatrix;
uniform mat4    ModelViewMatrix;
uniform mat3    NormalMatrix;

out vec3    nNormal;
out vec3    eyeCoord;
out vec3    ObjectCoord;

void main() 
{
    nNormal     = normalize ( NormalMatrix * Normal );
    eyeCoord    = vec3 ( ModelViewMatrix * VertexPosition );
    ObjectCoord = VertexPosition.xyz;

    gl_Position = ModelViewProjectionMatrix * VertexPosition;
}

 

Fragment Shader

아래 코드는 지그재그나 체크무늬를 만들때 자주 사용하는 코드이다.
- if (fract(position.y * 0.5 ) > 0.5) position.x += 0.5;

position.y 값의 범위 fract(position.y * 0.5의 값
0 ~ 1 < 0.5
1 ~ 2 > 0.5
2 ~ 3 < 0.5
3 ~ 4 > 0.5

즉 Y의 정수값이 홀수인 경우만, 조건이 true가 된다.

그러므로 홀수인 경우 x 좌표가 우측으로 0.5 이동하기 때문에 벽돌이 지그재그 형태로 보인다.

 

#version 300 es
precision mediump float;

uniform vec3    MaterialAmbient;
uniform vec3    MaterialSpecular;
uniform vec3    MaterialDiffuse;

uniform vec3    LightAmbient;
uniform vec3    LightSpecular;
uniform vec3    LightDiffuse;

uniform vec3    LightPosition;
uniform float   ShininessFactor;

in vec3    nNormal;
in vec3    eyeCoord;
in vec3    ObjectCoord;

layout(location = 0) out vec4 FinalColor;

// Brick uniform parameters
uniform vec3  BrickColor, MortarColor;
uniform vec2  RectangularSize, BrickPercent;

vec3 PhongShading()
{
    vec3 normalDir   = normalize ( nNormal );
    vec3 normalPosition = normalize( eyeCoord );
    vec3 nLight    = normalize( LightPosition - eyeCoord );
    
    // Diffuse Intensity
    float cosAngle = max( 0.0, dot( normalDir, nLight ));

    // Specular Intensity
    vec3 V       = -normalPosition;
    vec3 R       = reflect( -nLight, normalDir );
    float sIntensity 	= pow( max( 0.0, dot( R, V ) ), ShininessFactor );

    // ADS color as result of Material & Light interaction
    vec3 ambient    = MaterialAmbient  * LightAmbient;
    vec3 diffuse    = MaterialDiffuse  * LightDiffuse * cosAngle;
    vec3 specular   = MaterialSpecular * LightSpecular * sIntensity;

    return ambient + diffuse + specular;
}

vec3  color;
vec2  position, useBrick;

void main() {

    // 오브젝트 공간 좌표를 벽돌 셀 크기로 나눠서, 각 픽셀이 몇 번째 셀에 있는지 구함
    position = ObjectCoord.xy / RectangularSize;

    // 홀수 번째 y줄에서는 벽돌 위치를 반 셀만큼 x축으로 밀어 지그재그(벽돌 무늬)를 만듦
    if (fract(position.y * 0.5) > 0.5) {
        position.x += 0.5;
    }

    // 셀 내부의 상대 좌표 (0~1 범위)로 변환
    position = fract(position);

    // step(edge, x): x < edge → 0, x ≥ edge → 1
    // → x, y 좌표가 BrickPercent보다 작을 때만 벽돌 내부로 판단
    useBrick = step(position, BrickPercent);

    // 벽돌 내부면 BrickColor, 아니면 MortarColor(시멘트 색)를 사용
    color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);

    // Phong 조명 효과를 색상에 곱한 후 최종 출력
    FinalColor = vec4(color * PhongShading(), 1.0);
}

'Opengles 3.0 with Android' 카테고리의 다른 글

Chapter 6.4 Polka Dot  (0) 2025.04.24
Chapter 6.1 Pattern Effect - Circle  (0) 2025.04.16
Chapter 6.0 Warble Effect  (0) 2025.04.16
Chapter 5.2 Multi Light  (0) 2025.04.15
Chapter 5.1 Phong Shader  (0) 2025.03.24