42seoul 35

ShaderPixel - 4. 버텍스 셰이더에서 계산한 노말 값과 월드 좌표는 실제로 프래그먼트에 그려지는 픽셀의 월드 좌표와는 다르다

과제의A transluscent object (using volumetric ray-marching) with non-volumetric diffuse and specular lighting on its surface (like colored glass marble). Think to implement a mode to diplay one the specular/diffuse term of the lighting to verify that your lighting works.이부분에 해당하는 색구슬을 완성하였다. 이번에는 구슬 그리는데 삽질한 내용을 쓸 것이다. 우선 버텍스 셰이더에서 그 구슬을 그릴 공간을 구한다. 최적화하기위해 저 검은색 부분만 레이를 쏠 예정이다. 일단 저부분만 alpha값을 낮춰 ..

ShaderPixel - 3. 렌더링 전략 고민..

일단 과제에서 요구된 오브젝트 중 일부는 그냥 레이마칭으로 구현해야 하는 상황이었다.평소처럼 메쉬 기반으로 버텍스 셰이더에서 판단해서 그리면 되는 게 아니라 레이마칭을 적용해야 해서.. 메쉬랑 같이 사용하려면 깊이 정보를 직접 계산해줘야 했다. 이게 메쉬 기반 오브젝트가 혼합되어 있는 상황이라 더 어려워진다.  특히 지금 레이마칭을 적용해야 하는 오브젝트들은 블렌딩이나 반투명 효과를 주는 상황이 많아서, 뒷배경에 있는 오브젝트가 보이도록 해야 한다는 게 또 문제다.특히 반투명 구슬이나 구름 같은 오브젝트는 서로 영향을 주는 상호작용을 고려해야 한다.예를 들어 구름 뒤에 보이는 반투명 구슬, 혹은 구슬에 비치는 구름처럼 보이도록 구현하려면, 같은 셰이더 안에서 계산해야 이런 상호작용이 쉬워진다. 각각의 셰..

ShaderPixel - 2. 바닥 구성 (Normal map)

이번에는 Normal Map을 사용해 바닥 표면을 표현했다.알베도 텍스처와 Normal Map을 적용하여 표면의 질감과 조명이 자연스럽게 반응하도록 만들었다. Tangent-Bitangent-Normal (TBN) 행렬을 활용해 조명 계산을 위한 텍스처 공간(Tangent Space) 변환을 적용하여 표면의 기복에 따라 조명이 반사되도록 구현하였다.바닥 텍스처 및 모델 초기화 코드먼저 바닥에 사용할 알베도 텍스처와 Normal Map을 로드하고, 바닥의 크기와 회전 정보를 설정했다.// Normal Map 셰이더 프로그램 로드m_normalProgram = Program::Create("./shader/normal.vs", "./shader/normal.fs");// 바닥 알베도 텍스처와 Normal M..

ShaderPixel - 1. 배경 구성 (Skybox)

이번 작업에서는 HDR 파노라마 이미지를 큐브맵 텍스처로 변환해 스카이박스(Skybox)를 구성했다.캡처 초기화 코드HDR 이미지를 불러온 후, 큐브맵 텍스처로 변환하기 위해 큐브 프레임버퍼와 뷰 행렬을 설정했다.// HDR 이미지를 로드하여 Texture 객체로 생성m_hdrMap = Texture::CreateFromImage(Image::Load("./image/god_rays_sky_dome_8k.hdr").get());// 스피어리컬 맵에서 큐브맵으로 변환하는 셰이더 프로그램 로드m_sphericalMapProgram = Program::Create("./shader/spherical_map.vs", "./shader/spherical_map.fs");// 큐브맵 텍스처 생성 (2048x2048..

ShaderPixel - 0. 과제 해석

프로젝트 개요목적ShaderPixel 프로젝트의 주된 목적은 OpenGL을 통해 다양한 그래픽 객체가 논리적으로 연결되도록 매트릭스 스택을 조작하며, 쉐이더를 활용해 고차원적인 렌더링을 구현하는 것이다. 신체 부위와 같은 독립적인 개체들이 상호 연결된 상태로 동작할 수 있도록 구성하면서, 쉐이더의 복잡한 조명과 최적화를 경험할 수 있다. 또한 이 프로젝트를 통해 3D 공간에서 창의적인 비주얼 효과를 표현할 수 있다.일반적인 규칙Makefile 또는 빌드 파일 제공: 프로젝트 컴파일을 위해 Makefile, CMake 또는 Premake 등의 빌드 파일을 제공해야 한다.OpenGL 4.0 이상 사용: OpenGL을 사용할 경우 최소 버전 4.0을 사용하며, 쉐이더는 버전 330을 사용해야 한다. Vulka..

HumanGL - 7. ImGui 추가

이번에는 ImGui를 이용해 사람 모델의 각 파츠를 실시간으로 조정할 수 있는 인터페이스를 추가했다. 이제 각 파츠의 계층적 구조를 더 직관적으로 확인할 수 있게 되었고, 다양한 조정이 가능해졌다. ImGui 추가하기렌더링 함수에 ImGui를 추가하면서, 사람 모델의 각 파츠의 변형 값을 실시간으로 조정할 수 있도록 했다. Context::Render() 함수에서 ImGui 위젯을 사용해 각 파츠의 스케일, 색상, 회전 등을 다룰 수 있는 슬라이더와 버튼을 배치했다.void Context::Render() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); // ImGui 인터페이스 추가 if ..

HumanGL - 6. Animation 적용

이제 사람 모델에 애니메이션 기능을 적용했다. 각 파트의 움직임에 맞춰 회전 축(피벗)을 설정하고, 애니메이션 동작을 적용한 것이 주요 변경 사항이다.피벗 설정 및 Transform 계산 변경사람의 몸을 그리는 과정에서 파츠마다 회전할 때 피벗 위치가 달라야 했다. 그래서 각 파트에 맞는 회전 중심을 계산해 적용했다.DrawNode 함수 변경void Human::DrawNode(const Node& node, const Mesh* mesh, const Program* program, const sglm::mat4& transform) { sglm::vec3 rotationPivot; if (node.part->name == "body") { rotationPivot = sglm::..

HumanGL - 5. transform 행렬 계산식 변경

전에 발견한 문제를 해결하기 위해 transform 행렬 계산식을 수정했다. 이전 방식에서는 스케일이 translate에 영향을 주어 직관적이지 않았고, 이를 독립적으로 계산하려 했던 것이 문제의 원인이었다.문제 원인 분석기존에는 transform 계산식을 다음과 같이 적용했다:transform = projection * view * modelmodel = translate * rotate * scale그런데 상속을 받을 때, 스케일을 translate과 독립적으로 적용하려다 보니 다음과 같은 방식으로 계산했다:model = 부모 translate * 자식 translate * 부모 rotate * 자식 rotate * 부모 scale * 자식 scale이 방식으로는 부모와 자식의 좌표계가 서로 독립적으..

HumanGL - 4. 문제 발견

사람을 그리고 테스트하자마자 문제가 발생했다. static float scale = 1.0f;static float dir = 0.01f;scale += dir;if (scale >= 2.0f) dir = -0.01f;if (scale 렌더링될 때마다 스케일을 변하게 해줬는데, 영상에서 볼 수 있듯이 각각의 오브젝트가 동시에 커졌다. 자세히 살펴보면 위치는 고정된 상태로 크기만 변하는 걸 확인할 수 있다.이 현상이 꽤 이상해서 돌려봤는데...sglm::mat4 rotateModel = sglm::mat4(1.0f);static float angle = 0.0f;angle += 1.0f;if (angle >= 360.0f) angle = 0.0f;rotateModel = sglm::rotate(..

HumanGL - 3. 사람 그리기

이제 상자의 스케일을 조정하고, 몸의 각 파트를 계층적으로 나누어 사람을 그려주었다. 하위 단계의 값들은 상위 단계의 값을 계승하며, 각 파트는 부모의 상대 좌표를 기반으로 계산된다. 이렇게 계층 구조로 설정된 방식은 게임 엔진의 트리 구조와 비슷하게 동작한다.Human 초기화먼저 사람의 각 신체 부위를 초기화하는 작업부터 시작했다. 몸통을 중심으로 머리, 팔, 다리 등 모든 부위를 트리 구조로 정리해주었다. 각 파트는 위치(translate), 회전(rotate), 크기(scale), 색상(color) 정보를 가지며, 이 값들은 계층적으로 상위 값을 계승한다.void Human::Init() { m_body = {sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(0.0f, ..