一步步写水面渲染(三)

第九步:法线贴图

为了使海面更加有真实感,我们还要为其添加法线贴图,使其更具质感。为了保证法线方向的正确性,我们需要引入切线空间,并对于每一个三角面片计算其切线空间中的tangent和bitangent
代码如下:

void tangentandbitangent(GLint x)
{
    int x1, x2, x3;
    if (x % 2 == 0)//我绘制图像的时候使用的是GL_TRIANGLE_STRIP
    {
        x1 = x - 2;
        x2 = x - 1;
        x3 = x;
    }
    else
    {
        x1 = x - 1;
        x2 = x - 2;
        x3 = x;
    }

    vec3 pos1 = vec3(VBOdata[x1].vertex_data[0], VBOdata[x1].vertex_data[1], VBOdata[x1].vertex_data[2]);
    vec3 pos2 = vec3(VBOdata[x2].vertex_data[0], VBOdata[x2].vertex_data[1], VBOdata[x2].vertex_data[2]);
    vec3 pos3 = vec3(VBOdata[x3].vertex_data[0], VBOdata[x3].vertex_data[1], VBOdata[x3].vertex_data[2]);

    vec2 uv1 = vec2(VBOdata[x1].texcoord_data[0], VBOdata[x1].texcoord_data[1]);
    vec2 uv2 = vec2(VBOdata[x2].texcoord_data[0], VBOdata[x2].texcoord_data[1]);
    vec2 uv3 = vec2(VBOdata[x3].texcoord_data[0], VBOdata[x3].texcoord_data[1]);

    vec3 edge1 = pos2 - pos1;
    vec3 edge2 = pos3 - pos1;
    vec2 deltaUV1 = uv2 - uv1;
    vec2 deltaUV2 = uv3 - uv1;

    GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);

    vec3 tangent, bitangent;

    tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
    tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
    tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
    tangent = normalize(tangent);

    bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
    bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
    bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
    bitangent = normalize(bitangent);

    VBOdata[x1].tangents[0] = VBOdata[x2].tangents[0] = VBOdata[x3].tangents[0] = tangent.x;
    VBOdata[x1].tangents[1] = VBOdata[x2].tangents[1] = VBOdata[x3].tangents[1] = tangent.y;
    VBOdata[x1].tangents[2] = VBOdata[x2].tangents[2] = VBOdata[x3].tangents[2] = tangent.z;

    VBOdata[x1].bitangents[0] = VBOdata[x2].bitangents[0] = VBOdata[x3].bitangents[0] = bitangent.x;
    VBOdata[x1].bitangents[1] = VBOdata[x2].bitangents[1] = VBOdata[x3].bitangents[1] = bitangent.y;
    VBOdata[x1].bitangents[2] = VBOdata[x2].bitangents[2] = VBOdata[x3].bitangents[2] = bitangent.z;

}

我们需要稍微更新一下传递数据的代码:

void RenderWater()
{
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VBOdata), VBOdata, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat)));
    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(11 * sizeof(GLfloat)));

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glBindVertexArray(VAO);
    for (int c = 0; c<(STRIP_COUNT - 1); c++)
        glDrawArrays(GL_TRIANGLE_STRIP, STRIP_LENGTH * 2 * c, STRIP_LENGTH * 2);
    glBindVertexArray(0);
}

第十步:我们稍微更改一下纹理坐标,使其具有流动的感觉

if (i == 0)
            VBOdata[index].texcoord_data[0] = (pt_strip[pt * 3 + i] + glfwGetTime() / 20.0) / 10.0;
else if(i == 2)
            VBOdata[index].texcoord_data[1] = (pt_strip[pt * 3 + i] + glfwGetTime() / 20.0) / 10.0;

第十一步:更改片断着色器,使用ward各向异性光照模型(phong—blinn模型会有点屎)

#version 330 core

out vec4 FragColor;

in VS_OUT
{
    vec3 FragPos;
    vec2 TexCoords;
    vec3 TangentLightPos;
    vec3 TangentViewPos;
    vec3 TangentFragPos;
}fs_in;

uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

uniform vec4 materAmbient, materSpecular;
uniform vec4 lightDiffuse, lightAmbient, lightSpecular;
uniform vec4 envirAmbient;

void main()
{
    vec3 normal = texture(normalMap, fs_in.TexCoords).rgb;
    normal = normalize(normal * 2.0 - 1.0);                                 

    vec3 color = texture(diffuseMap, fs_in.TexCoords).rgb;

    //vec3 ambient = 0.1 * color;

    vec3 lightDir = normalize(fs_in.TangentLightPos - fs_in.TangentFragPos); 
    //float diff = max(dot(lightDir, normal), 0.0);                            
    //vec3 diffuse = diff * color;

    vec3 viewDir = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos);   
    vec3 reflectDir = normalize(reflect(-lightDir, normal));                 
    vec3 halfwayDir = normalize(lightDir + viewDir);                         
    //float spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0);               
    //vec3 specular = vec3(0.2) * spec;


    //上面被注释的代码是phong-blinn光照模型,效果非常屎,下面的则是ward各向异性光照模型
    vec4 diffuse, ambient, globalAmt;
    vec4 specular;
    float NdotL, NdotH, NdotR, S, temp, delta;
    float alpha = 0.4;

    NdotL = max(dot(normal, lightDir), 0.0);
    NdotH = max(dot(normal, halfwayDir), 0.0);
    NdotR = max(dot(normal, reflectDir), 0.0);

    delta = acos(NdotH);
    temp = -1.0 * tan(delta) * tan(delta) / alpha / alpha;
    S = pow(2.71828, temp) / 4.0 / 3.14159 / alpha / alpha / pow(NdotL * NdotR, 0.5);

    diffuse = texture2D(diffuseMap, fs_in.TexCoords) * lightDiffuse;
    globalAmt = envirAmbient * materAmbient;
    ambient = envirAmbient * lightAmbient;
    specular = materSpecular * lightSpecular;

    FragColor = NdotL * (diffuse + specular * S) + globalAmt;
}

最终结果

这里写图片描述
这里写图片描述

虽然效果还是有点屎,但是终于稍微有点海面的样子了,然而这些还是远远不够。。。。。比如水面倒影、水面折射、水面反射这些还没有进行添加,所以这只能算是我第一个半脱离教程的OpenGL代码,还需要继续努力啊。。。。。

PS:http://download.csdn.net/detail/xiewenzhao123/9770840 整个工程文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值