opengl - 使用 OpenGL 和 GLSL 时视差贴图无法正常工作

标签 opengl glsl opengl-es-2.0 opengl-4 glsles

我尝试使用 OpenGL 和 GLSL API 在我的 3D 引擎中实现视差映射,但显示不正确。为了学习和应用这种技术的复杂性,我受到以下 PDF 教程(第 16、17 和 18 页)的启发:

https://www.opengl.org/sdk/docs/tutorials/TyphoonLabs/Chapter_4.pdf

要产生非常基本的视差效果(没有任何光照效果),我需要使用 2 个纹理:

- 1 diffuse (color) texture (BPP: 24 -> RGB - format: JPEG)

enter image description here

- 1 displacement (height/grayscale) texture (BPP: 24 -> RGB - format: JPEG)

enter image description here

我使用著名且非常有用的软件“CrazyBump”来生成置换贴图。此外,该软件还可以显示视差贴图在像我这样的外部 3D 应用程序中的外观的 3D View 。

第一次,这是'CrazyBump'的显示(CrazyBump使用灯光效果,但这里不重要):

enter image description here

如您所见,视差效果已正确呈现。

现在这是我场景中的渲染(使用由“CrazyBump”生成的相同位移纹理,但没有亮度。我只想看到表面的假变形,如上所示)。

enter image description here

如您所见,显示不一样,当然也不正确。

为了尝试产生相同的效果,我应用了我在文章开头提到的 PDF 文件中的类(class)。

有关信息,我之前已经为我的引擎实现了“法线映射”技术(因此切线和副切线向量是正确的!)。

要执行我的着色器程序,我需要相机在世界空间和矩阵(ModelViewProj、ModelMatrix 和 NormalMatrix)中的位置。

这是我使用的客户端 C++ 代码:

glm::mat4 modelViewMatrix = pRenderBatch->GetModelViewMatrix();

glm::mat3 normalMatrix = glm::mat3(glm::vec3(modelViewMatrix[0]),
    glm::vec3(modelViewMatrix[1]), glm::vec3(modelViewMatrix[2]));

this->SetUniform("ModelViewProjMatrix", pRenderBatch->GetModelViewProjMatrix());
this->SetUniform("ModelViewMatrix", modelViewMatrix);
this->SetUniform("NormalMatrix", normalMatrix);

//Bound on channel 0
glActiveTexture(GL_TEXTURE0);
this->m_pTextureManager.PushAndBindTexture(
    pMaterial->GetDiffuseTexture());
{
    this->SetUniform("DiffuseSampler", 0);
}
//Bound on channel 1
glActiveTexture(GL_TEXTURE1);
    this->m_pTextureManager.PushAndBindTexture(
        pMaterial->GetDisplacementTexture());
{
    this->SetUniform("HeightSampler", 1);
}

顶点着色器:

#version 440

/*
** Vertex attributes.
*/
layout (location = 0) in vec4 VertexPosition;
layout (location = 1) in vec2 VertexTexture;
layout (location = 2) in vec3 VertexNormal;
layout (location = 3) in vec3 VertexTangent;
layout (location = 4) in vec3 VertexBitangent;

/*
** Uniform matrices.
*/
uniform mat4 ModelViewProjMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;

//Outputs
out vec2 TexCoords;
out vec3 viewDir_TS;

/*
** Vertex shader entry point.
*/
void main(void)
{
    //Texture coordinates
    TexCoords = VertexTexture;

    //Vertex position in world space
    vec3 Position_CS = vec3(ModelViewMatrix * VertexPosition);
    //Vertex normal in world space
    vec3 Normal_CS = NormalMatrix * VertexNormal;
    //Vertex tangent in world space
    vec3 Tangent_CS = NormalMatrix * VertexTangent;
    //Vertex bitangent in world space
    vec3 Bitangent_CS = NormalMatrix * VertexBitangent;

    //View vector in world space
    vec3 viewDir_CS = -Position_CS;

    //TBN matrix
    mat3 TBN =  mat3(
        Tangent_CS.x, Bitangent_CS.x, Normal_CS.x,
        Tangent_CS.y, Bitangent_CS.y, Normal_CS.y,
        Tangent_CS.z, Bitangent_CS.z, Normal_CS.z);

    //2 others ways to compute view vector in tangent space

        //mat3 TBN = transpose(mat3(Tangent_CS, Bitangent_CS, Normal_CS));

        /*viewDir_TS = vec3(
            dot(viewDir_CS, Tangent_CS),
            dot(viewDir_CS, Bitangent_CS),
            dot(viewDir_CS, Normal_CS)
        );*/

    //View vector converted in tangent space (not normalized)
    viewDir_TS = TBN * viewDir_CS;

    gl_Position = ModelViewProjMatrix * VertexPosition;
}

最后是片段着色器:

#version 440

layout (location = 0) out vec4 FragColor;

//Texture coordinates
in vec2 TexCoords;

//View (camera) vector in tangent space
in vec3 viewDir_TS;

//Diffuse texture sampler
uniform sampler2D DiffuseSampler;
//Displacement texture sampler
//(height map/grayscale map)
uniform sampler2D HeightSampler;

/*
** Fragment shader entry point
*/
void main(void)
{
    //Parralax intensity {scale(s), bias(b)}
    vec2 ScaleBias = vec2(0.04f, 0.02f);

    //Height(h) range [0;1] (float) recovered from height map (HeightSampler)
    float Height = texture2D(HeightSampler, TexCoords.st).r; 

    //Height scaled and biased according to the formula: hsb = h · s + b
    float HSB = Height * ScaleBias.x + ScaleBias.y;

    //View vector in tangent space normalized
    vec3 viewDirNorm_TS = normalize(viewDir_TS);

    //Computes texture offset according to the formula: Tn = To + (hsb · V{x, y}) 
    vec2 textOffset = TexCoords + (viewDirNorm_TS.xy * HSB);

    //Computes final diffuse texture color using parralax offset
    FragColor = texture2D(DiffuseSampler, textOffset);
}

我尝试修改比例和偏差值但没有成功:显示仍然不正确。

我以为我的置换纹理没有正确加载,但事实并非如此(为了获得信息,我使用了 NVIDIA NSight degugger)。

enter image description here

如果我按以下方式加载置换贴图 (GL_LUMINANCE):

glTexImage2D(this->m_Target, 0, GL_LUMINANCE,
    this->m_PixelData.GetWidth(), this->m_PixelData.GetHeight(),
            0, GL_BGR, GL_UNSIGNED_BYTE, OFFSET_BUFFER(0));

像素缓冲区开始于:

enter image description here

如果我按以下方式加载置换贴图 (GL_RGB):

glTexImage2D(this->m_Target, 0, GL_RGB, 这个->m_PixelData.GetWidth(), 这个->m_PixelData.GetHeight(), 0, GL_BGR, GL_UNSIGNED_BYTE, OFFSET_BUFFER(0));

像素缓冲区开始于:

enter image description here

在这两种情况下,我们有灰度像素。

所以我的问题似乎不是来自加载到内存中的纹理。也许矩阵有问题或空间有问题。我真的迷路了。

请问有人能帮帮我吗?

非常感谢您的帮助!

最佳答案

问题刚出线:

float HSB = Height * ScaleBias.x + ScaleBias.y;

这不是加法而是减法:

float HSB = Height * ScaleBias.x - ScaleBias.y;

截图一:

enter image description here

截图2:

enter image description here

当然,我已经为光度添加了法线贴图。

我希望这篇文章会有用!

关于opengl - 使用 OpenGL 和 GLSL 时视差贴图无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27045998/

相关文章:

android - OpenGL ES 2.0 指定位置属性 vec3 或 vec4

c++ - 向不可变纹理存储提供数据

OpenGL 缓冲区、glFlush 和 glutSwapBuffers()

c++ - 使用着色器绘制 3D 对象的正确方法是什么?

glsl - 如何确定性地检测着色器片段在其 2x2 像素四边形中的位置?

java - OpenGL ES 2.0 - 渲染到纹理全黑

python - 如何使用 Pyglet 创建 OpenGL 3.0 上下文

java - libGDX 中的枚举出现 ExceptionInInitializerError

opengl - HLSL:预定义变量

opengl - 每次调用 glBindBuffer 时都需要 glVertexAttribPointer 吗?