큐브맵을 2D 텍스처로 투영 (Project cubemap to 2D texture)


문제 설명

큐브맵을 2D 텍스처로 투영 (Project cubemap to 2D texture)

다음과 같이 전체를 2D 텍스처에 투영하여 큐브맵으로 렌더링 기능을 디버그하고 싶습니다.

텍스처 셰이더에서 렌더링할 때 UV 텍스처 좌표만 사용할 수 있습니다((0,0) ~ (1,1) 범위). 단일 드로우 콜에서 큐브맵을 화면에 어떻게 투영할 수 있습니까?


참조 솔루션

방법 1:

You can do this by rendering 6 quads and using 3D texture coords (s,t,p) pointing to each vertex of the cube so 8 variations of ( +/‑1,+/‑1,+/‑1 ).

The UV 2D coords (s,t) like 4 variations of (0/1,0/1) are not usable for whole CUBE_MAP only for its individual sides.

Look for txr_skybox in here

on how CUBE_MAP is used in fragment shader.

PS in OpenGL the texture coords are called s,t,p,q instead of u,v,w,...

Here related QA:

방법 2:

My answer is essentially the same as the one accepted one, but I have used this very technique to debug my depth‑cubemap (used for shadowcasting) in my current project, so I thought I would include a working sample of the fragment shader code I used.

Unfolding cubemap

This is supposed to be rendered to a rectangle on top of the screen with aspect ratio 3/4 directly on the screen and with s,t going from (0,0) in the lower‑left corner to (1,1) at the upper‑right corner.

Note that in this case, the cubemap I use is inverted, that is objects to the +(x,y,z) side of the cubemap origen is rendered to ‑(x,y,z), and the direction I choose as up for the top/bottom quads are completely arbitrary; so to get this example to work you may need to change some signs or swap s and t some times, also note that I here only read one channel, as it is debth map:

Fragment shader code for a quad‑map as the one in the question:

//Should work in most other versions
#version 400 core

uniform samplerCube dynamic_texture;

out vec4 out_color;
in vec2 ST;

void main()
{
    //In this example i use a debthmap with only 1 channel, but the projection should work with a colored cubemap to, just replace this with a vec3 or vec4    
    float debth=0;
    vec2 localST=ST;




    //Scale Tex coordinates such that each quad has local coordinates from 0,0 to 1,1
    localST.t = mod(localST.t*3,1);
    localST.s = mod(localST.s*4,1);


    //Due to the way my debth‑cubemap is rendered, objects to the ‑x,y,z side is projected to the positive x,y,z side


    //Inside where tob/bottom is to be drawn?
    if (ST.s*4>1 && ST.s*4<2)
    {
        //Bottom (‑y) quad
        if (ST.t*3.f < 1)
        {
            vec3 dir=vec3(localST.s*2‑1,1,localST.t*2‑1);//Get lower y texture, which is projected to the +y part of my cubemap

            debth = texture( dynamic_texture, dir ).r;
        }
        //top (+y) quad
        else if (ST.t*3.f > 2)
        {
            vec3 dir=vec3(localST.s*2‑1,‑1,‑localST.t*2+1);//Due to the (arbitrary) way I choose as up in my debth‑viewmatrix, i her emultiply the latter coordinate with ‑1

            debth = texture( dynamic_texture, dir ).r;
        }
        else//Front (‑z) quad
        {
            vec3 dir=vec3(localST.s*2‑1,‑localST.t*2+1,1);

            debth = texture( dynamic_texture, dir ).r;

        }


    }
    //If not, only these ranges should be drawn
    else if (ST.t*3.f > 1 && ST.t*3 < 2)
    {
        if (ST.x*4.f < 1)//left (‑x) quad
        {
            vec3 dir=vec3(‑1,‑localST.t*2+1,localST.s*2‑1);

            debth = texture( dynamic_texture, dir ).r;

        }
        else if (ST.x*4.f < 3)//right (+x) quad (front was done above)
        {
            vec3 dir=vec3(1,‑localST.t*2+1,‑localST.s*2+1);

            debth = texture( dynamic_texture, dir ).r;

        }
        else //back (+z) quad 
        {
            vec3 dir=vec3(‑localST.s*2+1,‑localST.t*2+1,‑1);

            debth = texture( dynamic_texture, dir ).r;

        }


    }
    else//Tob/bottom, but outside where we need to put something
    {
        discard;//No need to add fancy semi transparant borders for quads, this is just for debugging purpose after all
    }

    out_color = vec4(vec3(debth),1);
}

Here is a screenshot of this technique used to render my depth‑map in the lower‑right corner of the screen (rendering with a point‑light source placed at the very center of an empty room with no other objects than the walls and the player character):

Looking at a wall, with the player's shadow visible

Equirectangular projection

I must, however, say that I prefer using an equirectangular projection for debugging cubemaps, as it doesn't have any holes in it; and, luckily, these are even easier to make than unfolded cubemaps, just use a fragment shader like this (still with s,t going from (0,0) to (1,1) from lower‑left to upper‑right corner), but this time with aspect ratio 1/2:

//Should work in most other versions
#version 400 core

uniform samplerCube dynamic_texture;

out vec4 out_color;
in vec2 ST;

void main()
{
    float phi=ST.s*3.1415*2;
    float theta=(‑ST.t+0.5)*3.1415;


    vec3 dir = vec3(cos(phi)*cos(theta),sin(theta),sin(phi)*cos(theta));

    //In this example i use a debthmap with only 1 channel, but the projection should work with a colored cubemap to
    float debth = texture( dynamic_texture, dir ).r;
    out_color = vec4(vec3(debth),1);
}

Here is a screenshot where an equirectangular projection is used to display my depth‑map in the lower‑right corner:

Equirectangula

(by Bruno SenaSpektreNikolaj)

참조 문서

  1. Project cubemap to 2D texture (CC BY‑SA 2.5/3.0/4.0)

#graphics #rendering #opengl






관련 질문

Triangulate a quad with a hole in it using tessellation (Triangulate a quad with a hole in it using tessellation)

기존 이미지가 화면에 그려지지 않는 이유는 무엇입니까? (Why won't my existing image draw to the screen?)

barplot()에서 정보를 저장하고 그래프를 표시하지 않는 방법 (How to save information from barplot() and not displaying the graph)

Java 시간에 따라 사각형을 이동하는 방법 (java how to make a rectangle move by time)

큐브맵을 2D 텍스처로 투영 (Project cubemap to 2D texture)

OpenGL & Qt : 마우스 오버 시 레이블 표시 (OpenGL & Qt : display a label on the mouseover)

프리파스칼에서 기능적 그래픽을 얻으려면 어떻게 해야 합니까? (How do I get functional graphics from freepascal?)

스크래치 및 승리 (Scratch and win)

벡터 병합 알고리즘 도움말 (Help with algorithm for merging vectors)

WPF - ScreenSaver 그래픽 성능 향상 (WPF - ScreenSaver graphics performance improvements)

Java, 패널용 그래픽 개체 생성 및 편집? (Java, create and edit a Graphics Object for Panel?)

정점 셰이더의 out 변수는 어떻게 보간됩니까? (How are the out variables of vertex shader interpolated?)







코멘트