OpenGL(可编程管线):Shader + Bezier曲面 +QT

该博客介绍了如何使用OpenGL和细分着色器来绘制Bezier曲面。代码中包括了初始化数据、设置控制点、纹理加载和更新等关键步骤,同时展示了顶点着色器、细分控制着色器、细分计算着色器和片元着色器的实现细节。
摘要由CSDN通过智能技术生成

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ht巷子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值