- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试使用 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)
- 1 displacement (height/grayscale) texture (BPP: 24 -> RGB - format: JPEG)
我使用著名且非常有用的软件“CrazyBump”来生成置换贴图。此外,该软件还可以显示视差贴图在像我这样的外部 3D 应用程序中的外观的 3D View 。
第一次,这是'CrazyBump'的显示(CrazyBump使用灯光效果,但这里不重要):
如您所见,视差效果已正确呈现。
现在这是我场景中的渲染(使用由“CrazyBump”生成的相同位移纹理,但没有亮度。我只想看到表面的假变形,如上所示)。
如您所见,显示不一样,当然也不正确。
为了尝试产生相同的效果,我应用了我在文章开头提到的 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)。
如果我按以下方式加载置换贴图 (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));
像素缓冲区开始于:
如果我按以下方式加载置换贴图 (GL_RGB):
glTexImage2D(this->m_Target, 0, GL_RGB, 这个->m_PixelData.GetWidth(), 这个->m_PixelData.GetHeight(), 0, GL_BGR, GL_UNSIGNED_BYTE, OFFSET_BUFFER(0));
像素缓冲区开始于:
在这两种情况下,我们有灰度像素。
所以我的问题似乎不是来自加载到内存中的纹理。也许矩阵有问题或空间有问题。我真的迷路了。
请问有人能帮帮我吗?
非常感谢您的帮助!
最佳答案
问题刚出线:
float HSB = Height * ScaleBias.x + ScaleBias.y;
这不是加法而是减法:
float HSB = Height * ScaleBias.x - ScaleBias.y;
截图一:
截图2:
当然,我已经为光度添加了法线贴图。
我希望这篇文章会有用!
关于opengl - 使用 OpenGL 和 GLSL 时视差贴图无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27045998/
我试图理解这两个概念。我正在阅读的手册对它们非常简短,像多 channel 算法这样的东西对我来说是新的。我想要一些示例(不是代码),说明我需要在哪里使用不变变量或精确变量,只是为了获得一个大致的想法
您好,我正在尝试获得一个快速的圆角矩形 glsl 着色器,但我只设法使用此函数( https://github.com/marklundin/glsl-sdf-primitives/blob/mast
这可能是一个简单的问题。作为 GLSL 的新手,我宁愿在这里问。 现在,在顶点着色器中,我可以通过以下方式获取世界坐标系中的位置: gl_Position = ftransform();
我想知道是否有人拥有完整、有效且高效的代码来在 glsl 中进行双三次纹理过滤。有这个: http://www.codeproject.com/Articles/236394/Bi-Cubic-and
真的有两个问题... GLSL ES 2 是完全独立的语言,还是 GLSL 的特殊版本? 在“标准库”函数、语法和功能方面,它们之间有什么区别? 我正在为一个针对 Windows、Mac 和 iPad
从GLSL文档(https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/length.xhtml)中,长度函数“计算 vector 的长度”
我想在 GLSL 着色器中实现颜色矩阵滤镜,但找不到与此相关的任何文档。我是着色器世界的新手(我自己从未编写过代码)所以如果我的解释/词汇没有意义,请原谅我。 到目前为止我可以收集到的信息: 一个颜色
我刚刚开始使用 openframeworks 中的着色器,并且正在尝试编写一个片段着色器,它根据片段的观看角度来更改片段的颜色。例如,给定一个矩形,如果从正面看(相机与法线平行)它会是红色,但如果从侧
似乎某些在 case 中具有输出的函数可能使用 if 语句作为底层实现,从而导致分支。我不认为它,但我想知道。 对于 sign(x),如果数字是正数、负数或零,则分别重新运行 1、-1 和 0。 那么
如何在 glsl 中执行位操作? 使用常规 C 风格的按位运算符 | , & , ^ , 或 !不起作用。 最佳答案 它们是在 GLSL 1.30 (OGL 3.0) 中引入的。 根据您想要做什么,您
最近我一直在玩 webGl,我偶然发现了一个很酷的小演示 here (来源 here )我想稍微改变一下以获得一些很酷的结果。 我对改变地形的生成方式很感兴趣。而不是分层 10 个 Octave
这是每个设备的事情吗?还是基于浏览器?抱歉问了这样一个基本问题,但我似乎找不到直接的答案。 最佳答案 它基于 OpenGL ES 2.0,并根据 the spec , 它必须支持 GLSL ES 版本
你如何在 GLSL 着色器中通过引用传递? 最佳答案 您可以将属性标记为 inout在函数签名中,这将使属性有效地“通过引用传递” 例如, void doSomething( vec3 trans,
我有一个浮点 RGBA 缓冲区,我想将其作为统一 Texel 缓冲区传递到我的计算着色器(用于只读访问,没有采样)。谁能告诉我如何在 GLSL 中执行此操作? 我能找到的所有示例似乎都在跳过该主题,或
我有一些参数从 CPU 传递到 GPU,这些参数对于所有片段都是恒定的,但在每一帧上都会发生变化(我使用的是 GLSL ES 1.1)。对于这些值,我应该使用制服还是属性?属性可能因顶点而异,所以我的
我已经看到这个伪随机数生成器在着色器中使用,引用here and there around the web : float rand(vec2 co){ return fract(sin(dot(
我尝试在结构内初始化数组,如下所示: struct myStruct { vec3 data[20] = vec3[20] (vec3(1, 1, 1), vec3( 1, -1, 1), v
我尝试在结构内初始化数组,如下所示: struct myStruct { vec3 data[20] = vec3[20] (vec3(1, 1, 1), vec3( 1, -1, 1), v
在 GLSL 着色器中,出于各种原因,我经常需要几个函数来修改单个值(例如,片段着色器使用四个函数来应用照明、纹理、镜面反射和雾化)。我可以想到至少三种方法来传递这些值进行修改: 使用 inout每个
我在 SL 引用中搜索了“copy”,但找不到任何相关内容。 如果我有: float a[3] = float[3] (1.0,2.0,3.0); float b[3] = a; 是 b现在指向 a
我是一名优秀的程序员,十分优秀!