0

我正在尝试对我的着色器实现法线映射,但我不断得到奇怪的结果。
我已经实现了漫反射和镜面光(它们正在工作)。我首先从法线贴图计算归一化向量:Ni = 2 * normalColor - 1 然后通过法线和切线的交叉向量计算副法线向量。
最后,我通过转置(正切、副法线、法线)创建了 TBN 矩阵

这是我的代码和一些屏幕截图。

顶点着色器

#version 330

// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
in vec4 vertexTangent;

// Input uniform values
uniform mat4 mvp;

// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragPosition;
out vec4 fragTangent;
out vec3 fragNormal;
// out vec3 fragBiTangent;


// NOTE: Add here your custom variables

void main()
{
    // Send vertex attributes to fragment shader
    fragTexCoord = vertexTexCoord;
    fragColor = vertexColor;
    //added
    fragNormal = vertexNormal;
    fragPosition = vertexPosition;
    fragTangent = vertexTangent;


    // Calculate final vertex position
    gl_Position = mvp*vec4(vertexPosition, 1.0);
}

片段着色器

#version 330

// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragNormal;
in vec3 fragPosition;
in vec4 fragTangent;

// Input uniform values
uniform sampler2D texture0;     // diffuse texture
uniform vec4 colDiffuse;
uniform vec3 lightPos;          // light position
uniform mat4 matModel;          // pos, rotation and scaling of object
uniform vec3 viewPos;           // eyes position
uniform sampler2D normalMap;    // normal texture


// Output fragment color
out vec4 finalColor;

// NOTE: Add here your custom variables
vec3 unHomogenous(vec4 v)
{
    return v.xyz/v.w;
}

void main()
{
    //=====================LOAD TEXTURES=============================

    // Texel color fetching from texture sampler
    vec4 texelColor = texture(texture0, fragTexCoord);

    // obtain normal from normal map in range [0,1]
    vec3 normalColor = texture(normalMap, fragTexCoord).xyz;
    

    //=======================PARAMETERS==============================

    // calculate normal in world coordinates
    mat3 matNormal = transpose(inverse(mat3(matModel)));    //CPU heavy
    vec3 worldNormal = normalize(matNormal * fragNormal);

    // Calculate the location of this fragment (pixel) in world coordinates
    vec3 worldPosition = unHomogenous(matModel * vec4(fragPosition, 1.0));

    //=======================NORMAL MAPPING========================

    // transform normal vector to range [-1,1]
    vec3 normal = normalize(normalColor * 2.0 - 1.0); 

    normal = normalize(matNormal * normal);
    vec3 tangent = normalize(matNormal * fragTangent.xyz);
    vec3 binormal = normalize(cross(normal, tangent));

    mat3 TBN = mat3(tangent, binormal, worldNormal);
    TBN = transpose(TBN);
    
  

    //=======================DIFFUSING LIGHT===========================

    // Shading is calculated by diffuse = (LightVect dot NormalVect) * Diffused color  

    vec3 ambiant = 0.01 * texelColor.xyz ;

    // find light source : L = Lightposition - surfacePosition
    vec3 lightDir = normalize(lightPos - worldPosition);
    lightDir *= TBN; // NOT WORKING

    // diffuse the light with the dot matrix :
    float shading = clamp(dot(worldNormal, lightDir), 0.1, 1.0);
    vec3 diffuse = shading * texelColor.xyz;

    //=======================SPECULAR LIGHTNING====================

    //intensity between 0 and 1
    float specularStrength = 1;
    
    // //calculate the view direction vector and corresponding reflect vector along the normal axis
    vec3 viewDir = normalize(viewPos - worldPosition);
    viewDir *= TBN; // NOT WORKING

    vec3 reflectDir = reflect(-lightDir, worldNormal);  
    //Note that we negate the lightDir vector. 
    //The reflect function expects the first vector to point from the light source towards the fragment's position, 
    //but the lightDir vector is currently pointing the other way 
    

    // calclulate the specula component 32 is the shininess value of the highlight
    int shininess = 32;
    float spec = pow(clamp(dot(viewDir, reflectDir), 0.1, 1.0), shininess);

    vec3 lightColor = vec3(1.0,1.0,1.0);
    vec3 specular = specularStrength * spec * texelColor.xyz; 

    

    //=======================RENDER================================
    finalColor = vec4(ambiant + diffuse + specular, 1.0);

}

主文件

#include "raylib.h"
#include "rlgl.h"
#include <math.h>  
#include <raymath.h>

int main(void)
{
    // Initialization
    //[...]
    //=====================WALL=======================//

    Vector3 position = { -2.5f, 3.0f, 0.0f };

    Model model = LoadModel("assets/models/wall.obj");
    Texture2D texture = LoadTexture("assets/textures/cgaxis_pbr_17_stone_wall_5_diffuse.png");
    
    // Set normal mapping
    Texture2D normal_texture = LoadTexture("assets/textures/cgaxis_pbr_17_stone_wall_5_normal.png");

    model.materials[0].maps[MATERIAL_MAP_NORMAL].texture = normal_texture;
    //==========Generate mesh and diffuse texture=========//

    GenMeshTangents(model.meshes);   
    
    model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;            // Set map diffuse texture

   
    //===================SELECT SHADERS====================//

    // Shader shader = LoadShader("assets/shaders/base.vs", "assets/shaders/base.fs");                             // diffuse light
    // Shader shader = LoadShader("assets/shaders/specular.vs", "assets/shaders/specular.fs");                  // diff + specular
    Shader shader = LoadShader("assets/shaders/normal_mapping.vs", "assets/shaders/normal_mapping.fs");      // diff + spec + normal mapping

    // Set shader effect to 3d model
    model.materials[0].shader = shader;  

    //==================Light======================//

    Vector3 sunPos = {0.0f, 2.0f, 0.0f };
    float rotation = 90.0f;
    float radius = 5.0f;

    // Diffuse light
    int lightPosLoc = GetShaderLocation(shader, "lightPos");
    float lightPos[] = {sunPos.x, sunPos.y, sunPos.z};
    SetShaderValue(shader, lightPosLoc, lightPos, SHADER_UNIFORM_VEC3);
    
    //specular light
    int specularPosLoc = GetShaderLocation(shader, "viewPos");
    float specularPos[] = {camera.position.x, camera.position.y, camera.position.z};
    SetShaderValue(shader, specularPosLoc, specularPos, SHADER_UNIFORM_VEC3);


    //RUN & draw
    //[...]
    // De-Initialization
    //--------------------------------------------------------------------------------------
    CloseWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

漫反射 + 镜面反射 漫射光和镜面光

法线映射 添加了法线贴图

4

0 回答 0