0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PBR sahder を動かす

Last updated at Posted at 2023-05-04

OpenGL チュートリアルの

のサンプルコード

を元に、 pbr shader を自前で稼働させるには何が必要かという観点から調べてみた。

pbr.jpg

PBR Material

glTF でもおなじみの最近のフォトリアルマテリアルのデファクトです。

albedo, normal, metallic, roughness(smoothness), ambient occlusionの5つのテクスチャーを持つ。

property channel
albedo RGB
normal RGB
metallic float
roughness float
ambient occlusion float

metallic, roughness, ambient occlusion は grayscale なので1枚のテクスチャーにまとめられる。

PBR Shader

vertex shader

シンプル。特に変わったことはしていない。

gl_Position =  projection * view * vec4(WorldPos, 1.0);

fragment shader

8つのテクスチャーを使う。

// material parameters
uniform sampler2D albedoMap;
uniform sampler2D normalMap;
uniform sampler2D metallicMap;
uniform sampler2D roughnessMap;
uniform sampler2D aoMap;

// IBL
uniform samplerCube irradianceMap;
uniform samplerCube prefilterMap;
uniform sampler2D brdfLUT;

最初の5つは前項で触れた、 PbrMaterial のテクスチャー。
残りの3つが IBL(ImageBasedLighting) 向けのテクスチャー。

tangent uv と 法線から計算している

ibl_specular_textured.cpp

IBL向けのテクスチャー事前生成

IBL に使用する3つのテクスチャーは、プログラム開始時に生成する。
irradianceMap と prefilterMap は hdr テクスチャーから生成する。
brdfLUT は材料は不要です。

hdr 画像から cubemap を生成する: 2.2.2.equirectangular_to_cubemap.fs

stb で esources/textures/hdr/newport_loft.hdr をロードしてテクスチャー化します。

equirectangular, GL_RGB16F

hdrTexture を元に fbo を使って cubemap envCubemap を生成します。
この envCubemap は前処理と、毎フレームの skybox 描画の両方で使います。

GL_TEXTURE_CUBE_MAP, GL_RGB16F, 512x512

cubemap から irradianceMap を生成する: 2.2.2.irradiance_convolution.fs

envCubemap を元に fbo を使って cubemap を生成します。

GL_TEXTURE_CUBE_MAP, GL_RGB16F, 32x32

cubemap から prefilterMap を生成する: 2.2.2.prefilter.fs

envCubemap を元に fbo を使って cubemap を生成します。

GL_TEXTURE_CUBE_MAP, GL_RGB16F, 128x128, mipLevel=5

bbrdfLUT(LookUpTable) を生成する: 2.2.2.brdf.vs, fs

GL_TEXTURE_2D, GL_RG16F, 512x512

skybox: 2.2.2.background.vs, fs

main loop

だいたい以下のような感じ。

    // then before rendering, configure the viewport to the original framebuffer's screen dimensions
    int scrWidth, scrHeight;
    glfwGetFramebufferSize(window, &scrWidth, &scrHeight);
    glViewport(0, 0, scrWidth, scrHeight);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// sphere0
// sphere1
// sphere2
// sphere3
// sphere4
// skybox

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

前処理 と mainloop を分ければ読みやすい

  • pbr 環境ロード、テクスチャー生成(hdr画像からcubemapなどを生成)
  • pbr Sceneロード(5つの球、Pbrマテリアルのテクスチャーロード)
  • main loop
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?