GLSL
카테고리: OpenGL
태그: Graphics
Main Reference
- Learn OpenGL
- Rinthel Kwon - OpenGL Lecture
Shader Format
#version version_number
in type in_variable_name;
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
void main() {
// process input(s) and do some weird graphics stuff ...
// output processed stuff to output variable
out_variable_name = weird_stuff_we_processed;
}
in
/out
: 파이프라인에서 shader들의 입/출력- ex) vertex shader에서 out으로 지정한 output을 fragment shader에서 in으로 받아옴
- program에서 shader들 link할 때 in/out 변수의 타입, 이름을 검사
- Vertex Shader의 경우 VAO로 부터 데이터를 받아와야 하므로 input 받는 방식이 약간 다름
layout (location = 0) in vec3 aPos
uniform
: 병렬로 수행되는 shader thread들이 동일한 값을 사용해야 하는 경우 사용하는 global variable- ex) 모든 vertex에서 동일한 color 값을 사용할 경우, cpu에서 해당 값만 넘겨주면 됨
- ex) color값이 time에 따라 변하는 경우 cpu에서 time 변수 넘겨줄 때
- 사용법은 아래에서 다시 설명
- 모든 shader는 main 함수를 가져야 함
Uniform Variable
// context.cpp
// ...
auto loc = glGetUniformLocation(m_program->Get(), "color");
m_program->Use();
glUniform4f(loc, 1.0f, 1.0f, 0.0f, 1.0f);
// ...
glGetUniformLocation()
함수를 이용해 program object로 부터 uniform handler 얻기- “color”라는 변수 명을 이용해 location 찾음
glUniformXXXX
함수를 이용해 값 전달- 4f : float 4개
glUniform4fv
포인터 타입으로 값을 넘겨줄 경우 끝에 v가 붙음
GLSL Data Type
Type
- X : 2, 3, 4
- vecX : float형 벡터
- bvecX : bool형 벡터
- ivecX : int형 벡터
- uvecX : uint형 벡터
- dvecX : double형 벡터
- 마찬가지로
- matX, bmatX, …, dmatX 존재
Initialize
vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0);
- 벡터의 초기값은 생성자를 이용해 선언
- 다른 벡터를 섞어서 사용도 가능
Vector Index
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;
- 벡터의 인덱스는 xyzw, rgba 등으로 접근 가능
- 얻고 싶은 인덱스를 순서에 상관없이 사용할 수 있음
Example
// context.cpp
float vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // top right, red
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom right, green
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom left, blue
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, // top left, yellow
};
uint32_t indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3, // second triangle
};
m_vertexLayout = VertexLayout::Create();
m_vertexBuffer = Buffer::CreateWithData(GL_ARRAY_BUFFER, GL_STATIC_DRAW, vertices, sizeof(float) * 24);
m_vertexLayout->SetAttrib(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
m_vertexLayout->SetAttrib(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, sizeof(float) * 3);
m_indexBuffer = Buffer::CreateWithData(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, indices, sizeof(uint32_t) * 6);
ShaderPtr vertShader = Shader::CreateFromFile("./shader/per_vertex_color.vs", GL_VERTEX_SHADER);
ShaderPtr fragShader = Shader::CreateFromFile("./shader/per_vertex_color.fs", GL_FRAGMENT_SHADER);
- 이번에는 vertex마다 color값을 다르게 지정
- position에 관한 VBO, color에 관한 VBO를 각각 생성 후 바인딩
// vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec4 vertexColor;
void main() {
gl_Position = vec4(aPos, 1.0);
vertexColor = vec4(aColor, 1.0);
}
- vertex shader에서는 layout-location을 이용해 position, color값 받아온 후
- 해당 color값을 fragment shader로 전달(output)
#version 330 core
in vec4 vertexColor;
out vec4 fragColor;
void main() {
fragColor = vertexColor;
}
- fragment shader에서는 넘겨받은 color를 칠하기만 하면 되는데
- 주의할 점은 rasterization이 끝난 후 (interpolation된) 픽셀들이 넘어온다는 점
댓글 남기기