简体   繁体   English

如何在OpenGL中应用法线贴图?

[英]How to apply a normal map in OpenGL?

I'm learning to use normal maps (per pixel lighting?) in 2D graphics with OpenGL. 我正在学习使用OpenGL在2D图形中使用法线贴图(每像素光照?)。

New to normal mapping, I managed to wrap my head around the Sobel operator and the generation of normal maps (mostly thanks to this ), that is creating a (2D) array of normals from a (2D) array of pixel data. 作为法线贴图的新手,我设法绕过Sobel算子并生成法线贴图(主要归功于 ),即从(2D)像素数据阵列创建(2D)法线阵列。

(Most of the tutorials and forum threads that I have found were specific to 3D uses and modelling software. I aim to implement this functionality myself, in C++.) (我发现的大多数教程和论坛主题都是针对3D使用和建模软件的。我的目标是在C ++中自己实现这个功能。)

  • What do I do once I've got the normal map? 一旦我得到了正常的地图,我该怎么办?
  • Do I need to register it with OpenGL? 我需要在OpenGL中注册吗?
  • Does it need to be associated with the texture, if yes, how is it done? 它是否需要与纹理相关联,如果是,它是如何完成的?
  • How is it mapped to a 2D textured quad? 它是如何映射到2D纹理四边形的?
  • (Is this something that I can do without shaders / GLSL?) (这是我可以在没有着色器/ GLSL的情况下做的事吗?)

I recommend you look at: 我建议你看看:

This nvidia presentation on bumb mapping 关于bumb映射的这个nvidia演示文稿

I haven't looked at this for a while, but I remember it going over most of the details in implementing a bump map shader, should get a few ideas running. 我暂时没有看过这个问题,但是我记得它在实现凹凸贴图着色器时会考虑大部分细节,应该会有一些想法在运行。

This other nvidia tutorial for implementing bump mapping in the cg shader langauge 这个用于在cg着色器语言中实现凹凸贴图的其他nvidia教程

This bump mapping tutorial might also be helpful . 凹凸贴图教程也可能有所帮助

I know all these are not for full normal mapping but they're a good start. 我知道所有这些都不是完全正常的映射,但它们是一个良好的开端。

Also, while there are differences in shader languages it shouldn't be to hard to convert formulers between them if you want to use GLSL. 此外,虽然着色器语言存在差异,但如果您想使用GLSL,则不应该很难在它们之间转换制表器。

As ybungalobill said, you can do it without shaders but unless you are working on an educational project (for your education) or a particular embedded device, I have no idea why the hell you would want to - but if you do need to this is where you want to look, it was written before shaders, and updated to reference them later. 正如ybungalobill所说,你可以在没有着色器的情况下完成它,但除非你正在从事一个教育项目(为了你的教育)或一个特定的嵌入式设备,我不知道为什么你想要的 - 但如果你确实需要这个是你想看的地方,它是在着色器之前写的,并且更新后再引用它们。

  • What do I do once I've got the normal map? 一旦我得到了正常的地图,我该怎么办?
  • Do I need to register it with OpenGL? 我需要在OpenGL中注册吗?

Yes, you need to load it as a texture. 是的,您需要将其作为纹理加载。

  • Does it need to be associated with the texture, if yes, how is it done? 它是否需要与纹理相关联,如果是,它是如何完成的?

If you mean associated with the color texture, then no. 如果你的意思是与颜色纹理相关联,那么没有。 You need to create a texture that holds the normal map in order to use it later with OpenGl. 您需要创建一个包含法线贴图的纹理,以便稍后在OpenGl中使用它。

  • How is it mapped to a 2D textured quad? 它是如何映射到2D纹理四边形的?

Your normal map is just another texture, you bind it and map as any other texture. 你的法线贴图只是另一个贴图,你将它绑定并映射为任何其他纹理。

Normal map stores the normals in tangent space coordinates, so to calculate the lighting per pixel you need to know the relative position of the light source in tangent space coordinate system. 法线贴图将法线存储在切线空间坐标中,因此要计算每个像素的光照,您需要知道光源在切线空间坐标系中的相对位置。 This is done by setting additional parameters per vertex (normal, tangent, binormal), calculating the light-source position in tangent space coordinates and interpolating this position along the triangles. 这是通过为每个顶点设置附加参数(法线,切线,副法线),计算切线空间坐标中的光源位置并沿三角形插入此位置来完成的。 In the fragment shader you lookup the normal in the normal map and perform the desired lighting calculation based on the interpolated parameters. 在片段着色器中,您可以在法线贴图中查找法线,并根据插值参数执行所需的光照计算。

  • (Is this something that I can do without shaders / GLSL?) (这是我可以在没有着色器/ GLSL的情况下做的事吗?)

Yes, you can use some legacy extensions to program the multi-texture environment combination functions. 是的,您可以使用一些旧版扩展来编程多纹理环境组合功能。 Never done it myself but it looks like hell. 从来没有自己做过,但它看起来像地狱。

the topic is quite old,but I'll answer it for any beginner who could seek any help here: 这个话题已经很老了,但我会为任何能在这里寻求帮助的初学者回答这个问题:

1) & 2) 1)&2)

your normal map is like a regular diffuse texture,you need to load it from the disk,create your texture2D like you would do with diffuse texture,and lock it with the other textures to send it to the shaders. 你的法线贴图就像一个普通的漫反射贴图,你需要从磁盘加载它,像漫反射纹理一样创建texture2D,并用其他纹理锁定它以将其发送到着色器。 So to sum it up,normal maps,height maps,etc are not different when you deal with them CPU side...it's always loading them,creating the texture,and locking them. 总而言之,法线贴图,高度贴图等在处理CPU端时并没有什么不同......它总是加载它们,创建纹理并锁定它们。

3) 3)

Normal maps are just a way to store normals of every fragment in a texture. 法线贴图只是存储纹理中每个片段的法线的一种方法。 It's better to use them with the corresponding diffuse texture,because that's the way you can fake the little details. 最好将它们与相应的漫反射纹理一起使用,因为这是你伪造细节的方式。 Nevertheless, it's not always necessary in some cases...for example, last time I was working on a way to render water...I used a dudv map,and a normal map,but not the corresponding diffuse map,as I used to render into textures to achieve the reflection. 然而,在某些情况下并不总是必要的......例如,上次我正在研究渲染水的方法......我使用了dudv地图和法线贴图,但没有像我使用的那样使用相应的漫反射贴图渲染到纹理以实现反射。

4) 4)

normal maps are mapped with the same texture coordinates as the diffuse texture... it means that if you have a quad wich coordinates are 0;0 , 0;1 , 1;0 , 1;1 these are the coordinates you use to map both textures. 法线贴图使用与漫反射贴图相同的纹理坐标进行映射...这意味着如果你有一个四边形坐标是0; 0,0; ​​1,1; 0,1; 1这些是你用来映射的坐标两种纹理。

5) 5)

you could do it without shaders,I guess...you can even do it without OpenGL if you want...shaders are designed for these kind of operations,and it will be easier to do that with shaders. 你可以在没有着色器的情况下做到这一点,我想......你甚至可以在没有OpenGL的情况下做到这一点,如果你想要...着色器是为这类操作而设计的,并且使用着色器更容易做到这一点。

So,normal maps are textures that encode normal vectors into colors... a normal vector is a 3D vector , and colors are 3D vectors too. 因此,法线贴图是将法线矢量编码为颜色的纹理...法线矢量是3D矢量,颜色也是3D矢量。 When you use lighting,you usually send your normals from the vertex shader to the fragment shader...the fragment shader will interpolate the value of the vertex normal to find out an approximation of the pixel's own normal vector. 当您使用光照时,通常将法线从顶点着色器发送到片段着色器...片段着色器将插入顶点法线的值以找出像素自身法线向量的近似值。 this is done by default... 这是默认完成的......

With normal maps,you don't use a vertex normal vector,but the normal vector encoded in the texture. 对于法线贴图,您不使用顶点法线向量,而是使用纹理中编码的法线向量。

First,you'll have to convert the lighting calculation from world space into tangent space.that's done in the vertex shader. 首先,您必须将照明计算从世界空间转换为切线空间。这是在顶点着色器中完成的。

then,you will sample your normal map in the fragment shader like a usual texture.You will get an RGB color of your pixel. 然后,您将在片段着色器中像普通纹理一样对法线贴图进行采样。您将获得像素的RGB颜色。 you will have to convert that value into a normal vector,ie,multiply it by 2 and subtract 1 ,ie ,rgb*2 - 1,then use it as your normal vector in lighting calculation. 你必须将该值转换为法线向量,即将其乘以2并减去1,即rgb * 2 - 1,然后将其用作照明计算中的法线向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM