当前位置: 首页 > article >正文

【OpenGL/Assimp】渲染模型、半透明材质与封装光源

文章目录

    • 渲染成果
    • Assimp库准备:
    • Mesh类修改:
    • 透明贴图使用:
    • 光源封装:
    • 使用方式在如下测试环境中:

渲染成果

在这里插入图片描述

Assimp库准备:

从GitHub拉取源码,根据网络教程,借助CMake生成VS工程项目,并用VS将其编译为静态链接库(lib)或动态链接库(dll + lib)。最后将其库文件和工程内的include文件复制到图形工程下。

Mesh类修改:

在抽象Model,Mesh这些类时,我改动LearnOpenGL的最大的类是Mesh类,将其直接使用的GLAPI替换成了封装好的API,类如下。修改的数据结构在Model中修改相应的数据存放方法即可

//Mesh.h

#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>

#include <vector>

#include "Shader.h"
#include "VertexArray.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
#include "IndexBuffer.h"
#include "Texture.h"

using namespace std;

struct Vertex
{
    glm::vec3 Position;
    glm::vec3 Normal;
    glm::vec2 TexCoords;
};

struct TextureData
{
    string name;
    Texture* texture;
};

class Mesh
{
public:
    vector<Vertex> vertices;
    vector<GLuint> indices;
    vector<TextureData> textures;

    Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<TextureData> textures);
    void Draw(Renderer& renderer, Shader& shader);


private:
    VertexArray VAO;
    VertexBuffer VBO;
    IndexBuffer EBO;

    void setupMesh();
};
    
    
//Mesh.cpp
#include "Mesh.h"


Mesh::Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<TextureData> textures)
{
    this->vertices = vertices;
    this->indices = indices;
    this->textures = textures;

    this->setupMesh();             
}

void Mesh::setupMesh()
{
    VAO.Bind();
    VBO.Init(&vertices[0], vertices.size() * sizeof(Vertex));
    EBO.Init(&indices[0], indices.size());
    VAO.AddVertexBuffer(VBO);
    VAO.Unbind();
}

void Mesh::Draw(Renderer& renderer, Shader& shader)
{
    for (int i = 0; i < textures.size(); i++)
    {
        textures[i].texture->Bind(i);
        shader.SetUniform1i(textures[i].name, i);
    }

    renderer.Draw(VAO, EBO, shader);
}

透明贴图使用:

我所需要绘制的模型有半透明的面部贴图,因此需要使用透明度,这里需要注意的是,如果所有使用数据获取数据的地方都没有出错但仍没有透明效果,可以检查原始数据的问题,如图片本身的透明效果,在工程中加载图片时是否包含透明通道。

//shader
void main()
{
    vec3 norm = normalize(Normal);
    vec3 viewDir = normalize(viewPos - FragPos);

    //透明测试
    vec4 texColor = texture(texture_diffuse, TexCoords);
    if(texColor.a < 0.2 && mixFactor == 0)
        discard;

    //光照着色
    color = vec4(CalcPointLight(light, norm, FragPos, viewDir), 1);
}

光源封装:

每次使用光源需要大段的赋值语句,因此对其进行简单封装,目前只封装了点光源

//Light.h

#pragma once
#include <iostream>
#include <glm/glm.hpp>

#include "Shader.h"

using namespace std;

class Light
{
public:
	Light(
		glm::vec3 position = { 1.2f, 1.0f, 2.0f }, 
		glm::vec3 ambient = { 0.4, 0.4, 0.4 },
		glm::vec3 diffuse = { 1.2, 1.2, 1.2 },
		glm::vec3 specular = { 0.1, 0.1, 0.1 },
		float constant = 1, 
		float linear = 0.09, 
		float quadratic = 0.032);

	void SetupShader(Shader& shader, string lightName);

private:
	glm::vec3 m_Position;
	glm::vec3 m_Ambient;
	glm::vec3 m_Diffuse;
	glm::vec3 m_Specular;
	float m_Constant;
	float m_Linear;
	float m_Quadratic;
};


//Light.cpp
#include "Light.h"

Light::Light(glm::vec3 position, glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 specular, float constant, float linear, float quadratic)
{
	m_Position = position;
	m_Ambient = ambient;
	m_Diffuse = diffuse;
	m_Specular = specular;
	m_Constant = constant;
	m_Linear = linear;
	m_Quadratic = quadratic;
}

void Light::SetupShader(Shader& shader, std::string lightName)
{
	shader.SetUniform3f(lightName + ".position", m_Position.x, m_Position.y, m_Position.z);
	shader.SetUniform3f(lightName + ".ambient", m_Ambient.x, m_Ambient.y, m_Ambient.z);
	shader.SetUniform3f(lightName + ".diffuse", m_Diffuse.x, m_Diffuse.y, m_Diffuse.z);
	shader.SetUniform3f(lightName + ".specular", m_Specular.x, m_Specular.y, m_Specular.z);
	shader.SetUniform1f(lightName + ".constant", m_Constant);
	shader.SetUniform1f(lightName + ".linear", m_Linear);
	shader.SetUniform1f(lightName + ".quadratic", m_Quadratic);
}

使用方式在如下测试环境中:

#pragma once

#include "RunBase.h"

#include "Model.h"
#include "Light.h"

#include <glm/gtc/type_ptr.hpp>

class AssimpTest : public RunBase
{
public:
	Model* body, *blue, *ear, *eye, *mao, *mouth;
	Shader diffuseShader;

	Renderer renderer;

	Light light;

	AssimpTest() : RunBase()
	{
		diffuseShader.Init("res/shaders/AssimpTest.shader");
	}

	virtual void Init(GLFWwindow* window, float targetFrameTime) override
	{
		/*GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA));
		GLCall(glEnable(GL_BLEND));*/

		body = new Model("res/models/jixuanyou/body.obj");
		blue = new Model("res/models/jixuanyou/blue.obj");
		ear = new Model("res/models/jixuanyou/ear.obj");
		eye = new Model("res/models/jixuanyou/eye.obj");
		mao = new Model("res/models/jixuanyou/mao.obj");
		mouth = new Model("res/models/jixuanyou/mouth.obj");
	}

	virtual void RenderLoop(GLFWwindow* window, float targetFrameTime) override
	{
		renderer.Clear();


		//绘制受光物体
		diffuseShader.Bind();


		//视图矩阵(透视参数)
		glm::mat4 view(1), proj(1), model(1);
		view = camera.GetViewMatrix();
		proj = glm::perspective<GLfloat>(45, 640 / 480, .1f, 100.f);


		//赋值透视
		diffuseShader.SetUniformMat4f("view", glm::value_ptr(view));
		diffuseShader.SetUniformMat4f("projection", glm::value_ptr(proj));
		diffuseShader.SetUniformMat4f("model", glm::value_ptr(model));
		//赋值光照
		light.SetupShader(diffuseShader, "light");
		//赋值视图位置
		diffuseShader.SetUniform3f("viewPos", camera.Position.x, camera.Position.y, camera.Position.z);
		diffuseShader.SetUniform1f("shininess", 4);


		// 取消纯色
		diffuseShader.SetUniform1f("mixFactor", 0);
		//不透明物件
		body->Draw(renderer, diffuseShader);
		ear->Draw(renderer, diffuseShader);
		eye->Draw(renderer, diffuseShader);
		mouth->Draw(renderer, diffuseShader);


		// 使用纯色
		diffuseShader.SetUniform1f("mixFactor", 1);
		// 浅蓝色
		diffuseShader.SetUniform3f("diffuseColor", 0.50, 0.66, 0.81);
		mao->Draw(renderer, diffuseShader);
		// 深蓝色
		diffuseShader.SetUniform3f("light.diffuse", 4, 4, 4);
		diffuseShader.SetUniform3f("light.specular", 0.5, 0.5, 0.5);
		diffuseShader.SetUniform3f("diffuseColor", 0.022, 0.06, 0.21);
		blue->Draw(renderer, diffuseShader);
	}

	virtual bool UseCameraControl() override
	{
		return true;
	}
};

http://www.kler.cn/a/503763.html

相关文章:

  • 【Docker】保姆级 docker 容器部署 MySQL 及 Navicat 远程连接
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>优美的排列
  • Angular-生命周期及钩子函数
  • 【Vue实战】Vuex 和 Axios 拦截器设置全局 Loading
  • 【微信小程序】let和const-综合实训
  • AllData是怎么样的一款数据中台产品?
  • Web开发(一)HTML5
  • Elasticsearch Python 客户端是否与自由线程 Python 兼容?
  • 关于2025年智能化招聘管理系统平台发展趋势
  • 单体 vs 微服务 怎么选?
  • springboot高校教室资源管理平台
  • 2501,wtl显示html
  • 基于springboot+vue的洪涝灾害应急信息管理系统设计与实现
  • 【蓝桥杯】Python算法——快速幂
  • Python文档生成利器 - Sphinx入门指南
  • 【JVM】深入了解Java虚拟机-------内存划分、类加载机制、垃圾回收机制
  • 【Uniapp-Vue3】页面生命周期onLoad和onReady
  • 语音合成的预训练模型
  • Linux Centos中安装多个JDK并且管理
  • 基于深度学习的视觉检测小项目(十三) 资源文件的生成和调用
  • 学习进程前的简单认知-体系结构与OS
  • Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)
  • 刷题记录 回溯算法-10:93. 复原 IP 地址
  • 如何高效使用Adobe软件的组件功能
  • OpenCV实现彩色图像的直方图均衡化
  • riscv架构下linux4.15实现early打印