Bezier曲面前面的博客已经介绍,本次绘制Bezier曲面使用了细分着色器
直接上代码
#pragma once
#include <vector>
#include <qopenglfunctions_4_4_core.h>
#include <iostream>
#include <qmatrix4x4.h>
#include "Shader.h"
#include <string>
using namespace std;
class BezierSurface
{
private:
//控制点
vector<float> controlPoints;
//VAO和VBO
unsigned int VAO, VBO;
QOpenGLFunctions_4_4_Core* core;
//着色器
Shader shader;
//纹理路径
char* texturePath;
public:
//纹理
unsigned int flowertexture;
//管理VBO空间的指针
void* ptr;
public:
//初始化数据
void initBezier();
//绘制曲面
void drawBezier(QMatrix4x4 projection, QMatrix4x4 view, QMatrix4x4 model, string type);
//获取控制点
vector<float> getControlPoints();
//设置控制点
void setControlPoints(vector<float> controlPoints);
void setCore(QOpenGLFunctions_4_4_Core* &core);
//更新数据
void updatePos(vector<float> controlPoints);
//设置纹理文件的路径
void setTexturePath(char* texturePath);
};
#include "BezierSurface.h"
#include "Utils.h"
void BezierSurface::initBezier()
{
shader = Shader("bezier.vert", "bezier.frag", nullptr, "bezier.tesc", "bezier.tese");
//load vertex
core->glGenVertexArrays(1, &VAO);
core->glGenBuffers(1, &VBO);
core->glBindVertexArray(VAO);
core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
core->glBufferData(GL_ARRAY_BUFFER, 48 * 4, nullptr, GL_STATIC_DRAW);
core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
core->glEnableVertexAttribArray(0);
//load texture
flowertexture = loadTexture(texturePath);
}
void BezierSurface::drawBezier(QMatrix4x4 projection, QMatrix4x4 view, QMatrix4x4 model, string type)
{
core->glBindVertexArray(VAO);
shader.use();
shader.setMat4("view", view);
shader.setMat4("projection", projection);
core->glBindVertexArray(VAO);
//active texture
core->glActiveTexture(GL_TEXTURE0);
core->glBindTexture(GL_TEXTURE_2D, flowertexture);
core->glPatchParameteri(GL_PATCH_VERTICES, 16);
model.scale(0.05);
model.rotate(180.0f, QVector3D(0, 0, 1.0));
model.translate(QVector3D(2.3f, -2.3f, 0.0));
model.rotate(90.0f, QVector3D(0, 0, 1.0));
shader.setMat4("model", model);
core->glDrawArrays(GL_PATCHES, 0, 16);
}
vector<float> BezierSurface::getControlPoints()
{
return controlPoints;
}
void BezierSurface::setControlPoints(vector<float> controlPoints)
{
this->controlPoints = controlPoints;
}
void BezierSurface::setCore(QOpenGLFunctions_4_4_Core* &core)
{
this->core = core;
}
void BezierSurface::updatePos(vector<float> points)
{
core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
ptr = core->glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
memcpy(ptr, points.data(), points.size() * 4);
if (core->glUnmapBuffer(GL_ARRAY_BUFFER) != GL_TRUE)
{
cout << "update pos failed" << endl;
}
}
void BezierSurface::setTexturePath(char* texturePath)
{
this->texturePath = texturePath;
}
顶点着色器
#version 440 core
layout(location = 0) in vec3 aPos;
out vec2 TexCoords;
void main()
{
TexCoords = vec2((aPos.x + 1) / 2.0, (aPos.z + 1.0) / 2);
gl_Position = vec4(aPos, 1.0);
}
细分控制着色器
#version 440 core
layout(vertices = 16) out;
in vec2 TexCoords[];
out vec2 tesc_TexCoords[];
void main()
{
int TL = 32;
if (gl_InvocationID ==0)
{ gl_TessLevelOuter[0] = TL;
gl_TessLevelOuter[2] = TL;
gl_TessLevelOuter[1] = TL;
gl_TessLevelOuter[3] = TL;
gl_TessLevelInner[0] = TL;
gl_TessLevelInner[1] = TL;
}
tesc_TexCoords[gl_InvocationID] = TexCoords[gl_InvocationID];
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
细分计算着色器
#version 440 core
layout(quads, equal_spacing, ccw) in;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
in vec2 tesc_TexCoords[];
out vec2 tese_TexCoords;
void main()
{
vec3 p00 = (gl_in[0].gl_Position).xyz;
vec3 p10 = (gl_in[1].gl_Position).xyz;
vec3 p20 = (gl_in[2].gl_Position).xyz;
vec3 p30 = (gl_in[3].gl_Position).xyz;
vec3 p01 = (gl_in[4].gl_Position).xyz;
vec3 p11 = (gl_in[5].gl_Position).xyz;
vec3 p21 = (gl_in[6].gl_Position).xyz;
vec3 p31 = (gl_in[7].gl_Position).xyz;
vec3 p02 = (gl_in[8].gl_Position).xyz;
vec3 p12 = (gl_in[9].gl_Position).xyz;
vec3 p22 = (gl_in[10].gl_Position).xyz;
vec3 p32 = (gl_in[11].gl_Position).xyz;
vec3 p03 = (gl_in[12].gl_Position).xyz;
vec3 p13 = (gl_in[13].gl_Position).xyz;
vec3 p23 = (gl_in[14].gl_Position).xyz;
vec3 p33 = (gl_in[15].gl_Position).xyz;
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
float bu0 = (1.0-u) * (1.0-u) * (1.0-u);
float bu1 = (3.0 * u * (1.0 - u) * (1.0-u));
float bu2 = 3.0 * u * u * (1.0-u);
float bu3 = u * u * u;
float bv0 = (1.0 - v) * (1.0 - v) * (1.0 - v);
float bv1 = 3.0 * v * (1.0-v) * (1.0-v);
float bv2 = 3.0 * v * v * (1.0-v);
float bv3 = v * v * v;
vec3 outputPos = bu0 * (bv0*p00 + bv1*p01 + bv2*p02 + bv3*p03)
+ bu1 * (bv0*p10 + bv1*p11 + bv2*p12 + bv3*p13)
+ bu2 * (bv0*p20 + bv1*p21 + bv2*p22 + bv3*p23)
+ bu3 * (bv0*p30 + bv1*p31 + bv2*p32 + bv3*p33);
gl_Position = projection * view * model * vec4(outputPos, 1.0f);
//vec2 tc1 = mix(tesc_TexCoords[0], tesc_TexCoords[3], gl_TessCoord.x);
//vec2 tc2 = mix(tesc_TexCoords[12], tesc_TexCoords[15], gl_TessCoord.x);
//vec2 tc = mix(tc2, tc1, gl_TessCoord.y);
tese_TexCoords = vec2(u, v);
}
片元着色器
#version 440 core
out vec4 FragColor;
in vec2 tese_TexCoords;
struct Material{
//漫反射
sampler2D diffuse;
//镜面光
sampler2D specular;
float shinines;
};
//pointLight
struct PointLight{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant; //常数项
float linear; //一次项
float quadratic; //二次项
};
//材质
uniform Material material;
//灯光
uniform PointLight pointLights[4];
vec3 CalPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
uniform sampler2D texture1;
void main()
{
//FragColor = vec4(1.0f, 0.0, 0.0, 1.0f);
FragColor = texture(texture1, tese_TexCoords);
}
vec3 CalPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
//漫反射
float diff = max(dot(normal, lightDir), 0.0);
//镜面反光
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shinines);
//衰减
float distan = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distan + light.quadratic * distan * distan);
//合并结果
vec3 ambient = light.ambient * vec3(texture(material.diffuse, tese_TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, tese_TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, tese_TexCoords));
return (ambient + diffuse + specular) * attenuation;
}