首页 > 学院 > 开发设计 > 正文

一步步写水面渲染(三)

2019-11-06 07:16:20
字体:
来源:转载
供稿:网友

第九步:法线贴图

为了使海面更加有真实感,我们还要为其添加法线贴图,使其更具质感。为了保证法线方向的正确性,我们需要引入切线空间,并对于每一个三角面片计算其切线空间中的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 coreout 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 整个工程文件


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表