將立方體貼圖投影到 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 #opengl #rendering






相關問題

OpenGL等圖形庫的目的是什麼? (What is the purpose of a graphics library such as OpenGL?)

Blender: Kubus Mustahil (Blender: Impossible Cube)

隨機移動的圖像被屏幕的左上角吸引 (Randomly moving images are attracted by the top-left corner of the screen)

Bản đồ họa tiết Android OpenGLES 2.0 không hoạt động (Android OpenGLES 2.0 Texture Mapping Does Not Work)

用於顯示位圖和處理按鈕按下的簡單框架 (Simple Frameworks for Displaying Bitmaps and Handling Button Presses)

繪製後如何填充多邊形 (How to fill a polygon after drawing)

Java Swing/Graphics - repaint() 或 validate() 不起作用? (Java Swing/Graphics - repaint() or validate() doesn't work?)

繪製多邊形:找不到錯誤 (Drawing Polygon : unable to find error)

半透明 JButton:對像出現在背景中 (Semi-Transparent JButton: Objects appear in Background)

更改 BufferedImage 的 alpha 值? (Change the alpha value of a BufferedImage?)

圖像處理公式可生成類似通過 Mac 相機拍攝的照片的效果 (Image manipulation formula to generate effects like pictures taken via Mac's camera)

如何在 MATLAB 中為一組向量的旋轉設置動畫? (How do I animate the rotation of a set of vectors in MATLAB?)







留言討論