Notice
Recent Posts
Recent Comments
Link
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Archives
Today
Total
관리 메뉴

codingfarm

WebGL과 GLSL 본문

computer graphics/Three.js

WebGL과 GLSL

scarecrow1992 2026. 5. 30. 14:00

참고

https://webglfundamentals.org/webgl/lessons/ko/webgl-fundamentals.html

https://webgl2fundamentals.org/webgl/lessons/ko/webgl-fundamentals.html

 

1. 소개

WebGL은 브라우저의 <canvas> context를 통해 GPU를 사용하여 2D/3D 렌더링을 가속하기위한 API 이다. Scene이나 Camera 같은 추상화된 정보 없으며, 점/선/삼각형을 렌더링 하기 위해 GPU 정점, 쉐이더,텍스처, 상태를 전달하고 draw call을 실행하는 저수준기능만을 제공한다. 쉐이더는 GPU의 각 파이프라인에 실행되는 프로그램이며, GLSL은 이 쉐이더를 작성하기 위한 언이다.

WebGL은 WebGL과 WebGL2 두가지 버전으로 나뉘는데, WebGL1의 번거로움을 해결하기 위한 여러 extension들을 WebGL2에서 표준기능으로 포용한 버전에 가깝다. Three.jsWebGLRenderer는 WebGL2를 사용중이며, r163 이후의 버전부터 WebGL1을 지원하지 않는다.(링크) 그렇다고 WebGL2가 단순히 WebGL1의 extension들을 공식 기능으로 도입만 한것은 결코 아니다. 특히 UBO나 MRT 관련 기능들을 WebGL1에서 구현하기 위해서는 수많은 draw call이나 복잡한 shader가 필요하며 이는 성능차이로 이어질 수 있다. 즉, WebGL2WebGL1의 extension을 단순히 포함하기만하는 래퍼로써의 기능이 아닌, 상위호환격인 별도의 API라고 보는것이 옳다. 

GLSL(OpenGL Shading Language)는 OpenGL 계열 그래픽 API에서 GPU Shader를 작성하기 위한 C계열 언어이다. 브라우저라는 한정된 환경에서 효율적인 렌더링을 위해, 경량화된 그래픽 API인 OpenGL ES를 웹에 맞게 설계한것이 WebGL이며, 이에따라 shading 언어도 GLSL을 사용하게되었다. Three.js에서는 GLSL ES를 사용중이며 기본적으로 GLSL ES 1.00을 사용하되, GLSL ES 3.00도 지원한다.

 

2. 버전별 정보

 WebGL1/2와 GLSL ES 1.00/3.00 버전차이에 따른 차이점을 간략히 정리하고자한다.

 

2-1) WebGL1 / 2

WebGL1의 불편함을 감수하기 위해 제공되던 Extension들을 공식 기능으로 도입한것이 WebGL2이다.

대표적으로 VAO가 있으며, vectex attribute에 대한 데이터 관리를 효율적으로 추상화하는데 유용하다.

더 자세한 정보는 링크에 정리되어 있으며, 주요 차이는 아래와 같이 정리된다.

  • VAO(Vertex Array Object) 지원
  • instancing 지원
  • MRT(Multi Render Target)
  • 텍스쳐 타입 명시
    • gl.R8. gl.RGBA8, gl.R32F, gl. DEPTH_COMPONENT24 , gl. DEPTH24_STENCIL8...
  • UBO(Uniform Buffer Object) 지원
  •  Transform Feedback : vertex shader의 출력을 버퍼에 저장
  • Texture Array ( gl. TEXTURE_2D_ARRAY)
    • 타일맵, sprite atlas, material array
  • sampler 타입 확대
uniform sampler2D colorMap;
uniform isampler2D idMap;
uniform usampler2D objectIdMap;
uniform sampler2DShadow shadowMap;
uniform sampler3D volumeMap;
uniform sampler2DArray arrayMap;

object picking, clustered lighting, shadow mapping, volume rendering 등에 활용 가능

 

2-2) GLSL ES 1.00 / 3.00

GLSL ES의 1.00에서 3.00 버전업에 따른 주요 변화는 아래와 같다.

 

1) 암묵적 인터페이스에서 명시적인 인터페이스로

GLSL ES 1.00은 내장상태에 기대 암묵적으로 포용되던 관용구나 셰이더 언어들이 존재한다.

가령, 1.00 버전의 fragment shader 코드는 기본적으로 아래와 같다.

attribute vec3 position;
varying vec2 vUv;

void main() {
  gl_FragColor = vec4(1.0);
}

 

이 코드에서는 여러 정보들 언어차원에서 사실상 고정되어있다. 가령 gl_FragColor 또는 gl_FragData이다. 또한 vertex input은 attribute, stage간 전달은 varying, 텍스쳐 샘플링은 texture2D, textureCube 키워드로 정의된다.

 

하지만 3.00 버전의 shader 코드는 아래와 같다.

#version 300 es
layout(location = 0) in vec3 position;

out vec2 vUv;
#version 300 es
precision highp float;

in vec2 vUv;

layout(location = 0) out vec4 outColor;
layout(location = 1) out vec4 outNormal;

void main() {
  outColor = vec4(1.0);
  outNormal = vec4(0.0, 0.0, 1.0, 1.0);
}

정해진 이름의 내장 변수(gl_FragColor)에 쓰는 방식이 아닌, 셰이더가 자신의 입출력 인터페이스를 직접 선언하는 방식으로 바뀌었음이 확인된다.

GLSL ES 3.00은 고정적이고 관례적인 작성법을 탈피하여, 셰이더코드가 더 많은 GPU리소스 파이프라인 기능을 명확하게 표현하도록 탈바꿈되었음을 알 수 있다.

 

2)  색 계산이 아닌 데이터 연산 중심으로

1.00은 화면에 표기하기 위한 색상 출력에 집중되어 있다. 그렇기에 fragment shader의 최종 출력값도 사실상 gl_FragColor로 고정되며, 데이터 표현도 float vector 중심이다.
(vec2, vec3, vec4, sampler2D, samplerCube)

3.00은 색상 계산만이 아닌, GPU기반 데이터연산 중심으로 발전하였으며, 보다 다양한 데이터 타입과 연산들을 지원한다.
(uint, uvec2, uvec3, uvec4, isampler2D, sampler3D, sampler2DArray, bitwise Operation, texelFetch, textureSize, uniform blocks...)

즉, 기존 1.00 에서는 색상/좌표/법선과 같은 그래픽 데이터 중심이었다면, 3.00에서는 Id, index, 플래그, 레이어, uniform block 등 다양한 데이터에 대한 연산을 중심으로 확장되었다.

가령 1.00에서는 picking을 위해 id를 vec4 타입의 색상정보로 우회 표기해야했다.

gl_FragColor = vec4(encodedIdColor);

하지만3.00에서는 직접적으로 정수데이터를 다룰 수 있다.

#version 300 es
precision highp float;
precision highp usampler2D;

flat in uint vObjectId;

layout(location = 0) out uint outObjectId;

물론 int형 render target을 쓰기 위해서는 texture/render target 포맷 framebuffer 조건도 맞는 등 여러 조건이 따라오지만, 철학자체는 그래픽 렌더링(float only)에 그치지 않고, 범용 데이터 연산 방식으로 옮겨졌음을 확인할 수 있다.

1.00과 3.00의 주요 차이는 아래와 같이 정리될 수 있다.

GLSL ES 1.00 GLSL ES 3.00 목표
attribute in stage input 일반화
varying out / in stage 간 인터페이스 일반화
gl_FragColor 사용자 정의 out 출력 타겟 명시
texture2D, textureCube texture sampler 기반 함수 오버로드
gl_FragData[i] layout (location) out MRT 출력 명시

 

3. WebGL과 GLSL

WebGL은 GPU를 통해 점/선/면을 그리거나 일반 데이터를 연산하기 위한 API 이며, GLSL은 GPU에서 동작하는 프로그램을 작성하는 언어이다.

즉, 둘은 함께 사용되어야만 하는 관계이므로 버전별 호환성이 중요하다.

WebGL과 GLSL 간의 버전 호환은 간단히 아래와 같이 정리될 수 있다.

컨텍스트 GLSL
WebGL1 GLSL ES 1.00
WebGL2 GLSL ES 1.00 & 3.00

사실상 WebGL1은 GLSL ES 1.00 호환되며, WebGL2는 GLSL ES 3.00과 호환된다고 보면 된다.

WebGL2도 GLSL ES 1.00 을 사용 가능하지만, WebGL2의 여러 기능들 (UBO, MRT 등)을 본격적으로 쓰기 위해선 3.00 사용이 권장된다.

 

3-1) Three.js 환경

Three.js 의 THREE.WebGLRenderer는 WebGL2만을 지원한다. 하지만 three.js에 내장된 MeshStandardMaterial와 MeshPhysicalMaterial 등의 매터리얼등은 GLSL ES 1.00 으로 작성되었다. 또한 THREE.ShaderMaterialTHREE.RawShaderMaterialglslVersion: THREE.GLSL3 옵션을 넘기지 않는다면, 1.00버전으로 컴파일된다.

하지만 ShaderMaterial을 3.00으로 생성하여도, 1.00 과 마찬가지로 기본적인 uniform 이나 attribute 정보들은 Three.js가 직접 전달해준다.

[THREE.ShaderMaterial - 1.00]

const material = new THREE.ShaderMaterial({
  vertexShader: `
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec2 uv;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;

    varying vec2 vUv;

    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    precision highp float;

    varying vec2 vUv;

    void main() {
      gl_FragColor = vec4(vUv, 0.0, 1.0);
    }
  `
});

 

[THREE.ShaderMaterial - 3.00]

const material = new THREE.ShaderMaterial({
  glslVersion: THREE.GLSL3,

  vertexShader: `
    in vec3 position;
    in vec3 normal;
    in vec2 uv;

    uniform mat4 modelViewMatrix;
    uniform mat4 projectionMatrix;

    out vec2 vUv;

    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,

  fragmentShader: `
    precision highp float;

    in vec2 vUv;
    out vec4 outColor;

    void main() {
      outColor = vec4(vUv, 0.0, 1.0);
    }
  `
});

 

그렇기 때문에 ShaderMaterial 이나 RawShaderMaterial 을 통해 쉐이더를 직접 생성할 경우, 가급적 ES 3.00 버전으로 생성하고 해당 양식에 맞추어 작성하는것이 권장되나,

built-in material에서 shader chunk를 통해 replace 하는 방식으로 shader 코드를 가공한다면, ES 1.00 버전을 기준으로 작성해야한다.

 

'computer graphics > Three.js' 카테고리의 다른 글

PostProcessing EffectComposer  (0) 2026.01.01
R3F의 3D 컴포넌트  (0) 2026.01.01
Post Process  (0) 2025.12.27
Comments